diff --git a/VERSION b/VERSION index 16a246f6..12193b84 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.59.1 \ No newline at end of file +0.60.0 \ No newline at end of file diff --git a/frontend/src/components/AboutCell.tsx b/frontend/src/components/AboutCell.tsx index e2af1a75..9ddb995f 100644 --- a/frontend/src/components/AboutCell.tsx +++ b/frontend/src/components/AboutCell.tsx @@ -45,7 +45,7 @@ export default function AboutCell({ text, channelId }: { text: string | null; ch ref={pop.refs.setReference} {...pop.getReferenceProps()} tabIndex={0} - className="block max-w-88 truncate text-muted cursor-help outline-hidden" + className="block max-w-88 truncate text-muted cursor-help rounded-sm outline-hidden focus-visible:outline-2 focus-visible:outline-accent/60 focus-visible:outline-offset-2" > {preview} diff --git a/frontend/src/components/AddToPlaylist.tsx b/frontend/src/components/AddToPlaylist.tsx index 7e3a548d..0cfc74c2 100644 --- a/frontend/src/components/AddToPlaylist.tsx +++ b/frontend/src/components/AddToPlaylist.tsx @@ -98,7 +98,7 @@ export default function AddToPlaylist({ - + {/* A React portal still propagates events up the REACT tree, so a click inside this panel would otherwise reach the feed card that hosts the trigger and start playback. */}
e.stopPropagation()}> diff --git a/frontend/src/components/AnchoredPopover.tsx b/frontend/src/components/AnchoredPopover.tsx index f807375d..bdce815e 100644 --- a/frontend/src/components/AnchoredPopover.tsx +++ b/frontend/src/components/AnchoredPopover.tsx @@ -250,11 +250,15 @@ type ItemRole = "menuitem" | "menuitemradio" | "menuitemcheckbox" | "option"; * focus-visible heuristic, so a `:focus-visible` highlight can stay invisible until the first arrow * key. (Since the Tailwind v4 migration `bg-accent/NN` works — v4 does the opacity modifier via * color-mix — so the recipe no longer needs a hand-written color-mix arbitrary value.) */ -// Applied to EVERY PopoverItem so the roving-focus row is clearly visible across all schemes: an -// accent fill plus a 1px inset accent ring for a defined edge. (The previous per-consumer 24% fill -// alone read as barely-there — a real UAT finding, 2026-08-08.) -const ACTIVE_HIGHLIGHT = +// The roving-focus highlight, SPLIT by selection state (R9). A NON-selected row gets the familiar +// accent fill + inset ring. A SELECTED/checked row gets ring-ONLY, so the consumer's own resting +// selected paint (a bg-accent fill, text-accent, a checkbox) SURVIVES being highlighted instead of +// being downgraded to a 35% tint or having its text recoloured (the R10-S0 review findings). The two +// can't be merged onto one recipe: the fill and the selected paint both drive background/color on the +// same element, so the highlight must yield to the selected state rather than overwrite it. +const HIGHLIGHT_UNSELECTED = "data-active:bg-accent/35 data-active:text-fg data-active:ring-1 data-active:ring-inset data-active:ring-accent/60"; +const HIGHLIGHT_SELECTED = "data-active:ring-2 data-active:ring-inset data-active:ring-accent/70"; export function PopoverItem({ children, @@ -323,7 +327,7 @@ export function PopoverItem({ tabIndex={focusActive ? 0 : -1} data-active={visualActive ? "true" : undefined} disabled={disabled} - className={`${ACTIVE_HIGHLIGHT}${className ? ` ${className}` : ""}`} + className={`outline-hidden ${checked || selected ? HIGHLIGHT_SELECTED : HIGHLIGHT_UNSELECTED}${className ? ` ${className}` : ""}`} > {children} diff --git a/frontend/src/components/BackToTop.tsx b/frontend/src/components/BackToTop.tsx index 8a888244..ec9ff758 100644 --- a/frontend/src/components/BackToTop.tsx +++ b/frontend/src/components/BackToTop.tsx @@ -51,7 +51,7 @@ export default function BackToTop({ dep, threshold = 600 }: { dep?: unknown; thr return createPortal( diff --git a/frontend/src/components/SearchBar.tsx b/frontend/src/components/SearchBar.tsx index 7b2983bd..aa4f1af7 100644 --- a/frontend/src/components/SearchBar.tsx +++ b/frontend/src/components/SearchBar.tsx @@ -31,7 +31,7 @@ export default function SearchBar({ if (onGo && !goDisabled) onGo(); }; return ( -
+
{open && filtered.length > 0 && ( -
+
{filtered.map((u) => (