* feat(design-system): add :inline variant + migrate indexa_capital + snaptrade panels
Adds an `:inline` variant to `DS::Disclosure` for plain text-link-style
toggles that have no surface, no padding, no shadow — the disclosure
reads as a clickable summary text + revealed content, nothing more.
Use case: "Alternative auth" form section toggle in the Indexa Capital
provider panel; "Manage connections" lazy-loaded toggle in the
Snaptrade provider panel. Both were the last raw-`<details>` callsites
in `app/views/settings/providers/`.
Migrations:
- `_indexa_capital_panel.html.erb` — single inline `<details>` revealing
username / document / password form fields under an "Alternative auth"
summary text.
- `_snaptrade_panel.html.erb` — lazy-load `<details>` with
`data-controller="lazy-load"` etc. The new `tag.details ... **opts`
forwarding from #1857 lets the Stimulus controller attrs flow
through cleanly via DS::Disclosure's `data:` keyword.
Chevron rotation on snaptrade gets the standard
`motion-safe:transition-transform motion-safe:duration-150` treatment
(was `transition-transform` without the motion-safe gate).
Variant summary now:
| Variant | Details surface | Use case |
|---|---|---|
| `:default` | none / bg-surface summary | inline expander inside parent card |
| `:card` | `bg-container shadow-border-xs rounded-xl p-4` | provider rows, settings sections |
| `:card_inset` | `bg-surface-inset rounded-xl p-4` | inset sub-panels |
| `:inline` | no surface | text-link-style toggles |
* fix(review): guard variant.to_sym against nil in DS::Disclosure
CodeRabbit on #1858 flagged that `variant: nil` crashed with
`NoMethodError` at `variant.to_sym` before the explicit `VARIANTS`
check could run. Use safe navigation (`variant&.to_sym`) so nil
falls through to the validation, and inspect `@variant` in the
error message so nil / non-symbol inputs render readably.
Verified manually via runner: `DS::Disclosure.new(variant: nil)` now
raises `ArgumentError: Invalid variant: nil. Must be one of
[:default, :card, :card_inset, :inline]`.
* feat(design-system): add :card_inset variant + migrate ibkr_panel and settings/_section
Wraps up the disclosure migration cluster from #1715 §6:
1. **New `:card_inset` variant** on `DS::Disclosure`. Same contract
as `:card` but uses `bg-surface-inset rounded-xl p-4` (no shadow)
for inset sub-panels embedded inside a parent card surface.
2. **Migrate `_ibkr_panel.html.erb`** — the "flex query details"
disclosure (`<details class="group bg-surface-inset rounded-xl p-4">`)
was the one panel skipped from #1856 because it used the inset
surface. Now uses `DS::Disclosure(variant: :card_inset)`. Chevron
gets the `motion-safe:transition-transform motion-safe:duration-150`
treatment along the way.
3. **Migrate `settings/_section.html.erb`** — the global "collapsible
settings card" primitive backing 19 callsites via the
`settings_section(...)` helper. The collapsible branch's
`<details class="group bg-container shadow-border-xs rounded-xl p-4">`
becomes `DS::Disclosure(variant: :card, open: open, data: ...)`.
While here:
- Update `disclosure.html.erb` to spread `**opts` onto the `<details>`
element via `tag.details`. Previously opts were captured but never
applied; the `settings/_section` migration needs `data-controller`
+ `data-auto-open-param-value` to flow through to the rendered
`<details>`.
- Non-collapsible branch in `settings/_section.html.erb` stays as
raw `<section>` — different semantics (not expandable), DS::Disclosure
can't replace because it always renders `<details>`.
API:
DS::Disclosure.new(
variant: :card | :card_inset | :default,
open: bool,
data: { controller: "...", ... } # forwarded to <details>
)
* fix(review): merge caller class in DS::Disclosure + i18n plaid deletion
- DS::Disclosure: extract caller class: from opts and merge via class_names
before forwarding to tag.details. Prevents the latent duplicate keyword
arg error when callers pass class: alongside the variant-derived classes.
- plaid_items/_plaid_item: localize "(deletion in progress...)" via
t('.deletion_in_progress') + add en locale key, matching lunchflow /
mercury / sophtron / coinstats convention.
* fix(panels): replace text-white and bg-gray-tint-10 with semantic tokens
`text-white` → `text-inverse` on the EnableBanking reauthorize button
(`bg-warning` background); `bg-gray-tint-10` → `bg-container-inset` on
the IndexaCapital item avatar wrapper. Both flagged by sure-design as
non-functional palette tokens.
Pre-existing on main; surfaced by the re-indentation that this PR
applied during the disclosure migration.
* feat(design-system): DS::Disclosure :card variant + migrate 14 provider items
Resolves part of #1715 §6. The provider-item view templates
(binance, brex, coinbase, coinstats, enable_banking, ibkr,
indexa_capital, kraken, lunchflow, mercury, plaid, simplefin,
snaptrade, sophtron — 14 in total) all hand-rolled the same
`<details open class="group bg-container p-4 shadow-border-xs
rounded-xl">` shell with a custom summary inside and content below.
Extend `DS::Disclosure` with a `:card` variant that bakes the card
chrome onto the `<details>` element itself; the summary becomes
slot-driven via the existing `summary_content` slot. Provider items
keep their custom summary content (logos, brand colors, status copy)
unchanged — they just hand it to the slot instead of writing it
between `<summary>` tags.
API:
DS::Disclosure.new(variant: :card, open: true) do |d|
d.with_summary_content do
<div class="flex items-center gap-2">
chevron + custom summary markup
</div>
end
body content
end
While here:
- Drop the no-op `group-open:transform` from the default chevron
(Tailwind v4 applies `rotate-90` directly).
- Add `motion-safe:transition-transform motion-safe:duration-150`
to chevron rotation for reduced-motion respect (matches the
pattern landing in #1841).
- Extract `summary_classes` / `details_classes` helpers so the
default and card surfaces stay readable side-by-side.
Note: this PR touches `DS::Disclosure` and will textually conflict
with #1841 (focus-ring + reduced-motion polish). Both changes are
compatible — when #1841 merges first, the resolution is just
preserving both edits (the focus-ring classes are already merged
into `summary_classes` here).
* fix(review): use ring-alpha-black-300 focus token in DS::Disclosure
CodeRabbit P2: switch the focus-visible outline from raw
gray-900/white palette values to the alpha-black-300 ring token,
matching the established focus pattern on settings/provider_card.html.erb.
This keeps theme behavior centralized in the design system tokens
instead of branching on theme-dark: in the component.
Applies to both :default and :card summary variants.
* fix(review): stretch DS::Disclosure summary_content to full width
Codex P2 follow-up on the disclosure-migration stack: \`<summary>\` is
\`display: list-item\`, so a flex inner div inside the slot
shrink-wraps to content width — any \`justify-between\` the caller
adds has nothing to distribute, and the right-side admin actions
collapse toward the title across every provider-item partial migrated
to \`DS::Disclosure variant: :card\` in #1855 (and the panels in
#1856 / #1857 / #1858 that inherit this component).
Wrap the slot in \`<div class=\"w-full\">\` so caller-supplied flex
rows stretch across the card. \`:default\` variant is unchanged
(it never uses \`summary_content\`).