diff --git a/frontend/src/components/AnchoredPopover.tsx b/frontend/src/components/AnchoredPopover.tsx index ed7c023e..5ea62784 100644 --- a/frontend/src/components/AnchoredPopover.tsx +++ b/frontend/src/components/AnchoredPopover.tsx @@ -186,7 +186,15 @@ type ItemRole = "menuitem" | "menuitemradio" | "option"; /** 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, - * `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({ children, onSelect, @@ -230,6 +238,8 @@ export function PopoverItem({ type="button" // Roving tabindex: only the active item is in the Tab order; arrows move focus between them. 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} className={className} {...ariaProps} diff --git a/frontend/src/components/ChannelTags.tsx b/frontend/src/components/ChannelTags.tsx index b6c6b9d9..100dbaa4 100644 --- a/frontend/src/components/ChannelTags.tsx +++ b/frontend/src/components/ChannelTags.tsx @@ -72,8 +72,8 @@ function TagEditorMenu({ checked={on} onSelect={() => onToggle(tg.id)} 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 ${ - on ? "text-fg" : "text-muted hover: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" }`} >