WCAG 2.1 AA — release blocker
Web (React DOM)
- Renders as
<header>so it lands in the page landmarks (screen readers can jump to it with the "Banner" shortcut). - The slots are pass-through — every interactive child must satisfy its own a11y rules:
- The logo: prefer
<a href="/">over a<button>so the home shortcut works. TopBarMenuButton: ships witharia-label="Open menu"(override viaariaLabel),aria-haspopup="menu", type=button, focus-visible ring, and a 40×40 hit area. Visuallylg:hidden(mobile + tablet only); on desktop it'sdisplay: noneand unfocusable, so the keyboard tab order on desktop is unchanged.- The bell: a
<button>witharia-label="Notifications, N unread"(theNotificationBadgeitself is decorative). - The avatar: a
<button>if it opens a menu, else a plain<img>withalt. - "What's new" / "Logout":
<button>if they open a UI,<a>if they navigate.
- The logo: prefer
Keyboard navigation
Tabmoves between focusable children in DOM order.- Each child handles its own activation.
- For dropdowns triggered from the end slot (profile menu, notifications panel), use a headless popover primitive with managed focus.
Reduced motion
The bar has no transitions; nothing to honour beyond the system default.
Color is never the only signal
- The shadow under the bar uses
shadow-mi-soft— a soft drop that's still visible to users with reduced colour perception. - Dividers use a 15 px line in
bordercolour, not just lighter text spacing.
Audit checklist
- Every interactive child has a real role (
<button>/<a>) and an accessible name. - Icon-only buttons have
aria-label. -
Taborder matches visual order. - Bar contrast ≥ 4.5:1 between
bg-cardandtext-foreground× light/dark.