Accessibility is a product requirement, not a polish step. Components should be usable with keyboard, screen reader, zoom, and reduced-motion preferences.

Keyboard navigation

  • All interactive elements must be keyboard reachable.
  • Use native controls (button, input, select, a) whenever possible.
  • Do not remove focusability using positive or negative tabindex hacks.
  • Complex widgets should follow WAI-ARIA authoring patterns.

Focus management

  • Every interactive control must have a visible focus style.
  • Keep focus ring color consistent with --of-ring.
  • Dialogs should move focus to the first actionable item on open and return focus to the trigger on close.
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--of-ring);
}

Color contrast

  • Body text: minimum WCAG AA contrast against its background.
  • UI controls and focus indicators: ensure clear state distinction.
  • Do not convey state by color alone. Pair color with text/icon shape.

Labels and names

  • Every form input needs a persistent, visible label.
  • Icon-only buttons must include aria-label.
  • Decorative icons should be aria-hidden="true".
<button class="of-btn of-btn--ghost" aria-label="Close dialog">
  <svg aria-hidden="true" width="16" height="16">...</svg>
</button>

Live regions and status

  • Toasts and validation summaries should use polite live regions.
  • Error messages should be associated with fields using aria-describedby.

Motion and reduced motion

  • Keep transitions short and optional.
  • Respect prefers-reduced-motion for animated UI.
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0ms !important;
    transition-duration: 0ms !important;
    scroll-behavior: auto !important;
  }
}

Testing checklist

  • Navigate each page using only keyboard (Tab, Shift+Tab, Enter, Esc).
  • Verify headings and landmarks with a screen reader.
  • Test contrast in both light and dark mode.
  • Test at 200% zoom.
  • Run Lighthouse and axe checks before shipping.

Component requirements

Component typeRequired accessibility behavior
ButtonsKeyboard activation, visible focus, accessible name
InputsLabel association, error description linkage
DialogsFocus trap, Esc close, labeled title
TabsArrow-key navigation, selected state announced
ToastsLive region announcement