Audit the UI in $ARGUMENTS against WCAG 2.2 Level AA and report every violation with its fix. This is read-only: do not edit files.
Scope
- If $ARGUMENTS names a file, component, or route, audit that. If empty, audit the UI touched by the current diff (
git diff --name-only HEADfiltered to markup/component files); if that is empty, audit the UI files changed in the last commit (git diff --name-only HEAD~1 HEAD). - First, detect the stack and conventions: framework (React/Vue/Svelte/Angular/plain HTML), the styling system (Tailwind, CSS Modules, styled-components, design tokens), and any existing a11y utilities, ESLint plugins (jsx-a11y), or component library primitives. Map issues to how THIS project already does things; do not propose a foreign pattern.
- Trace each component to the actual rendered DOM (follow wrappers,
asprops, and slots) before judging — a<Button>may render a real<button>or a<div>.
Checks (run all, cite the specific element)
- Semantic HTML: real
<button>/<a href>for actions/links, not<div onClick>. Headings nest in order with no skipped levels (h1→h2→h3, never h2→h4). Landmarks (<main>,<nav>,<header>) present, and each<nav>/<main>labeled if repeated. Lists for list-shaped content.<a>for navigation,<button>for in-page actions. - Names & labels: every control has an accessible name (visible
<label for>, wrapping label,aria-label, oraria-labelledby). Icon-only buttons named. No placeholder-as-label.<img>hasalt(emptyalt=""for decorative, descriptive text for meaningful, not "image of"). - Keyboard: everything operable via Tab/Enter/Space/Esc/arrows per role. Visible focus indicator (contrast >=3:1, not
outline:nonewithout replacement). Logical tab order, no positivetabindex. No keyboard traps; modals trap intentionally and restore focus on close. Custom widgets follow the WAI-ARIA Authoring Practices keyboard pattern. - ARIA: prefer native elements over ARIA. If ARIA is used, role is valid, required states present (
aria-expanded,aria-selected,aria-checked), no invalid or contradictory attributes, noaria-hiddenon focusable content. Live regions for async status. - Color & contrast: text >=4.5:1 (>=3:1 for >=24px or >=19px bold), UI components/graphics >=3:1. Compute ratios from the actual token/hex values, resolving CSS variables. Information never conveyed by color alone (add text, icon, or pattern).
- Forms: inputs programmatically associated with labels. Errors linked via
aria-describedbyand marked witharia-invalid; error text is specific, not color-only. Required state exposed. Related radios/checkboxes in a<fieldset>/<legend>. - Motion & responsive: animations/auto-play respect
prefers-reduced-motion. Content reflows without horizontal scroll at 320px; nouser-scalable=no. Target size >=24x24px (WCAG 2.2 SC 2.5.8). - Page-level & content: root has a valid
lang(SC 3.1.1) and any inline language shift is marked (SC 3.1.2); routed/<head>title is unique and descriptive (SC 2.4.2); link text states its purpose in or near itself, no bare "click here"/"read more" (SC 2.4.4); tooltip/popover content on hover or focus is dismissable, hoverable, and persistent (SC 1.4.13).
Output
Group by severity: Critical (blocks a user), Serious, Moderate. For each finding, one entry:
- Element:
file:lineand the selector/snippet. - Criterion: WCAG SC number, name, and its real level (e.g. 1.4.3 Contrast (Minimum) — AA, or 4.1.2 Name, Role, Value — A). Both A and AA failures count, since AA conformance requires meeting every A criterion too.
- Why it fails: the concrete user impact (which assistive tech / interaction breaks).
- Fix: exact code change in this project's idiom (show the corrected snippet).
End with a one-line summary count per severity. If a check needs runtime verification you cannot do statically (computed contrast against images, focus order in the live DOM), say so explicitly and give the manual step.
Rules
- Never invent violations to pad the list; report only what the code actually exhibits. If clean, say so.
- Never recommend
role/aria-*where a native element does the job. - Always quote the real WCAG 2.2 SC number and level; never write "accessibility best practice" as a justification.
- Cite line numbers you actually read; do not guess locations.