Accessibility
Overview
WCAG 2.1 AA compliance for React + shadcn/ui — keyboard navigation, screen readers, color contrast, semantic HTML.
When to Use
- •Building any new UI component or page
- •Before production launch
- •When accessibility audit fails
- •When adding forms, modals, or interactive elements
Workflow
Phase 1: Semantic HTML
- •Correct heading hierarchy (h1 > h2 > h3, one h1/page)
- •Landmarks:
<nav>,<main>,<aside>,<section> - •
<button>for actions,<a>for navigation (never<div onClick>) - •
<label>for all form inputs
Phase 2: Keyboard
- •All interactive elements focusable via Tab
- •Visible focus indicators (shadcn
focus-visiblering) - •Escape closes modals/dropdowns
- •Arrow keys in menus/tabs
- •Test: navigate entire page with keyboard only
Phase 3: Screen Readers
- •
aria-labelon icon-only buttons:tsx<Button variant="ghost" size="icon" aria-label="Close dialog"> <X className="h-4 w-4" /> </Button>
- •
aria-live="polite"on dynamic regions (toasts, loading) - •
role="alert"on error messages - •
aria-hidden="true"on decorative elements
Phase 4: Color & Contrast
- •Text contrast: 4.5:1 minimum (AA)
- •Large text (18px+): 3:1 minimum
- •Never color alone to convey meaning (add icons/text)
- •Test: DevTools > Rendering > Emulate vision deficiencies
Phase 5: Forms
- •Visible labels on every input
- •
aria-required="true"on required fields - •Errors linked with
aria-describedby+aria-invalid="true"
Phase 6: Audit
- •Lighthouse Accessibility > 90
- •axe DevTools extension
- •Keyboard-only walkthrough
- •200% zoom — layout intact
Checklist
- • Semantic landmarks and heading hierarchy
- • All elements keyboard-accessible
- • Visible focus indicators
- •
aria-labelon icon buttons - •
aria-liveon dynamic content - • 4.5:1 contrast ratios
- • Color not sole indicator
- • Form labels and error linking
- • Lighthouse Accessibility > 90
- • Tested keyboard-only + 200% zoom