React Accessibility Checklist
A React-specific accessibility checklist covering the patterns that break in JSX: focus management on route changes, ARIA state syncing with React state, useId for accessible IDs, Portals + dialogs, controlled-component form accessibility, and React Testing Library practices. Pair it with the Developer checklist for non-React-specific items.
Frequently asked questions
Why a React-specific checklist? Doesn't WCAG apply equally?
WCAG is framework-agnostic, but the implementation pitfalls in React are framework-specific. SPAs break browser-default focus management on route change; React's render model can strip ARIA attributes during hydration; Portals decouple React tree from DOM tree. These patterns don't exist in vanilla HTML, so they're not in the standard developer checklist.
Does this replace the developer checklist?
No — pair them. The Developer checklist covers WCAG 2.2 AA across all 4 POUR principles (semantic HTML, contrast, keyboard, ARIA, forms, etc). This React checklist covers the specific React integration patterns that surface bugs in those areas. Run both.
Does this work for Next.js, Remix, Gatsby?
Yes — the items apply to any React-based framework. Route-change focus uses the framework's router hook (Next.js useRouter, Remix useNavigation, etc.) instead of React Router, but the underlying behavior is the same. SSR-specific items (hydration, Suspense) apply to Next.js and Remix more than Gatsby's static-export model.
What about React Server Components?
RSCs render on the server, so they hit the same hydration concerns as classic SSR — ARIA attributes from server render must match client. The interactive items (focus management, ARIA state, form handling) all apply to client components inside an RSC tree, no different than in a fully-client React app.
Should I use a UI library like Radix, Headless UI, or React Aria?
Strongly recommended for complex widgets (combobox, menu, dialog, tabs, listbox). These libraries handle the WAI-ARIA Authoring Practices patterns correctly — keyboard navigation, focus traps, ARIA state — which is hours of work per component to get right yourself. Radix and React Aria are the most thorough.
How do I test all this? Manual or automated?
Both. Automated: jest-axe in unit tests, @testing-library/user-event for keyboard flows, focus + ARIA assertions in component tests. Manual: walk every primary flow with a real screen reader (NVDA + Firefox, or VoiceOver + Safari). Automated catches ~30% of issues; manual catches the rest. See the Testing checklist for the full testing flow.
What about Vue, Svelte, or Solid?
The same architectural concerns apply — SPA route changes, dynamic ARIA state, form accessibility — but the framework APIs differ. Per-framework checklists are on the roadmap. Until then, this checklist's concepts (not the React-specific code) transfer cleanly to other frameworks.
Is React 18+ better for accessibility than older versions?
Yes, modestly. useId (React 18) replaces the older error-prone manual ID generation. Concurrent rendering's useTransition makes it easier to manage loading states without stranding focus. Suspense boundaries are more usable. But the bulk of accessibility work remains the same as React 16 — focus management, ARIA, semantic HTML.