Accessibility QA
Make your app usable by everyone: keyboard, contrast, labels, focus, and screen-reader basics.
The route
5 steps to Done
- 01
Keyboard-only audit
Unplug the mouse: can you use the whole app?
Preview prompt + verify gate ▾ Hide ▴
Audit the entire app using only the keyboard. Tab through every page: record every interactive element that cannot be reached, cannot be activated (Enter/Space), or has no visible focus indicator; note tab order absurdities; test Escape on dismissibles; attempt the core journey end to end by keyboard. Produce the issue table: element -> problem -> page.
- ✓ Every page was tabbed through
- ✓ The core journey was attempted by keyboard
- ✓ Focus visibility was checked per element
- 02
Fix keyboard operability
Everything clickable must be tabbable, activatable, and visibly focused.
Preview prompt + verify gate ▾ Hide ▴
Fix every keyboard issue. Requirements: replace click-divs with buttons/links (or add tabindex and key handlers where unavoidable); ensure Enter/Space activates controls; add a visible focus style consistent with the design (never remove outlines without replacement); fix tab order via DOM order; make dismissibles respond to Escape. Re-run the keyboard core journey to verify.
- ✓ All controls reachable and activatable
- ✓ Focus indicators visible everywhere
- ✓ The core journey passes keyboard-only
- 03
Contrast and visual pass
Text people cannot read is text that does not exist.
Preview prompt + verify gate ▾ Hide ▴
Audit and fix contrast. Check every text style (body, muted, labels, placeholders, buttons, links) against its background for WCAG AA (4.5:1 normal, 3:1 large) - report the failing pairs with their ratios; check UI element contrast (borders, icons, focus rings) at 3:1; check state-dependent text (disabled, errors, success). Fix failures by adjusting the tokens, not one-off overrides, and re-report the ratios.
- ✓ Failing pairs were measured with ratios
- ✓ Fixes applied at token level
- ✓ Error/success/muted text re-verified
- 04
Names, semantics, and structure
Assistive tech needs names and structure to navigate.
Preview prompt + verify gate ▾ Hide ▴
Fix semantics and naming. Requirements: every icon-only button gets an accessible name (aria-label); images get meaningful alt (or empty alt if decorative); heading levels form a sane hierarchy per page (one h1, no skips); landmarks (nav/main) present; links say where they go (no naked 'click here'); dynamic status messages (toasts, errors) use live regions where they matter. Verify with the accessibility tree inspector per page.
- ✓ No unnamed interactive elements in the accessibility tree
- ✓ Heading hierarchy is sane per page
- ✓ Toasts/errors are announced
- 05
Focus management and forms
The dynamic layer: modals, updates, and error handling must guide focus.
Preview prompt + verify gate ▾ Hide ▴
Fix focus management and forms. Modals/drawers: focus moves in on open, stays trapped inside, returns to the trigger on close. Forms: every input has a programmatically associated label; errors are visible, specific, and associated with their fields (aria-describedby); on failed submit, focus moves to the first error; required fields communicated. Route changes: focus/announce the new page context. Verify each behavior by keyboard.
- ✓ Modal focus traps and restores
- ✓ Every input has a real label
- ✓ Failed submit focuses the first error