mirror of
https://github.com/we-promise/sure.git
synced 2026-05-24 13:04:56 +00:00
e67ff3e3dcdaad50ec4b5899953e4667dea7ef8b
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e30ccd94af |
fix(design-system): DS::Tooltip a11y — focusable trigger, keyboard parity, Esc dismiss (#1845)
* fix(design-system): DS::Tooltip a11y — focusable trigger, keyboard parity, Esc dismiss Closes #1747. Five fixes on the tooltip primitive. 1. **Tooltip anchor not in a11y tree.** The trigger was a bare Lucide icon, which Lucide renders with `aria-hidden="true"`. The tooltip target had `role="tooltip"` but nothing referenced it, so AT users had no way to discover the description. Wrap the icon in a focusable `<button type="button">` with `aria-describedby="<tooltip-id>"` so the underlying icon stays `aria-hidden` and the button picks up the description binding. 2. **Stable per-instance id.** Each DS::Tooltip now mints a `tooltip-<8-char hex>` id wired between the trigger's `aria-describedby` and the tooltip's `id`. 3. **Keyboard parity.** Hover-only triggers locked keyboard-only users out. Add `focusin` / `focusout` listeners on the controller element so Tab onto the trigger reveals the tooltip, Tab away dismisses it. 4. **Esc-to-dismiss.** Matches the WAI-ARIA tooltip pattern. `Escape` while the tooltip is open closes it without removing focus from the trigger. 5. **Resize-safe width cap.** Replace the hard-coded `max-w-[200px]` with `max-w-[20rem]` so the tooltip scales with the user's root font-size setting (large-text accessibility pref). Slightly wider visual cap (320px @ default) but no longer clips on text-zoom. Plus: docstring note that tooltip content must be non-interactive (no buttons / links / form controls inside) — `aria-describedby` exposes content as a description, not as an interactive subtree. Callers needing actions should reach for a popover/menu primitive. API unchanged. Existing 30+ DS::Tooltip callsites work without modification — they all pass `text:`-only payloads, which still render correctly under the new markup. * fix(review): as: option + alpha focus-ring on DS::Tooltip Addresses two AI review findings on #1845: 1. **Button-inside-summary spec violation.** Wrapping the icon in `<button>` regressed keyboard/AT behavior at 13 callsites where DS::Tooltip lives inside a `<summary>` (8 provider items, lunchflow disclosure, activity_date, 4 simplefin badges). HTML's content model forbids interactive content inside `<summary>`; browsers and AT can drop focus or conflate activation with the disclosure toggle. Add `as:` parameter — default `:button` preserves the standalone a11y wrap; `:span` renders a non-focusable wrapper for summary-nested usage. `focusin` bubbles up to the controller from the ancestor `<summary>`, so keyboard tooltips still appear on tab. Migrate the 13 in-summary callsites to `as: :span`. 2. **Raw palette focus ring → alpha tokens.** Swap `outline-gray-900 theme-dark:focus-visible:outline-white` to the established focus-ring pattern `focus-visible:ring-2 focus-visible:ring-alpha-black-300 theme-dark:focus-visible:ring-alpha-white-300` — matches the DS::Toggle fix landed in #1843 review and provider_card / form-field tokens. * fix(review): bind tooltip focus on ancestor <summary> Codex P2 follow-up on #1845: \`as: :span\` renders a non-focusable trigger inside the disclosure \`<summary>\`. Keyboard users hit Tab and focus lands on the summary itself; \`focusin\` fires on the summary and bubbles UP — never down to a descendant span — so the existing listener on \`this.element\` never fires and the tooltip stays hidden for keyboard-only users on every in-summary row (provider _item partials, lunchflow disclosure, activity_date, simplefin badges). My earlier reply that the focusin "bubbles up to the Stimulus controller on the outer span" was wrong about the direction; \`focusin\` only bubbles upward. In \`addEventListeners\`, resolve \`this.element.closest("summary")\` and bind \`focusin\` / \`focusout\` / \`keydown\` on it too. Track the ancestor on the controller and undo the bindings in \`removeEventListeners\` so reconnect-on-Turbo cycles don't leak. Update the template comment to reflect the actual mechanism. * docs(ds-tooltip): correct as=:span comment to match controller mechanism --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> |
||
|
|
0fe1e06645 |
refactor(design-system): migrate fg-* utilities to text-* and remove namespace (#1626)
* refactor(design-system): migrate fg-* utilities to text-* and remove namespace
The design system carried two parallel namespaces for foreground colors:
text-* (canonical, ~2,000 uses) and fg-* (32 uses). Most fg-* tokens
were 1:1 duplicates of a text-* counterpart. fg-gray was nearly
identical to text-secondary, with a one-step shade difference in dark
mode.
This PR migrates all 32 usages to their text-* equivalents and removes
the fg-* block from the design tokens. Closes #1606.
Mapping:
- fg-inverse -> text-inverse (20 usages, identical light/dark values)
- fg-gray -> text-secondary (7 usages; light values match, dark is
one step lighter: gray-300 vs gray-400)
- fg-primary -> text-primary (3 usages, identical values)
- fg-subdued -> text-subdued (2 usages, identical values)
The four other fg-* tokens (fg-contrast, fg-primary-variant,
fg-secondary, fg-secondary-variant) had zero usages despite being
defined; they are removed without replacement.
JSON / build:
- design/tokens/sure.tokens.json: $version 1.0.0 -> 2.0.0 (breaking
schema change per the policy added in #1620). 8 fg-* token
definitions removed.
- button-bg-ghost-hover's dark value still references "fg-inverse"
internally; rewritten to "bg-gray-800 text-inverse" so the cleanup
doesn't break that utility.
- _generated.css regenerated. 42 utility blocks now (was 50).
Lookbook tokens preview:
- The Text & foregrounds section dropped its split between text-*
(canonical) and fg-* (legacy). Now a single section listing the
five text-* utilities. The "(legacy)" framing is gone since there's
no legacy left.
README:
- design/tokens/README.md's button-bg-ghost-hover edge-case example
updated to reflect the new "bg-gray-800 text-inverse" dark value.
Visual review needed in dark mode:
- Anywhere icons use the application_helper#icon helper with
color: "default" (most icons in the app). The default class moved
from fg-gray (gray-400 dark) to text-secondary (gray-300 dark), so
default-color icons render slightly lighter in dark mode.
- DS::Buttonish icons in secondary buttons (same shade shift).
- DS::Link icons (same).
- Time series chart axes (same).
- All tooltips, account add flow, settings hostings buttons,
invitations, AI consent, family export, danger-zone buttons --
these used fg-inverse, which is identical to text-inverse, so no
visual change expected.
* fix(design-system): use inverse pair on tooltips for readable dark mode
* fix(lookbook): use semantic tokens in menu preview header text
* fix(lookbook): set text-primary on layout body so previews inherit theme
* fix(design-system): keep shadows dark-toned in dark mode
Inverting shadows to white|8% on dark surfaces produces a halo
effect rather than an elevation cue, and stacks redundantly with
the alpha-white 1px ring already in shadow-border-*.
Switch dark-mode shadows to black at progressively higher alpha
(25%/30%/35%/40%/50% for xs..xl) so they read as actual cast
shadows on near-black surfaces. Surface-tint differences and the
existing alpha-white border ring continue to handle elevation
hierarchy and edge definition.
Approach matches Material 3, Apple HIG, IBM Carbon, Refactoring UI,
and the dark-mode shadows used in Linear/Vercel/Stripe.
* fix(design-system): set text-primary on DS::Dialog element
Browser UA stylesheets apply color: black directly to <dialog>,
which overrides ancestor inheritance even when a body or html
ancestor sets a theme-aware color. Unstyled child content then
renders black regardless of theme.
Setting text-primary on the dialog element itself defeats the UA
override and lets descendants inherit the semantic token.
* fix(lookbook): use shadow css vars in effects preview so dark theme renders
* Revert "fix(design-system): keep shadows dark-toned in dark mode"
This reverts commit
|
||
|
|
e8eb32d2ae |
Start and end balance breakdown in activity view (#2466)
* Initial data objects * Remove trend calculator * Fill in balance reconciliation for entry group * Initial tooltip component * Balance trends in activity view * Lint fixes * trade partial alignment fix * Tweaks to balance calculation to acknowledge holdings value better * More lint fixes * Bump brakeman dep * Test fixes * Remove unused class |