A /a11y Claude Code skill that looks at a live page, figures out what UI components are on it, and generates Playwright tests for their keyboard accessibility behavior.
Dialog is the first pattern. The design is meant to grow — each new pattern (menu, combobox, tooltip, etc.) adds one contract file and the rest of the framework reuses it.
You run /a11y on a page. Claude scans every interactive trigger, scores what it finds against known pattern signals, decides what each component is supposed to be, then asks you to confirm before writing tests.
The output is a Playwright test file that checks the behaviors keyboard users depend on — focus moves in on open, Tab stays inside, Escape closes, focus returns to the trigger.
Scan first, reason second. A Node script clicks every trigger on the page before Claude is involved. It records raw signals (ARIA role, backdrop, scroll lock, inert, z-index, focusable children, etc.) as JSON. Claude reads that, not the live DOM.
Pattern contracts. Each pattern is a .ts file in .claude/skills/a11y/ that declares how to recognize it, what variants exist, what behaviors to expect, and how to score confidence. It's declarative — never executed at runtime, just read as context.
Reproducible scoring. Each contract has a DetectionRubric — a table of signals and weights. Claude sums matched weights to get a detectionScore and maps it to High / Medium / Low confidence. Same page, same score every time.
Human in the loop. Claude prints a plain-English report of what it found and waits for approval before writing any files.
.claude/skills/a11y.md the skill — what Claude does, step by step
.claude/skills/a11y/dialog.pattern.ts dialog contract (first pattern; others follow the same shape)
scripts/a11y-scan.js pre-scan script — runs before Claude
fixtures/dialog/ test fixtures: accessible, inaccessible, false-positives, library examples
tests/a11y/ generated and hand-written Playwright tests