accessibility-review · git:20260718.7c1285c · 2026-07-18 · sha256 b42a41b804ef320e

accessibility-review git:20260718.7c1285cA

Immutable. This exact content is served forever at /api/v1/blob/b42a41b804ef320e.

---
name: accessibility-review
description: Audit a UI for real accessibility, keyboard-first, with concrete failures and fixes rather than checkbox compliance. Use when reviewing or building any user interface.
---

# Accessibility review

Accessibility is whether real people can use the thing: with a keyboard, a
screen reader, low vision, or a tremor: not whether a linter is quiet.
Audit by use, report by failure.

## Method

1. **Walk the keyboard path first.** Unplug the mouse mentally and complete
   the page's primary task with Tab, Shift+Tab, Enter, Space, Escape, and
   arrows. Every failure is a finding:
   - Focus that vanishes (no visible indicator) or lands somewhere absurd.
   - Interactive things you cannot reach (`div onclick` without `tabindex`
     and key handling: a native `<button>` fixes all of it at once).
   - Traps: modals you cannot Escape, menus that swallow Tab.
   - Order that jumps around the visual layout.
2. **Read the page as the accessibility tree.** Every control needs an
   accessible name (visible label, `aria-label`, or `alt`); every input a
   programmatic label (`for`/`id` or wrapping); images `alt` text that says
   what matters (`alt=""` for decoration); headings a real hierarchy
   (one `h1`, no skipped levels: structure, not styling).
3. **Check state and change announcements.** Toggles carry `aria-pressed`
   or `aria-expanded`; errors are associated with their field
   (`aria-describedby`), not floating red text; async updates that matter
   (saved, failed, loading) reach `aria-live` regions; the modal traps
   focus in and returns it on close.
4. **Check the visual floor.** Text contrast 4.5:1 (3:1 for large text and
   UI parts); information never carried by color alone (the red/green dot
   needs a label); layout survives 200% zoom; animation respects
   `prefers-reduced-motion`; touch targets are not miniature.
5. **Report by task, ranked by exclusion.** "A keyboard user cannot send a
   message" is a blocker; "the decorative divider is announced" is minor.
   Each finding: who is excluded, where, the failing behavior, the concrete
   fix: which is usually *use the native element*.

## Rules

- Native elements first (`button`, `a`, `label`, `select`, `dialog`);
  ARIA is the patch, not the plan. Wrong ARIA is worse than none.
- Test the actual behaviors, not the attribute presence: `aria-label=""`
  passes a grep and fails a person.
- Accessibility notes belong in the same review as everything else, at the
  same severity scale. A blocker is a blocker.