Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 129 additions & 2 deletions .claude/skills/a11y-audit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,132 @@ name: claude-a11y-audit
description: Use when reviewing UI diffs, accessibility audits, or flaky UI tests to catch a11y regressions, semantic issues, keyboard/focus problems, and to recommend minimal fixes plus role-based test selectors.
---

This skill is shared. Read the canonical skill at:
../../../skills/a11y-audit/SKILL.md
# Accessibility Change Audit

Brief purpose: review UI changes for accessibility regressions and missing improvements, then propose minimal fixes tied to the diff.

## Overview

This skill audits UI diffs for semantics, keyboard access, focus management, ARIA correctness, contrast, and testability. It is diff-first: only evaluate changed lines and their immediate context.

## Prerequisites

- A diff, PR, or change list that includes relevant UI files.
- Optional: a screenshot or description of the changed UI state.

## Instructions

### Step 1: Scope the audit to the diff

Identify changed UI elements, interactions, and styles. Ignore unrelated files.

### Step 2: Run the diff-first checklist

Focus on changes that alter semantics, interaction, or visual affordances.

### Step 3: Produce findings and minimal fixes

Tie each issue to a specific change and propose the smallest reasonable fix.

### Step 4: Improve test reliability

Recommend role- and name-based queries for tests instead of data or class selectors.

## Audit Checklist (Diff-First)

Semantics and structure

- Headings follow order and are not skipped.
- Interactive elements are buttons/links, not divs/spans.
- Landmarks are present for new regions (main, nav, header, footer, aside).
- Lists and tables use correct elements (ul/ol/li, th/thead/tbody).

Labels and names

- Inputs have labels or aria-label/aria-labelledby.
- Icon-only controls have accessible names.
- Helper text ties to inputs via aria-describedby.

Keyboard and focus

- All interactive elements are keyboard reachable and operable.
- Focus order follows DOM order (avoid tabIndex > 0).
- Dialogs/menus trap focus and return focus to trigger.

ARIA correctness

- ARIA only when native semantics are insufficient.
- aria-expanded/controls/pressed reflect actual state.
- role is correct and not redundant.

Visual and motion

- Text and focus indicators meet contrast requirements.
- Color is not the only indicator.
- Motion respects reduced-motion preferences.

Media and imagery

- Images have meaningful alt or empty alt for decorative.
- Media controls are accessible and labeled.

Testing reliability

- New elements can be found by role and accessible name.
- Interaction tests use user flows and semantic queries.

## Minimal Fix Patterns

1. Icon-only button

- Add visible text or aria-label.

2. Clickable non-button

- Convert to <button> or add role="button", tabIndex=0, and Enter/Space handling.

3. Form label

- Add <label htmlFor> or aria-labelledby and connect helper text with aria-describedby.

4. Disclosure

- Toggle uses aria-expanded and aria-controls; update on state change.

5. Dialog

- Use role="dialog", aria-modal, label by heading, and return focus on close.

## Output Format

Findings (ordered by severity):

- [severity] path:line - problem and impact
Fix: minimal change suggestion

Tests:

- Recommend updates that use role/name queries and user-driven events.

UX/Speed Note:

- Call out any change that impacts perceived speed (layout shifts, heavy DOM, over-rendering).

Severity scale: blocker, high, medium, low.

## Example Review Output

Findings:

- high `packages/web/src/views/Example.tsx:42` - Clickable div lacks keyboard support; keyboard users cannot activate it.
Fix: convert to <button type="button"> or add role, tabIndex, and Enter/Space handlers.
- medium `packages/web/src/views/Example.tsx:60` - Icon-only control has no accessible name.
Fix: add aria-label="Add event".

Tests:

- Add a role-based query: getByRole("button", { name: /add event/i }).

UX/Speed Note:

- No layout shift detected; DOM complexity unchanged.
136 changes: 134 additions & 2 deletions .codex/skills/a11y-audit/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,139 @@
---
name: codex-a11y-audit
description: Use when reviewing UI diffs, accessibility audits, or flaky UI tests to catch a11y regressions, semantic issues, keyboard/focus problems, and to recommend minimal fixes plus role-based test selectors.
version: 1.0.0
tags:
- accessibility
- ui
- testing
---

This skill is shared. Read the canonical skill at:
../../../skills/a11y-audit/SKILL.md
# Accessibility Change Audit

Brief purpose: review UI changes for accessibility regressions and missing improvements, then propose minimal fixes tied to the diff.

## Overview

This skill audits UI diffs for semantics, keyboard access, focus management, ARIA correctness, contrast, and testability. It is diff-first: only evaluate changed lines and their immediate context.

## Prerequisites

- A diff, PR, or change list that includes relevant UI files.
- Optional: a screenshot or description of the changed UI state.

## Instructions

### Step 1: Scope the audit to the diff

Identify changed UI elements, interactions, and styles. Ignore unrelated files.

### Step 2: Run the diff-first checklist

Focus on changes that alter semantics, interaction, or visual affordances.

### Step 3: Produce findings and minimal fixes

Tie each issue to a specific change and propose the smallest reasonable fix.

### Step 4: Improve test reliability

Recommend role- and name-based queries for tests instead of data or class selectors.

## Audit Checklist (Diff-First)

Semantics and structure

- Headings follow order and are not skipped.
- Interactive elements are buttons/links, not divs/spans.
- Landmarks are present for new regions (main, nav, header, footer, aside).
- Lists and tables use correct elements (ul/ol/li, th/thead/tbody).

Labels and names

- Inputs have labels or aria-label/aria-labelledby.
- Icon-only controls have accessible names.
- Helper text ties to inputs via aria-describedby.

Keyboard and focus

- All interactive elements are keyboard reachable and operable.
- Focus order follows DOM order (avoid tabIndex > 0).
- Dialogs/menus trap focus and return focus to trigger.

ARIA correctness

- ARIA only when native semantics are insufficient.
- aria-expanded/controls/pressed reflect actual state.
- role is correct and not redundant.

Visual and motion

- Text and focus indicators meet contrast requirements.
- Color is not the only indicator.
- Motion respects reduced-motion preferences.

Media and imagery

- Images have meaningful alt or empty alt for decorative.
- Media controls are accessible and labeled.

Testing reliability

- New elements can be found by role and accessible name.
- Interaction tests use user flows and semantic queries.

## Minimal Fix Patterns

1. Icon-only button

- Add visible text or aria-label.

2. Clickable non-button

- Convert to <button> or add role="button", tabIndex=0, and Enter/Space handling.

3. Form label

- Add <label htmlFor> or aria-labelledby and connect helper text with aria-describedby.

4. Disclosure

- Toggle uses aria-expanded and aria-controls; update on state change.

5. Dialog

- Use role="dialog", aria-modal, label by heading, and return focus on close.

## Output Format

Findings (ordered by severity):

- [severity] path:line - problem and impact
Fix: minimal change suggestion

Tests:

- Recommend updates that use role/name queries and user-driven events.

UX/Speed Note:

- Call out any change that impacts perceived speed (layout shifts, heavy DOM, over-rendering).

Severity scale: blocker, high, medium, low.

## Example Review Output

Findings:

- high `packages/web/src/views/Example.tsx:42` - Clickable div lacks keyboard support; keyboard users cannot activate it.
Fix: convert to <button type="button"> or add role, tabIndex, and Enter/Space handlers.
- medium `packages/web/src/views/Example.tsx:60` - Icon-only control has no accessible name.
Fix: add aria-label="Add event".

Tests:

- Add a role-based query: getByRole("button", { name: /add event/i }).

UX/Speed Note:

- No layout shift detected; DOM complexity unchanged.
8 changes: 4 additions & 4 deletions .cursorrules/accessibility.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Accessibility standards - semantic HTML, keyboard navigation, ARIA labels, refer to skills/a11y-audit/SKILL.md for comprehensive checklist
description: Accessibility standards - semantic HTML, keyboard navigation, ARIA labels, refer to .codex/skills/a11y-audit/SKILL.md for comprehensive checklist
globs:
- "packages/web/**/*.{ts,tsx}"
---
Expand All @@ -23,7 +23,7 @@ Follow accessibility best practices to ensure the application is usable by every
## Detailed Guidelines

Refer to the comprehensive accessibility audit checklist in:
**`skills/a11y-audit/SKILL.md`**
**`.codex/skills/a11y-audit/SKILL.md`**

This skill provides:

Expand Down Expand Up @@ -131,7 +131,7 @@ This aligns with the testing standards in `testing.md`.
## Audit Checklist Reference

For comprehensive review of UI changes, refer to:
**`skills/a11y-audit/SKILL.md`**
**`.codex/skills/a11y-audit/SKILL.md`**

Key sections:

Expand All @@ -157,4 +157,4 @@ Review these for accessibility patterns:
- Support keyboard navigation (Tab, Enter, Space)
- Use ARIA when needed (`aria-expanded`, `aria-label`, `role`)
- Test with semantic queries (`getByRole`, `getByLabelText`)
- Refer to `skills/a11y-audit/SKILL.md` for detailed guidance
- Refer to `.codex/skills/a11y-audit/SKILL.md` for detailed guidance
Loading