← LeaderboardThe Skill Leaderboard

design-qa

Use when a UI screen, page or component is about to be called done, handed off or shipped, or when generated UI looks generic or half-finished. Gates the rendered result, not the design file - finds controls that do nothing, placeholder copy, removed focus rings, missing loading/empty/error states, low contrast, small targets, hidden focus and broken reflow measured in the real browser, and flags template defaults without blocking on taste.

Published by alirezarezvani ↗alirezarezvani/claude-skills

Try your first task

A source-grounded starter task has not been verified for this skill yet.

SKILL.md

name: design-qadescription: Use when a UI screen, page or component is about to be called done, handed off or shipped, or when generated UI looks generic or half-finished. Gates the rendered result, not the design file - finds controls that do nothing, placeholder copy, removed focus rings, missing loading/empty/error states, low contrast, small targets, hidden focus and broken reflow measured in the real browser, and flags template defaults without blocking on taste.argument-hint: "[UI source path | state matrix CSV | rendered snapshot JSON | URL to capture]"license: MITmetadata:   version: 1.0.0  build_pattern: "Three deterministic stdlib scripts (source finish lint, interaction-state matrix, rendered snapshot audit) with blocking exit codes, plus a read-only browser collector and an optional Playwright keyboard pass; WCAG 2.2 AA thresholds for contrast, focus, reflow, names and target size; template traits from Anthropic's frontend-design skill as warnings only"  distinct_from: "a11y-audit (source-level WCAG scan: alt text, labels, ARIA, headings); ui-design-system (generates tokens and components); ux-researcher-designer (research); epic-design and frontend-design (make the design, this checks the build)"

Design QA

Portability: 3 stdlib Python scripts, no network. The browser collector is plain JavaScript; the keyboard pass needs Playwright in your own project. This checks the build, not the taste. Objective defects block; template defaults only warn, because the brief may ask for them.

Screens get reviewed in a static, populated, happy-path frame and ship with a button wired to () => {}, an empty state that says "Lorem ipsum", and a focus ring someone removed. Each script catches one class of these before a user does.

Workflow

# 1 - Source: is anything unfinished in the code?
python scripts/finish_lint.py src/ --output json > lint.json
# 2 - States: does every surface have loading, empty, error, busy, focus...?
python scripts/state_matrix_checker.py --matrix states.csv --evidence-root .
# 3 - Rendered: what did the browser actually show? (capture 320 px and desktop)
node assets/capture_snapshot.mjs http://localhost:3000/invoices --width 320 --out s320.json
python scripts/rendered_audit.py --snapshot s320.json --waivers waivers.csv

Step 1 blocks on inert handlers, dead links, placeholder copy and focus outlines removed without a replacement. It warns on sample data, token drift and each template trait it finds, and rates generic risk LOW, MEDIUM or HIGH.

Step 2 derives required states from each surface's kind (data_view, form, action, control, media, page). An unlisted state counts as missing, and DONE without evidence is reported. Start from assets/states.example.csv.

Step 3 reads a snapshot of the rendered page and blocks on WCAG 2.2 AA failures: text contrast, no focus indicator, focus obscured, reflow at 320 px, empty accessible names and targets under 24×24 px without the spacing exception. Contrast is composited through translucent layers and opacity, so a token that passes on white but fails inside a tinted card is caught. Repeated rows are grouped. No Playwright? Paste assets/collect_snapshot.js into the DevTools console and run copy(JSON.stringify(designQaSnapshot())). Focus results are then unverified rather than passed.

Capture one snapshot per key state (empty, error, long content), not just the populated page. Fill assets/finish_signoff.md from the three runs.

Hard rules

  • Unlisted is missing. A state nobody wrote down was not built.
  • Measure the render, not the CSS. Contrast on a real background beats a declared colour pair.
  • Never block on taste. Template traits warn. Record in the sign-off whether the brief asks for the look.
  • A waiver names the WCAG exception or a ticket. The scripts reject a waiver or NA with no reason.
  • Unverified is not pass. Text on a gradient or focus from script focus is checked by hand or with the keyboard pass.
  • Not an accessibility conformance claim. The checks cover what can be measured. A screen-reader pass and a11y-audit cover the rest.

Scripts

ScriptRoleExit codes
scripts/finish_lint.pyInert controls, dead links, placeholder copy, removed focus, template traits, token drift0 clean · 2 findings · 3 bad input · 4 blocked
scripts/state_matrix_checker.pyRequired states per surface kind, evidence and NA reasons0 complete · 2 · 3 · 4 blocked
scripts/rendered_audit.pyContrast, focus, target size, names, clipping, reflow from a snapshot0 clean · 2 · 3 · 4 blocked

All support --help, --sample and --output json.

References and assets

design-qa by alirezarezvani · The Skill Leaderboard