mirror of
https://github.com/we-promise/sure.git
synced 2026-05-25 13:34:58 +00:00
Two regressions from the recent token sweep, both producing low-contrast results in dark mode. ## DS::Toggle off-track PR #1843 (DS::Toggle a11y + token swaps) replaced the raw `bg-gray-100 theme-dark:bg-gray-700` off-track with `bg-surface-inset` for semantic alignment. `bg-surface-inset` resolves to gray-800 in dark mode, but the toggle typically sits inside `bg-container` (gray-900). The contrast ratio dropped from ~2.45:1 (gray-700 vs gray-900) to ~1.5:1 (gray-800 vs gray-900) — visibly worse than the pre-#1843 baseline and below WCAG 1.4.11 (3:1 for UI components). Most visible inside the transaction-edit modal SETTINGS section (`Exclude`, `One-time Expense`) where the off-state switches nearly vanished into the modal chrome. Introduce `--color-toggle-track` (light: gray-100, dark: gray-700) and swap `bg-surface-inset` → `bg-toggle-track` in DS::Toggle. Restores the pre-#1843 off-track contrast while keeping a semantic token (instead of the raw palette references the migration was trying to remove). ## border-destructive subtle borders PR #1849 (single-color tokens to @theme) flagged that `border-destructive/N` rendered the wrong shade (the `@utility border-destructive` block defined red-500 light, while `--color-destructive` in `@theme` is red-600 — `/N` resolves from @theme), and swapped a couple of callsites to solid `border-destructive`. Solid renders red-500/red-400 at full saturation in both modes, which reads as a loud error border on contexts that were meant to be subtle (left-rule on the provider-sync "view error details" pane, error-message box in SimpleFIN settings, alert-component border, provider connection error rows). Two callsites (`DS::Alert`, settings/providers/_connection_row) still carried the broken `border-destructive/20` / `/25` modifier — same off-shade footgun #1849 was meant to retire. Introduce `--color-destructive-subtle` (light: red-200, dark: red-800) and swap the four subtle-by-intent callsites to `border-destructive-subtle`: - app/components/DS/alert.rb (destructive variant) - app/views/settings/providers/_connection_row.html.erb (err status) - app/components/provider_sync_summary.html.erb (error-details left rule) - app/views/simplefin_items/edit.html.erb (error-message box) The handful of intentionally-loud `border-destructive` callsites (split-transaction over-allocation, blank-name account labels, etc.) keep the solid token. Regenerated `_generated.css` via `npm run tokens:build`.
39 lines
1.8 KiB
Ruby
39 lines
1.8 KiB
Ruby
class DS::Toggle < DesignSystemComponent
|
|
attr_reader :id, :name, :checked, :disabled, :checked_value, :unchecked_value, :opts
|
|
|
|
def initialize(id:, name: nil, checked: false, disabled: false, checked_value: "1", unchecked_value: "0", **opts)
|
|
@id = id
|
|
@name = name
|
|
@checked = checked
|
|
@disabled = disabled
|
|
@checked_value = checked_value
|
|
@unchecked_value = unchecked_value
|
|
@opts = opts
|
|
end
|
|
|
|
def label_classes
|
|
class_names(
|
|
"relative block w-9 h-5 cursor-pointer",
|
|
# `bg-toggle-track` lifts the dark-mode off-track to gray-700 so the
|
|
# switch keeps WCAG 1.4.11 contrast against the surrounding
|
|
# bg-container (gray-900). `bg-surface-inset` resolves to gray-800
|
|
# in dark mode and dropped to ~1.5:1 against the container,
|
|
# making the toggle nearly invisible inside modals.
|
|
"rounded-full bg-toggle-track",
|
|
# `motion-safe:` gates the bg + thumb-translate transitions on
|
|
# `prefers-reduced-motion`; reduced-motion users get a snap.
|
|
"motion-safe:transition-colors motion-safe:duration-300",
|
|
"after:content-[''] after:block after:bg-white after:absolute after:rounded-full",
|
|
"after:top-0.5 after:left-0.5 after:w-4 after:h-4",
|
|
"motion-safe:after:transition-transform motion-safe:after:duration-300 motion-safe:after:ease-in-out",
|
|
"peer-checked:bg-success peer-checked:after:translate-x-4",
|
|
# Focus ring driven from the sr-only input via `peer-focus-visible:`.
|
|
# Offset places the ring outside the track so it lands on the
|
|
# surrounding chrome regardless of theme.
|
|
"peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2",
|
|
"peer-focus-visible:ring-alpha-black-300 theme-dark:peer-focus-visible:ring-alpha-white-300",
|
|
"peer-disabled:opacity-70 peer-disabled:cursor-not-allowed"
|
|
)
|
|
end
|
|
end
|