Unify provider and account card UI and move setup actions to menus (#755)

* feat: add auto-open functionality for collapsible sections and streamline unlinked account handling

- Introduce `auto-open` Stimulus controller to auto-expand <details> elements based on URL params.
- Update all settings sections and panels to support the new `auto_open_param` for seamless navigation.
- Improve unlinked account logic for Coinbase, SimpleFIN, and SnapTrade, ensuring consistent and optimized handling.
- Refactor sync warnings and badges for better readability and user experience.
- Extend localization for additional menu items, warnings, and setup prompts.

* fix: improve error handling and safe HTML usage in Coinbase and settings components

- Log warning for unhandled exceptions in Coinbase unlinked account count fallback.
- Escape `auto_open_param` in settings section for safe HTML injection.
- Clean up URL params in `auto-open` controller after auto-expansion.

---------

Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
This commit is contained in:
LPW
2026-01-23 19:11:56 -05:00
committed by GitHub
parent bf3e257112
commit 8c9764f1ad
12 changed files with 173 additions and 128 deletions

View File

@@ -0,0 +1,29 @@
import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="auto-open"
// Auto-opens a <details> element based on URL param
// Use data-auto-open-param-value="paramName" to open when ?paramName=1 is in URL
export default class extends Controller {
static values = { param: String };
connect() {
if (!this.hasParamValue || !this.paramValue) return;
const params = new URLSearchParams(window.location.search);
if (params.get(this.paramValue) === "1") {
this.element.open = true;
// Clean up the URL param after opening
params.delete(this.paramValue);
const newUrl = params.toString()
? `${window.location.pathname}?${params.toString()}${window.location.hash}`
: `${window.location.pathname}${window.location.hash}`;
window.history.replaceState({}, "", newUrl);
// Scroll into view after opening
requestAnimationFrame(() => {
this.element.scrollIntoView({ behavior: "smooth", block: "start" });
});
}
}
}

View File

@@ -3,11 +3,26 @@ import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="lazy-load"
// Used with <details> elements to lazy-load content when expanded
// Use data-action="toggle->lazy-load#toggled" on the <details> element
// Optional: data-lazy-load-auto-open-param-value="paramName" to auto-open when ?paramName=1 is in URL
export default class extends Controller {
static targets = ["content", "loading", "frame"];
static values = { url: String, loaded: Boolean };
static values = { url: String, loaded: Boolean, autoOpenParam: String };
connect() {
// Check if we should auto-open based on URL param
if (this.hasAutoOpenParamValue && this.autoOpenParamValue) {
const params = new URLSearchParams(window.location.search);
if (params.get(this.autoOpenParamValue) === "1") {
this.element.open = true;
// Clean up the URL param after opening
params.delete(this.autoOpenParamValue);
const newUrl = params.toString()
? `${window.location.pathname}?${params.toString()}${window.location.hash}`
: `${window.location.pathname}${window.location.hash}`;
window.history.replaceState({}, "", newUrl);
}
}
// If already open on connect (browser restored state), load immediately
if (this.element.open && !this.loadedValue) {
this.load();