mirror of
https://github.com/we-promise/sure.git
synced 2026-06-06 19:29:03 +00:00
* fix(ds): dark-mode token parity — text, borders, checkbox, toggle, over-budget badge Dark-mode contrast/parity pass (design-review epic #2134, follow-up to #1736): - text-subdued (dark): gray-500 -> gray-400; faint/eyebrow text ~3.6:1 -> ~6.7:1 (clears AA), staying below text-secondary so hierarchy holds. - border-primary/secondary/subdued (dark): +1 alpha-white step each; restores group-card edges and in-card row hairlines (border-primary 1.86:1 -> 2.8:1). Alpha keeps them surface-relative across any dark bg. - Dark checkbox: unchecked was a solid white square (read as already-selected) — now a transparent outlined box; checked/indeterminate use a white fill with a #171717 glyph (was #808080, ~2:1); added an explicit indeterminate dash; disabled muted to gray-700. - Toggle (light off-state): track gray-100 -> gray-300 plus a thumb shadow; the white-thumb-on-white-track invisible off-state now reads (dark off-track was already hardened to gray-700). - Over-budget badge: text-red-500 -> text-destructive (theme-aware, matching the on-track/near-limit siblings); in-situ dark contrast 4.18:1 -> 4.55:1 (AA). - Correct invalid icon color keys (red/yellow/green -> destructive/warning/success) on the three budget status badges. Verified in-browser, light+dark: isolated checkbox states, /accounts card borders, /reports muted text, toggle off-state, /budgets over-budget badge (in-situ 4.55:1). * fix(ds): reconcile destructive color + fix filled-pill contrast Continues the dark-parity pass (#2134): - Reconcile destructive: border-destructive and button-bg-destructive were red-500 while the destructive text/icon token was red-600. Unify on red-600 (light) / red-400 (dark) across text, border, and button — the text token can't drop to red-500 (3.96:1 on white, fails AA), so border/button move up instead. White-on-destructive-button 3.96:1 -> 4.36:1 (AA-large); hover red-600 -> red-700. - DS::Pill filled style: deepen the fill tone-500 -> tone-700. White label text on tone-500 failed AA on nearly every tone (amber 2.35:1, green 2.62:1, red 3.95:1); tone-700 clears it (amber 5.43, green 4.30, red 5.86, others 6.4-12) in both themes and removes the dark-surface glare. Date-input calendar glyph in dark verified already-correct (existing invert(1) rules; color-scheme is normal, so no conflict) — no change needed. Verified in-browser: real .button-bg-destructive (red-600) + filled pills, all tones, light and dark. * fix(ds): destructive button consumes the reconciled red-600 Follow-up to the destructive reconcile in this branch: DS::Buttonish's destructive variant still used raw bg-red-500 / hover:bg-red-600, so destructive *buttons* didn't match the reconciled destructive text/border (red-600). Align to red-600 / hover red-700 (light); dark unchanged (red-400 / red-500). White-on-red-600 = 4.37:1 (AA-large), consistent with the rest of the destructive family. * refactor(ds): tokenize budget-category badge + bar backgrounds Status-badge foregrounds already used semantic tokens (text-destructive/ warning/success) but backgrounds + progress-bar fills stayed on the raw palette (bg-red-500/10, bg-yellow-500, ...). Switch to the matching semantic tokens (bg-destructive/10, bg-warning, bg-success) — same value in light, now theme-aware in dark. Mirrors DS::Alert. Addresses CodeRabbit/Codex on #2139.
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 after:shadow-sm",
|
|
"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
|