# WCAG manual checklist

Automation (axe on every story — WP-01; template a11y lint — WP-17; the form-field/alert
play tests — WP-16) catches structural and component-level issues. It cannot catch
cross-page flows: tab order across a whole page, focus traps, zoom/reflow, or how a
screen reader actually narrates a journey. This checklist is the manual complement —
a living doc, filled in per page as it's walked, not a one-time sign-off.

See `src/docs/a11y.mdx` (Storybook → Foundations → Accessibility) for how this fits
with the automated layers.

## How to run a page through this checklist

1. **Keyboard walk**: `Tab`/`Shift+Tab` through the whole page. Every interactive
   element reachable, in a sensible order, with a visible focus ring; no trap (you can
   always tab back out).
2. **No traps**: a modal/dropdown/menu, if present, returns focus on close/`Escape`.
3. **200% zoom / reflow**: browser zoom to 200% (or a 320px-wide viewport). Content
   reflows to one column; nothing is clipped or requires horizontal scroll.
4. **Screen reader pass**: NVDA (Windows) or VoiceOver (macOS) — navigate by heading
   and by tab; confirm labels, descriptions, and error announcements are heard, not
   just visible.
5. **Visible focus**: every focused element has a visible indicator (no
   `outline: none` without a replacement).
6. **Error announcement**: submitting an invalid form announces the error (this is
   what WP-16's `role="alert"` + `aria-describedby` wiring is for) — confirm it's
   actually heard, not just present in the DOM.

## Status

Legend: ✅ pass · ⚠️ pass with notes · ❌ fails · — not yet walked

| Page                       | Keyboard walk | No traps | 200% zoom/reflow | Screen reader | Visible focus | Error announcement |
| -------------------------- | :-----------: | :------: | :--------------: | :-----------: | :-----------: | :----------------: |
| Login (`/login`)           |      ✅       |    ✅    |        ✅        |       —       |      ✅       |        n/a¹        |
| Dashboard (`/dashboard`)   |       —       |    —     |       ❌²        |       —       |       —       |         —          |
| Registratie wizard         |       —       |    —     |        —         |       —       |      ✅³      |        ✅³         |
| Herregistratie wizard      |       —       |    —     |        —         |       —       |       —       |         —          |
| Brief (letter composition) |       —       |    —     |        —         |       —       |       —       |         —          |

¹ Login's demo form has no client-side validation/error state to exercise.
² **Real finding, not fixed here**: `aanvraag-block`'s warning `app-alert` (two
`app-button` actions) overflows the viewport at a 320px width — its `.feedback` flex
row doesn't wrap, pushing the second button past the edge. Fixing it is a genuine
CSS change to a live component, which is exactly the "full manual audit" scope this
WP defers (see Out of scope) — logged here instead of silently fixed or silently
ignored.
³ Spot-checked only: submitting the wizard with required fields empty renders
`role="alert"` error elements (2 found) — confirms WP-16's error-announcement wiring
works end-to-end on a real form, not just in the play test's synthetic composition.
Full keyboard walk / zoom / screen-reader pass on this page not yet done.

"Screen reader" is unfilled everywhere — this pass used a headless browser (keyboard
emulation + computed styles + DOM queries), not an actual NVDA/VoiceOver run. Don't
read the automation above as a substitute for that row; it isn't one.

Filling in the remaining rows (and fixing finding ²) is ongoing work (WP-17's
out-of-scope note) — this table makes what's been checked, and what hasn't, visible
rather than assumed.
