Agents accessibility-audit
Audit design components and generated code for WCAG 2.1 compliance including color contrast, touch targets, and screen reader compatibility
install
source · Clone the upstream repo
git clone https://github.com/aRustyDev/agents
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/aRustyDev/agents "$T" && mkdir -p ~/.claude/skills && cp -r "$T/content/plugins/frontend/design-to-code/skills/accessibility-audit" ~/.claude/skills/arustydev-agents-accessibility-audit && rm -rf "$T"
manifest:
content/plugins/frontend/design-to-code/skills/accessibility-audit/SKILL.mdsource content
Accessibility Audit
Audit design components and generated code for WCAG 2.1 compliance. Check color contrast, touch targets, screen reader compatibility, and keyboard navigation.
WCAG Compliance Levels
| Level | Description | Target |
|---|---|---|
| A | Minimum accessibility | Required |
| AA | Standard compliance | Recommended |
| AAA | Enhanced accessibility | Aspirational |
Color Contrast
Requirements
| Element | WCAG Level | Ratio |
|---|---|---|
| Normal text | AA | 4.5:1 |
| Large text (18px+) | AA | 3:1 |
| UI components | AA | 3:1 |
| Enhanced (AAA) | AAA | 7:1 |
Checking Contrast
Using design tokens:
function getContrastRatio(color1, color2) { const l1 = getLuminance(color1); const l2 = getLuminance(color2); const lighter = Math.max(l1, l2); const darker = Math.min(l1, l2); return (lighter + 0.05) / (darker + 0.05); } function getLuminance(hex) { const rgb = hexToRgb(hex); const [r, g, b] = rgb.map(c => { c = c / 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); }); return 0.2126 * r + 0.7152 * g + 0.0722 * b; }
Audit Report Format:
## Color Contrast Audit ### Passing | Pair | Foreground | Background | Ratio | Level | |------|------------|------------|-------|-------| | Text on surface | #1A1A1A | #FFFFFF | 16.1:1 | AAA | | Primary button | #FFFFFF | #2196F3 | 4.6:1 | AA | ### Failing | Pair | Foreground | Background | Ratio | Required | Fix | |------|------------|------------|-------|----------|-----| | Muted text | #999999 | #F5F5F5 | 2.8:1 | 4.5:1 | Darken to #666666 | | Disabled | #CCCCCC | #FFFFFF | 1.6:1 | 3:1 | Darken to #949494 |
Automated Tools
# Install color contrast checker npm install -g color-contrast-checker # Check specific colors contrast-check "#1A1A1A" "#FFFFFF" # Audit CSS file npx color-contrast-audit ./styles.css
Touch Targets
Requirements
| Platform | Minimum Size | Recommended |
|---|---|---|
| iOS | 44×44 pt | 48×48 pt |
| Android | 48×48 dp | 56×56 dp |
| Web | 44×44 px | 48×48 px |
Checking Touch Targets
Component Audit:
## Touch Target Audit ### Compliant | Component | Size | Platform | Status | |-----------|------|----------|--------| | Button | 48×48 | All | ✓ | | ListItem | 56×48 | All | ✓ | | Checkbox | 44×44 | All | ✓ | ### Non-Compliant | Component | Current | Required | Fix | |-----------|---------|----------|-----| | IconButton | 32×32 | 44×44 | Add padding | | CloseButton | 24×24 | 44×44 | Increase hit area | | Link (inline) | 16×16 | 44×44 | Add touch padding |
Implementation Fixes
SwiftUI:
// Bad: Small touch target Image(systemName: "xmark") .frame(width: 24, height: 24) // Good: Adequate touch target Image(systemName: "xmark") .frame(width: 44, height: 44) .contentShape(Rectangle())
React:
// Bad: Small touch target <button className="w-6 h-6">×</button> // Good: Visual + touch area separated <button className="w-11 h-11 flex items-center justify-center"> <span className="w-6 h-6">×</span> </button>
Screen Reader Compatibility
Requirements
- All interactive elements must have accessible names
- Images must have alt text (or be decorative)
- Form inputs must have labels
- Dynamic content must be announced
Audit Checklist
## Screen Reader Audit ### Images | Image | Alt Text | Status | |-------|----------|--------| | logo.png | "Company Logo" | ✓ | | hero.jpg | "Team collaboration" | ✓ | | icon-arrow.svg | "" (decorative) | ✓ | | product.png | Missing | ✗ Fix: Add alt | ### Interactive Elements | Element | Accessible Name | Source | |---------|-----------------|--------| | Submit button | "Submit form" | Content | | Close button | "Close dialog" | aria-label | | Search input | "Search products" | Label element | | Nav menu | Missing | ✗ Fix: Add aria-label | ### Dynamic Content | Update | Announcement | Status | |--------|--------------|--------| | Form error | role="alert" | ✓ | | Toast | aria-live="polite" | ✓ | | Loading | "Loading..." | ✗ Fix: Add aria-busy |
ARIA Implementation
Required Attributes:
<!-- Buttons with icons only --> <button aria-label="Close dialog"> <svg>...</svg> </button> <!-- Form inputs --> <label for="email">Email</label> <input id="email" type="email" aria-describedby="email-hint"> <span id="email-hint">We'll never share your email</span> <!-- Dynamic regions --> <div role="status" aria-live="polite"> {statusMessage} </div>
Keyboard Navigation
Requirements
- All interactive elements reachable via Tab
- Visible focus indicators
- Logical tab order
- Escape closes modals/dialogs
- Arrow keys for menus/lists
Focus Indicators
Requirements:
| Property | Minimum | Recommended |
|---|---|---|
| Contrast | 3:1 | 4.5:1 |
| Width | 2px | 3px |
| Offset | 0px | 2px |
| Style | Solid | Any visible |
Implementation:
/* Bad: Removed focus */ :focus { outline: none; } /* Good: Custom focus */ :focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; } /* Good: Focus ring component */ .focus-ring:focus-visible { box-shadow: 0 0 0 3px var(--color-focus); }
Tab Order Audit
## Keyboard Navigation Audit ### Tab Order 1. Skip to content link ✓ 2. Logo (link to home) ✓ 3. Navigation items (1-5) ✓ 4. Search input ✓ 5. Main content starts ✓ ### Focus Visibility | Element | Has Focus Style | Contrast | Status | |---------|-----------------|----------|--------| | Button | Yes | 4.8:1 | ✓ | | Link | Yes | 4.5:1 | ✓ | | Input | Yes | 3.2:1 | ✓ | | Checkbox | No | - | ✗ Fix | ### Keyboard Shortcuts | Action | Key | Working | |--------|-----|---------| | Submit form | Enter | ✓ | | Close modal | Escape | ✓ | | Menu navigation | Arrow keys | ✓ | | Skip link | Tab (first) | ✓ |
Motion and Animation
Requirements
- Respect
prefers-reduced-motion - No auto-playing videos with sound
- No flashing content (3 flashes/second)
- Provide pause controls for animation
Implementation
CSS:
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } }
SwiftUI:
@Environment(\.accessibilityReduceMotion) var reduceMotion var animation: Animation? { reduceMotion ? nil : .spring() }
React:
const prefersReducedMotion = window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches; const variants = { enter: prefersReducedMotion ? { opacity: 1 } : { opacity: 1, y: 0, transition: { duration: 0.3 } }, };
Audit Report Template
# Accessibility Audit Report **Component**: ButtonComponent **Date**: 2026-02-22 **WCAG Target**: AA ## Summary | Category | Pass | Fail | Warnings | |----------|------|------|----------| | Color Contrast | 4 | 1 | 0 | | Touch Targets | 3 | 0 | 1 | | Screen Reader | 5 | 2 | 0 | | Keyboard | 4 | 0 | 0 | | Motion | 2 | 0 | 0 | | **Total** | **18** | **3** | **1** | ## Critical Issues ### 1. Insufficient Color Contrast - **Element**: Disabled state text - **Current**: 2.8:1 - **Required**: 4.5:1 - **Fix**: Change `#999999` to `#767676` ### 2. Missing Accessible Name - **Element**: Icon-only button - **Issue**: No accessible name for screen readers - **Fix**: Add `aria-label="Close"` ## Recommendations 1. Add focus indicators to all interactive elements 2. Increase disabled state contrast 3. Add aria-labels to icon buttons 4. Test with VoiceOver/TalkBack ## Compliance Status | Level | Status | |-------|--------| | WCAG 2.1 A | ⚠️ 2 issues | | WCAG 2.1 AA | ⚠️ 3 issues | | WCAG 2.1 AAA | ❌ Not targeted |
Testing Tools
Automated
# axe-core CLI npm install -g @axe-core/cli axe https://example.com # Lighthouse accessibility npx lighthouse https://example.com --only-categories=accessibility # pa11y npx pa11y https://example.com
Manual Testing
| Tool | Platform | Purpose |
|---|---|---|
| VoiceOver | macOS/iOS | Screen reader |
| TalkBack | Android | Screen reader |
| NVDA | Windows | Screen reader |
| Accessibility Inspector | Xcode | iOS audit |
| Chrome DevTools | Web | Accessibility tree |
Integration
The accessibility-audit skill is used by:
- design-translator: Validate generated components
- component-spec style: Include accessibility section
- design-system-architect: Ensure system-wide compliance