fix(popover): visible accent highlight on the active menu item (R8 S2 UAT)

The tag editor's active row barely differed from the menu background. Drive
the highlight off the roving `data-active` attribute (reliable across click-
vs key-open, unlike :focus-visible, which a click-open's programmatic focus
doesn't trip) and tint it with the accent. `bg-accent/NN` can't be used —
the theme's --accent is a hex var and Tailwind v3 can't inject alpha into it
— so use a color-mix arbitrary value, matching the app's glass idiom.
This commit is contained in:
2026-07-30 23:33:50 +02:00
parent 5d1854b808
commit d950867d26
2 changed files with 13 additions and 3 deletions
+11 -1
View File
@@ -186,7 +186,15 @@ type ItemRole = "menuitem" | "menuitemradio" | "option";
/** One keyboard-navigable option inside a menu/listbox `PopoverSurface`. Self-registers for roving /** One keyboard-navigable option inside a menu/listbox `PopoverSurface`. Self-registers for roving
* focus + typeahead and applies the correct ARIA. Use `menuitemradio`+`checked` for a toggle, * focus + typeahead and applies the correct ARIA. Use `menuitemradio`+`checked` for a toggle,
* `option`+`selected` for a listbox choice, plain `menuitem` for an action. */ * `option`+`selected` for a listbox choice, plain `menuitem` for an action.
*
* The active (roving) item carries `data-active` — style the highlight off THAT, not `:focus-visible`:
* a click-opened menu focuses the first item programmatically, which does NOT reliably trip the
* focus-visible heuristic, so a `:focus-visible` highlight can stay invisible until the first arrow
* key. The recommended recipe is an accent tint — and note `bg-accent/NN` does NOT work here (the
* theme's `--accent` is a hex var, and Tailwind v3 can't inject alpha into it), so use a color-mix
* arbitrary value like the app's own glass idiom:
* `data-[active]:bg-[color-mix(in_srgb,var(--accent)_24%,transparent)] data-[active]:text-fg`. */
export function PopoverItem({ export function PopoverItem({
children, children,
onSelect, onSelect,
@@ -230,6 +238,8 @@ export function PopoverItem({
type="button" type="button"
// Roving tabindex: only the active item is in the Tab order; arrows move focus between them. // Roving tabindex: only the active item is in the Tab order; arrows move focus between them.
tabIndex={active ? 0 : -1} tabIndex={active ? 0 : -1}
// Highlight hook: reliable across click- vs key-open (see the note above), unlike :focus-visible.
data-active={active ? "true" : undefined}
disabled={disabled} disabled={disabled}
className={className} className={className}
{...ariaProps} {...ariaProps}
+2 -2
View File
@@ -72,8 +72,8 @@ function TagEditorMenu({
checked={on} checked={on}
onSelect={() => onToggle(tg.id)} onSelect={() => onToggle(tg.id)}
label={tg.name} label={tg.name}
className={`w-full flex items-center gap-2 text-left text-xs px-2 py-1.5 rounded-md outline-none transition focus-visible:bg-card ${ className={`w-full flex items-center gap-2 text-left text-xs px-2 py-1.5 rounded-md outline-none transition hover:bg-card data-[active]:bg-[color-mix(in_srgb,var(--accent)_24%,transparent)] data-[active]:text-fg ${
on ? "text-fg" : "text-muted hover:bg-card" on ? "text-fg" : "text-muted"
}`} }`}
> >
<span <span