audit-a11y-code
Perform a lightweight, source-code accessibility review on any component or template. No browser required — analysis is static. For live runtime checks, use chrome-inspect-a11y.
Inputs
| Variable |
Description |
Example |
${input:componentPath} |
Path to the component/template file |
src/components/modal/modal.component.html |
${input:context} |
Optional context |
Storybook story route, feature name, Figma frame URL |
Tasks
1. Structural audit
- Verify semantic landmarks:
<main>, <nav>, <header>, <footer>, <aside>, <section aria-label>.
- Check heading order:
h1 → h2 → h3 (no skips, no decorative headings).
- Confirm correct element roles:
<button> for actions, <a href> for navigation, no <div onClick> without role/tabindex.
2. ARIA usage
- Every
aria-labelledby and aria-describedby must reference an existing, visible element id.
aria-label should only be used when there is no visible label.
- No redundant ARIA (e.g.,
<button role="button"> is unnecessary).
aria-hidden="true" must not be applied to focusable elements.
3. Interactive controls
- All focusable elements must have a visible focus indicator.
- Custom interactive elements (
[role="button"], [role="menuitem"], etc.) must be keyboard operable (Enter/Space to activate).
- Dropdowns and menus: Arrow keys for navigation, Escape to close.
- Tab/focus order must follow visual reading order.
4. Dialogs and overlays
- Dialogs require
role="dialog" (or <dialog>), aria-modal="true", and aria-labelledby pointing to a visible title.
- Focus must be trapped inside the dialog when open.
- Escape key must close the dialog.
5. Forms and validation
- Every input must have an associated
<label for> or aria-labelledby.
- Required fields: visible asterisk
* and aria-required="true".
- Error messages: appear adjacent to the input and linked via
aria-describedby or role="alert".
placeholder is not a substitute for a label.
6. Tables
- Data tables use
<th scope="col|row"> for headers.
- Complex tables with multi-level headers use
headers + id associations.
- Add
aria-sort on sortable column headers.
- Layout tables use
role="presentation" to remove table semantics.
7. Media and icons
- Images: meaningful
alt text describing content/function; decorative images use alt="".
- Icon-only buttons:
aria-label or visually hidden text (not tooltip-only).
- SVGs used as images:
role="img" + aria-label or <title> element.
8. Motion and announcements
- Animated content: respects
prefers-reduced-motion media query.
- Status updates (loading, success, error): use
aria-live="polite" or role="status".
- Urgent alerts:
role="alert" or aria-live="assertive" (use sparingly).
9. Contrast (heuristic)
- Text contrast must be ≥ 4.5:1 (AA) for normal text, ≥ 3:1 for large text (≥18pt or 14pt bold).
- UI component boundaries (focus rings, button borders) must be ≥ 3:1 against adjacent colors.
Output Format
✅ Passes
Bullet list of elements/patterns already correctly implemented.
⚠️ Issues
For each problem:
- What: describe the violation
- Where: exact file + element (line number if possible)
- WCAG criterion: e.g., SC 1.3.1, SC 4.1.2
- How to fix: minimal HTML/ARIA snippet
🛠 Recommended fixes (diff-style)
Minimal patches with exact file paths:
- <div (click)="save()">Save</div>
+ <button type="button" (click)="save()">Save</button>
WCAG 2.1 AA Quick Reference
| Criterion |
Requirement |
| 1.1.1 Non-text content |
Alt text for images |
| 1.3.1 Info and relationships |
Semantic structure |
| 1.3.2 Meaningful sequence |
Reading order |
| 1.4.3 Contrast (minimum) |
4.5:1 text, 3:1 large text |
| 1.4.11 Non-text contrast |
3:1 for UI components |
| 2.1.1 Keyboard |
All functionality by keyboard |
| 2.4.3 Focus order |
Logical focus sequence |
| 2.4.7 Focus visible |
Visible focus indicator |
| 3.3.2 Labels or instructions |
Inputs have labels |
| 4.1.2 Name, role, value |
ARIA roles/states correct |
Common Mistakes
- Using
aria-label on non-interactive elements — it only works reliably on interactive and landmark roles.
- Duplicate ids —
aria-labelledby becomes ambiguous; ids must be unique per page.
- Focus trap missing in modals — users can tab outside the dialog to background content.
- Error message not linked — screen readers won't associate the message with the input without
aria-describedby.
1---2name: audit-a11y-code3description: Use when you need a static accessibility review of a component, template, or markup file — checks semantic structure, ARIA usage, keyboard access, forms, tables, and contrast against WCAG 2.1 AA.4---56# audit-a11y-code78Perform a lightweight, source-code accessibility review on any component or template. No browser required — analysis is static. For live runtime checks, use `chrome-inspect-a11y`.910## Inputs1112| Variable | Description | Example |13|----------|-------------|---------|14| `${input:componentPath}` | Path to the component/template file | `src/components/modal/modal.component.html` |15| `${input:context}` | Optional context | `Storybook story route`, `feature name`, `Figma frame URL` |1617## Tasks1819### 1. Structural audit20- Verify semantic landmarks: `<main>`, `<nav>`, `<header>`, `<footer>`, `<aside>`, `<section aria-label>`.21- Check heading order: `h1` → `h2` → `h3` (no skips, no decorative headings).22- Confirm correct element roles: `<button>` for actions, `<a href>` for navigation, no `<div onClick>` without `role`/`tabindex`.2324### 2. ARIA usage25- Every `aria-labelledby` and `aria-describedby` must reference an **existing, visible** element id.26- `aria-label` should only be used when there is no visible label.27- No redundant ARIA (e.g., `<button role="button">` is unnecessary).28- `aria-hidden="true"` must not be applied to focusable elements.2930### 3. Interactive controls31- All focusable elements must have a visible focus indicator.32- Custom interactive elements (`[role="button"]`, `[role="menuitem"]`, etc.) must be keyboard operable (Enter/Space to activate).33- Dropdowns and menus: Arrow keys for navigation, Escape to close.34- Tab/focus order must follow visual reading order.3536### 4. Dialogs and overlays37- Dialogs require `role="dialog"` (or `<dialog>`), `aria-modal="true"`, and `aria-labelledby` pointing to a visible title.38- Focus must be trapped inside the dialog when open.39- Escape key must close the dialog.4041### 5. Forms and validation42- Every input must have an associated `<label for>` or `aria-labelledby`.43- Required fields: visible asterisk `*` **and** `aria-required="true"`.44- Error messages: appear adjacent to the input and linked via `aria-describedby` or `role="alert"`.45- `placeholder` is not a substitute for a label.4647### 6. Tables48- Data tables use `<th scope="col|row">` for headers.49- Complex tables with multi-level headers use `headers` + `id` associations.50- Add `aria-sort` on sortable column headers.51- Layout tables use `role="presentation"` to remove table semantics.5253### 7. Media and icons54- Images: meaningful `alt` text describing content/function; decorative images use `alt=""`.55- Icon-only buttons: `aria-label` or visually hidden text (not tooltip-only).56- SVGs used as images: `role="img"` + `aria-label` or `<title>` element.5758### 8. Motion and announcements59- Animated content: respects `prefers-reduced-motion` media query.60- Status updates (loading, success, error): use `aria-live="polite"` or `role="status"`.61- Urgent alerts: `role="alert"` or `aria-live="assertive"` (use sparingly).6263### 9. Contrast (heuristic)64- Text contrast must be ≥ 4.5:1 (AA) for normal text, ≥ 3:1 for large text (≥18pt or 14pt bold).65- UI component boundaries (focus rings, button borders) must be ≥ 3:1 against adjacent colors.6667## Output Format6869### ✅ Passes70Bullet list of elements/patterns already correctly implemented.7172### ⚠️ Issues73For each problem:74- **What:** describe the violation75- **Where:** exact file + element (line number if possible)76- **WCAG criterion:** e.g., SC 1.3.1, SC 4.1.277- **How to fix:** minimal HTML/ARIA snippet7879### 🛠 Recommended fixes (diff-style)80Minimal patches with exact file paths:81```diff82- <div (click)="save()">Save</div>83+ <button type="button" (click)="save()">Save</button>84```8586## WCAG 2.1 AA Quick Reference8788| Criterion | Requirement |89|-----------|-------------|90| 1.1.1 Non-text content | Alt text for images |91| 1.3.1 Info and relationships | Semantic structure |92| 1.3.2 Meaningful sequence | Reading order |93| 1.4.3 Contrast (minimum) | 4.5:1 text, 3:1 large text |94| 1.4.11 Non-text contrast | 3:1 for UI components |95| 2.1.1 Keyboard | All functionality by keyboard |96| 2.4.3 Focus order | Logical focus sequence |97| 2.4.7 Focus visible | Visible focus indicator |98| 3.3.2 Labels or instructions | Inputs have labels |99| 4.1.2 Name, role, value | ARIA roles/states correct |100101## Common Mistakes102- **Using `aria-label` on non-interactive elements** — it only works reliably on interactive and landmark roles.103- **Duplicate ids** — `aria-labelledby` becomes ambiguous; ids must be unique per page.104- **Focus trap missing in modals** — users can tab outside the dialog to background content.105- **Error message not linked** — screen readers won't associate the message with the input without `aria-describedby`.