What to build
The shared Button primitive uses focus-within:brightness-75 instead of focus-visible. This:
- Triggers on mouse-down (
:focus-within matches on any descendant focus, including programmatic), producing the focus style for non-keyboard users.
- Provides no visible outline/ring — only a brightness change — which can be invisible on themed surfaces.
Additionally, several places pass styled={false} to Button (e.g. cart-button.tsx:19-31, "Clear cart" in cart-lines.tsx:34-45), which strips the existing focus styling without providing a replacement. Keyboard users get nothing.
Fix:
- Replace
focus-within with focus-visible on the Button base.
- Add an explicit
focus-visible:ring-2 focus-visible:ring-offset-2 (or token-equivalent) so the focused state is visible across light/dark surfaces.
- When
styled={false}, still apply a minimum focus-visible ring at the wrapper.
Acceptance criteria
Blocked by
None — can start immediately.
References
apps/storefront/src/components/actionable/button.tsx:33
apps/storefront/src/components/header/cart-button.tsx:19
apps/storefront/src/components/cart/cart-lines.tsx:34
What to build
The shared
Buttonprimitive usesfocus-within:brightness-75instead offocus-visible. This::focus-withinmatches on any descendant focus, including programmatic), producing the focus style for non-keyboard users.Additionally, several places pass
styled={false}toButton(e.g.cart-button.tsx:19-31, "Clear cart" incart-lines.tsx:34-45), which strips the existing focus styling without providing a replacement. Keyboard users get nothing.Fix:
focus-withinwithfocus-visibleon the Button base.focus-visible:ring-2 focus-visible:ring-offset-2(or token-equivalent) so the focused state is visible across light/dark surfaces.styled={false}, still apply a minimumfocus-visiblering at the wrapper.Acceptance criteria
focus-withinusage remains onButton(and any other interactive primitives where it was used as a focus proxy)Tabthrough cart, header, and PDP produces a visible focus indicator on every interactive controlstyled={false}Buttons still surface focusBlocked by
None — can start immediately.
References
apps/storefront/src/components/actionable/button.tsx:33apps/storefront/src/components/header/cart-button.tsx:19apps/storefront/src/components/cart/cart-lines.tsx:34