feat(a11y): R9 focus foundation — glass shadow fix, focus-visible ring, highlight/selected split
S1 — recipe foundation: - Move .glass/.glass-card/.glass-menu into @layer components so a JSX shadow-* utility overrides the glass box-shadow again; the ~9 dead shadow-* on glass surfaces (modals, menus, save-bar, chat) now paint their intended drop-shadow. Perf-mode and :hover overrides stay unlayered so they still win. - Add a .selectable recipe: the hover tint menu/list rows already use, PLUS the app-wide focus-visible ring that was missing on non-input controls (the biggest a11y gap). - Split the popover roving highlight from the selected state (AnchoredPopover): a selected/checked PopoverItem now gets a ring ONLY, so its resting paint (bg-accent fill / text-accent / checkbox) survives being highlighted instead of downgrading to a 35% tint or being recoloured. Fixes the 4 review findings deferred from R10-S0 generically; drops the leftover per-consumer data-active ring in tableHeader. S2 — worst offenders: - Account-menu trigger + switch/add/sign-out rows adopt .selectable (visible keyboard focus). - Saved-views rows: group-focus-within reveals the hover-only action buttons for keyboard users; aria-current on the active row; focus-visible ring on every button. - The 3 invisible-focus inputs get an accent focus ring: SearchBar + ShareDialog via focus-within on the glass pill/row, AboutCell via focus-visible on the trigger. Deferred to a later R9 sprint: the full unification of all ~14 selection idioms, a shared <NavItem>, and .is-current/.chip recipes (no consumer yet in this pass). Verified: tsc/eslint/prettier/knip/vitest (79) green; browser computed-style checks confirm the glass shadow now wins, the focus outlines render (2px accent), and the split renders (selected ring-only, unselected fill).
This commit is contained in:
@@ -322,7 +322,7 @@ export default function NavSidebar({
|
||||
ref={acctPop.refs.setReference}
|
||||
{...acctPop.getReferenceProps()}
|
||||
title={slim ? `${name} · ${roleLabel}` : undefined}
|
||||
className={`${rowBase} ${slim ? "justify-center px-0" : ""} text-muted hover:text-fg hover:bg-card`}
|
||||
className={`${rowBase} selectable ${slim ? "justify-center px-0" : ""} text-muted hover:text-fg hover:bg-card`}
|
||||
>
|
||||
<span className="relative shrink-0">
|
||||
<AvatarImg
|
||||
@@ -367,7 +367,7 @@ export default function NavSidebar({
|
||||
key={a.id}
|
||||
onClick={() => switchTo(a.id)}
|
||||
title={t("header.account.switchTo", { name: a.display_name ?? a.email })}
|
||||
className="w-full flex items-center gap-2.5 px-2 py-1.5 rounded-lg hover:bg-card transition"
|
||||
className="selectable w-full flex items-center gap-2.5 px-2 py-1.5 rounded-lg hover:bg-card transition"
|
||||
>
|
||||
<AvatarImg
|
||||
src={a.avatar_url}
|
||||
@@ -393,14 +393,14 @@ export default function NavSidebar({
|
||||
clearActiveAccount();
|
||||
window.location.href = "/auth/login";
|
||||
}}
|
||||
className="w-full flex items-center gap-2 text-sm px-2 py-2 rounded-lg text-muted hover:text-fg hover:bg-card transition"
|
||||
className="selectable w-full flex items-center gap-2 text-sm px-2 py-2 rounded-lg text-muted hover:text-fg hover:bg-card transition"
|
||||
>
|
||||
<UserPlus className="w-4 h-4" />
|
||||
{t("header.account.addAccount")}
|
||||
</button>
|
||||
<button
|
||||
onClick={logout}
|
||||
className="w-full flex items-center gap-2 text-sm px-2 py-2 rounded-lg text-muted hover:text-fg hover:bg-card transition"
|
||||
className="selectable w-full flex items-center gap-2 text-sm px-2 py-2 rounded-lg text-muted hover:text-fg hover:bg-card transition"
|
||||
>
|
||||
<LogOut className="w-4 h-4" />
|
||||
{t("header.account.signOut")}
|
||||
|
||||
Reference in New Issue
Block a user