Accessibility (a11y)
Trigger phrases: "a11y", "accessibility", "WCAG", "screen reader", "keyboard navigation", "contrast", "ARIA", "keyboard only", "with a keyboard", "keyboard focus", "without a mouse", "focus ring", "tab order", "alt text", "color blind", "colour blind", "voiceover", "talkback", "reduced motion"
Goal: make the interface usable by everyone, including keyboard, screen reader, and low vision. Baseline target: WCAG 2.1 AA.
Stack-agnostic (web/React/RN); do a web search when needed for framework-specific APIs.
Checklist
How
- Start with semantics — the right element solves 80%. Use
button instead of role="button"+div.
- Navigate with the keyboard — drop the mouse, run the whole flow with Tab/Shift-Tab/Enter/Escape; is focus visible and its order sensible.
- Naming — does every interactive element have an accessible name (
aria-label on visual-only icon buttons).
- Contrast — check color pairs against the ratio; don't convey meaning by color alone (add an icon/text).
- Dynamic content — notify the screen reader via a live region (
aria-live); manage modal focus.
- Automated + manual — tools like linters/axe are the baseline; but manual keyboard+reader testing is essential (tools don't catch 100%).
React / RN note
- Web React: semantic element in JSX +
htmlFor/aria-*; use button instead of a clickable div.
- React Native:
accessible, accessibilityLabel, accessibilityRole, accessibilityState (coordinate with frontend-rn-expo).
Invariant rules
- Semantics first, ARIA second — wrong ARIA does harm.
- Must be fully usable by keyboard — without a mouse.
- Color cannot be the sole carrier of meaning.
- Automated tools are not enough — manual keyboard+reader testing.
- Follow the existing design system — if there is a component library, keep its accessible pattern.
1---2name: a11y3description: Frontend accessibility audit (WCAG): semantic HTML, keyboard access, focus management, contrast, ARIA, screen readers. Use when building or changing UI, or before shipping a user-facing screen.4---56# Accessibility (a11y)78<!-- routing-eval reads this line; it lives in the BODY so the always-on skill LISTING stays inside9 Claude Code's budget (1% of the context window) — an overflowing listing gets descriptions10 truncated or dropped, which strips the very keywords a match depends on. -->11Trigger phrases: "a11y", "accessibility", "WCAG", "screen reader", "keyboard navigation", "contrast", "ARIA", "keyboard only", "with a keyboard", "keyboard focus", "without a mouse", "focus ring", "tab order", "alt text", "color blind", "colour blind", "voiceover", "talkback", "reduced motion"1213Goal: make the interface usable by **everyone**, including keyboard, screen reader, and low vision. Baseline target: **WCAG 2.1 AA**.14Stack-agnostic (web/React/RN); do a web search when needed for framework-specific APIs.1516## Checklist17- [ ] **Semantic HTML**: `button`/`a`/`nav`/`main`/`h1..h6` correct; no `div`-buttons18- [ ] **Keyboard**: every interaction reachable via Tab, sensible order, visible **focus ring**19- [ ] **Focus management**: focus moves on modal/route change, focus trap correct20- [ ] **Contrast**: text ≥ 4.5:1, large text ≥ 3:121- [ ] **Alt text**: `alt` on meaningful images; `alt=""` on decorative images22- [ ] **Forms**: every input has a `label`; error message programmatically linked (`aria-describedby`)23- [ ] **ARIA**: only when needed; wrong ARIA is worse than no ARIA; role/name/state correct24- [ ] **Motion/animation**: respect `prefers-reduced-motion`25- [ ] **Language**: `<html lang>` correct (coordinate with i18n)2627## How281. **Start with semantics** — the right element solves 80%. Use `button` instead of `role="button"`+`div`.292. **Navigate with the keyboard** — drop the mouse, run the whole flow with Tab/Shift-Tab/Enter/Escape; is focus visible and its order sensible.303. **Naming** — does every interactive element have an accessible name (`aria-label` on visual-only icon buttons).314. **Contrast** — check color pairs against the ratio; don't convey meaning by color alone (add an icon/text).325. **Dynamic content** — notify the screen reader via a live region (`aria-live`); manage modal focus.336. **Automated + manual** — tools like linters/axe are the baseline; but manual keyboard+reader testing is essential (tools don't catch 100%).3435## React / RN note36- Web React: semantic element in JSX + `htmlFor`/`aria-*`; use `button` instead of a clickable `div`.37- React Native: `accessible`, `accessibilityLabel`, `accessibilityRole`, `accessibilityState` (coordinate with `frontend-rn-expo`).3839## Invariant rules401. **Semantics first, ARIA second** — wrong ARIA does harm.412. Must be **fully usable by keyboard** — without a mouse.423. **Color cannot be the sole carrier of meaning.**434. **Automated tools are not enough** — manual keyboard+reader testing.445. **Follow the existing design system** — if there is a component library, keep its accessible pattern.