Context
packages/loopover-ui-kit's interactive primitives consistently use Tailwind's focus-visible: variant (which only applies a focus ring for keyboard/programmatic focus, not mouse-click focus) for their focus ring — see button.tsx (focus-visible:outline-none focus-visible:ring-2 ...), input.tsx, textarea.tsx, switch.tsx, checkbox.tsx, toggle.tsx, slider.tsx, and badge.tsx (focus:outline-none focus-visible:ring-2 ... — focus: only clears the native outline, the actual ring is still focus-visible:).
Four components break this convention and instead apply their ring/highlight on plain focus:, which also fires on mouse-click focus and produces a persistent focus ring/background highlight after every click — something none of the other primitives do:
select.tsx:22 — SelectTrigger: ... focus:outline-none focus:ring-1 focus:ring-ring ...
dialog.tsx:47 — DialogPrimitive.Close: ... focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ...
sheet.tsx:72 — SheetPrimitive.Close: ... focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ...
navigation-menu.tsx:44 — NavigationMenuTrigger's trigger style: ... focus:bg-accent focus:text-accent-foreground focus:outline-none ...
Requirements
- In each of the four locations above, change the ring/background-highlight classes from
focus: to focus-visible:, matching the exact convention already used by button.tsx/input.tsx/textarea.tsx/switch.tsx/checkbox.tsx/toggle.tsx/slider.tsx.
- Keep
focus:outline-none as-is where present (clearing the native browser outline on any focus, not just keyboard focus, is correct and matches every other primitive) — only the visible ring/highlight classes (focus:ring-*, focus:bg-accent, focus:text-accent-foreground) need to move to focus-visible:.
- Do not touch any other className on these four elements (radius, padding, color tokens unrelated to focus).
- This is a class-rename-only fix — no new abstraction, no adoption of the
.focus-ring CSS utility in theme.css (that utility is for app-level nav/hero elements per its own comment, not the primitive-component convention these four should follow).
Deliverables
Test Coverage Requirements
packages/loopover-ui-kit is not in the root vitest.config.ts's coverage.include and is not Codecov-gated (its own vitest.config.ts states the acceptance signal is the suite running and passing, not a percentage) — still add a test per the Deliverables above so the fix is verifiable and doesn't silently regress.
Expected Outcome
SelectTrigger, DialogPrimitive.Close, SheetPrimitive.Close, and NavigationMenuTrigger only show their focus ring/highlight for keyboard/programmatic focus, matching every other interactive primitive in @loopover/ui-kit — clicking them with a mouse no longer leaves a lingering ring/highlight.
Links & Resources
Context
packages/loopover-ui-kit's interactive primitives consistently use Tailwind'sfocus-visible:variant (which only applies a focus ring for keyboard/programmatic focus, not mouse-click focus) for their focus ring — seebutton.tsx(focus-visible:outline-none focus-visible:ring-2 ...),input.tsx,textarea.tsx,switch.tsx,checkbox.tsx,toggle.tsx,slider.tsx, andbadge.tsx(focus:outline-none focus-visible:ring-2 ...—focus:only clears the native outline, the actual ring is stillfocus-visible:).Four components break this convention and instead apply their ring/highlight on plain
focus:, which also fires on mouse-click focus and produces a persistent focus ring/background highlight after every click — something none of the other primitives do:select.tsx:22—SelectTrigger:... focus:outline-none focus:ring-1 focus:ring-ring ...dialog.tsx:47—DialogPrimitive.Close:... focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ...sheet.tsx:72—SheetPrimitive.Close:... focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ...navigation-menu.tsx:44—NavigationMenuTrigger's trigger style:... focus:bg-accent focus:text-accent-foreground focus:outline-none ...Requirements
focus:tofocus-visible:, matching the exact convention already used bybutton.tsx/input.tsx/textarea.tsx/switch.tsx/checkbox.tsx/toggle.tsx/slider.tsx.focus:outline-noneas-is where present (clearing the native browser outline on any focus, not just keyboard focus, is correct and matches every other primitive) — only the visible ring/highlight classes (focus:ring-*,focus:bg-accent,focus:text-accent-foreground) need to move tofocus-visible:..focus-ringCSS utility intheme.css(that utility is for app-level nav/hero elements per its own comment, not the primitive-component convention these four should follow).Deliverables
select.tsx'sSelectTriggerring classes changed fromfocus:tofocus-visible:dialog.tsx'sDialogPrimitive.Closering classes changed fromfocus:tofocus-visible:sheet.tsx'sSheetPrimitive.Closering classes changed fromfocus:tofocus-visible:navigation-menu.tsx'sNavigationMenuTriggerhighlight classes changed fromfocus:tofocus-visible:focus:ring/focus:bg-accentclass in its rendered class listTest Coverage Requirements
packages/loopover-ui-kitis not in the rootvitest.config.ts'scoverage.includeand is not Codecov-gated (its ownvitest.config.tsstates the acceptance signal is the suite running and passing, not a percentage) — still add a test per the Deliverables above so the fix is verifiable and doesn't silently regress.Expected Outcome
SelectTrigger,DialogPrimitive.Close,SheetPrimitive.Close, andNavigationMenuTriggeronly show their focus ring/highlight for keyboard/programmatic focus, matching every other interactive primitive in@loopover/ui-kit— clicking them with a mouse no longer leaves a lingering ring/highlight.Links & Resources
packages/loopover-ui-kit/src/components/button.tsx,input.tsx,switch.tsx(thefocus-visible:convention to match)AccordionTriggerfocus-visible gap — same "inconsistent with every other interactive control in ui-kit" shape)