Use when a feature needs manual screen-reader testing before sign-off: step-by-step scripts for NVDA, JAWS, VoiceOver or TalkBack with keystrokes and expected announcements, WCAG 2.2 checklists per page type, widget keystroke matrices and a guided session with a signed report.
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Companion reference for screen-reader-test-author. Consult when a component
spec needs explicit a11y acceptance criteria before implementation, when
building an a11y-acceptance gate at design-review time, or for pre-PR
self-review. The checklist pairs with the SKILL.md test narratives for manual
verification and with a11y-violation-gate for automated scans.
Each archetype has its own checklist pattern:
| Archetype | Examples |
|---|---|
| Static text / display | Heading, badge, banner, blockquote. |
| Interactive - single trigger | Button, link, icon button. |
| Interactive - form input | Text input, checkbox, radio, select, switch. |
| Interactive - multi-state | Disclosure, accordion, tabs, popover. |
| Interactive - overlay | Modal, drawer, dropdown menu, command palette. |
| Composite | Combobox, date picker, multi-select, tree. |
| Live region | Toast, alert, in-page status, error banner. |
| Layout / navigation | Header, footer, breadcrumb, pagination. |
wcag-color-contrast).alt=""; meaningful images have
descriptive alt.<button> / <a href> used (no <div onclick>).<button>).aria-label / aria-labelledby if no visible label).aria-pressed).aria-disabled / aria-busy).<label for="..."> OR aria-labelledby referencing a visible
label.required (native) AND a non-color cue.aria-invalid="true" plus an error
message linked via aria-describedby.autocomplete="email", "name", etc.).aria-expanded reflects open/closed state on the trigger.aria-controls references the controlled region's id.hidden attribute or display: none
(NOT visibility: hidden or opacity: 0, which leave the content
focusable).(See wcag-keyboard-navigation references/focus-trap.md for the 6-step
pattern.)
role="dialog" (modal) OR role="alertdialog" (interrupt).aria-modal="true" for modals.aria-labelledby references the dialog's title.inert (or pre-inert focusable cycle).(See aria-authoring-patterns.)
aria-expanded on the trigger.aria-controls linking trigger to the popup.aria-activedescendant (when not moving DOM focus) OR moves DOM
focus into the popup.aria-selected (listbox) or
aria-checked (tree).role="status" (polite) or role="alert" (assertive)
OR aria-live="polite" / "assertive".<header> / <main> / <nav> / <footer> /
<aside>. (One <main> per page.)aria-label (e.g. "Pagination").aria-label="Breadcrumb" and aria-current="page"
on the current page.Beyond the archetype defaults, the spec may declare:
prefers-reduced-motion.Manual-verification items must be emitted as concrete keystrokes and expected announcements - never as a bare skill name. The artifact ships into the user's repo and has to be runnable by a tester holding only that file. Baseline commands (per the NVDA user guide and Apple VoiceOver; same set as SKILL.md Step 3):
| Action | NVDA + Firefox (Windows) | VoiceOver + Safari (macOS) |
|---|---|---|
| Next heading | H | VO (Ctrl+Option) + Cmd + H |
| Next form field | F | VO + Cmd + J |
| Read next / previous item | Down / Up arrow | VO + Right / Left arrow |
| Enter focus mode on a field | Enter | (automatic) |
| Activate the focused control | Enter | VO + Space |
| Element list overlay | - | VO + U (web rotor) |
A step passes when the announcement identifies the element type, reads the visible label verbatim, and conveys state and position-in-set where applicable.
## A11y Checklist - `<ComponentName>`
**Archetype:** Interactive - overlay (modal)
### Required (must pass before merge)
- [ ] Modal has `role="dialog"` and `aria-modal="true"`.
- [ ] Modal title is `aria-labelledby`-referenced.
- [ ] On open: focus moves to first focusable inside modal.
- [ ] Tab cycles within modal; outside content is `inert`.
- [ ] Escape closes; focus returns to trigger.
- [ ] Close button has accessible name "Close" or "Dismiss".
- [ ] Focus indicator on close button at >= 3:1 contrast.
### Per-component (this design adds)
- [ ] Confirmation modal's "Delete" button has `aria-describedby`
linking to the warning text.
- [ ] On confirm: live region announces "Deleted" via
`aria-live="polite"`.
### Verification
- Automated: axe-core scan with `dialog` rule enabled.
- Manual (NVDA + Firefox, Windows): press `Enter` on the trigger -
NVDA announces "Confirm delete, dialog"; `Tab` cycles inside the
dialog and never reaches page content; `Escape` closes and focus
returns to the trigger, announced as "Delete, button".
- Manual (VoiceOver + Safari, macOS): `VO`+`Space` on the trigger,
`VO`+`Right arrow` to walk the dialog contents, `Escape` to
close - same expected announcements.
- Code review: against the checklist above.component: ConfirmModal
archetype: overlay-modal
checks:
- id: AC-MODAL-1
description: Modal has role and aria-modal
severity: blocker
method: automated
rule: axe::role-modal
- id: AC-MODAL-2
description: Focus moves to first focusable on open
severity: blocker
method: e2e-test
framework: playwright
- id: AC-MODAL-3
description: Escape closes; focus restored
severity: blocker
method: e2e-test
- id: AC-MODAL-4
description: Live region announces "Deleted" on confirm
severity: blocker
method: manual
tester_role: a11y-specialist
instructions: >-
NVDA + Firefox (Windows): Tab to "Delete", press Enter.
NVDA must speak "Deleted" from the aria-live="polite" region
without focus moving. VoiceOver + Safari (macOS): VO+Space on
"Delete"; same announcement expected.| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Generic checklist for all components | Static text doesn't need keyboard checks; modal does. | Per-archetype checklist; pick once. |
| Checklist created post-implementation | A11y becomes a retrofit; bugs found late. | Build the checklist from the spec, before implementation. |
| Marking items "won't fix" without rationale | Loss of institutional knowledge; same item resurfaces. | Document each waiver with a date + reviewer initials. |
| One mega-checklist per component (50+ items) | Reviewer fatigue; rubber-stamping. | Per-archetype defaults; only add custom items the design demands. |
wcag-keyboard-navigation, wcag-color-contrast,
aria-authoring-patterns, a11y-violation-gate.