Initial commit
This commit is contained in:
864
commands/review/accessibility.md
Normal file
864
commands/review/accessibility.md
Normal file
@@ -0,0 +1,864 @@
|
||||
# Accessibility Review
|
||||
|
||||
Performs comprehensive accessibility (a11y) audit focusing on WCAG compliance, screen reader compatibility, keyboard navigation, and inclusive design principles.
|
||||
|
||||
## Parameters
|
||||
|
||||
**Received from router**: `$ARGUMENTS` (after removing 'accessibility' operation)
|
||||
|
||||
Expected format: `scope:"review-scope" [depth:"quick|standard|deep"] [level:"A|AA|AAA"]`
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Parse Parameters
|
||||
|
||||
Extract from $ARGUMENTS:
|
||||
- **scope**: What to review (required) - components, pages, features
|
||||
- **depth**: Review thoroughness (default: "standard")
|
||||
- **level**: WCAG compliance level (default: "AA")
|
||||
|
||||
## WCAG Compliance Levels
|
||||
|
||||
- **Level A**: Minimum accessibility (basic compliance)
|
||||
- **Level AA**: Standard accessibility (recommended target)
|
||||
- **Level AAA**: Enhanced accessibility (gold standard)
|
||||
|
||||
### 2. Gather Context
|
||||
|
||||
**Identify UI Components**:
|
||||
```bash
|
||||
# Find frontend components
|
||||
find . -name "*.tsx" -o -name "*.jsx" -o -name "*.vue" -o -name "*.svelte" | head -20
|
||||
|
||||
# Check for accessibility tooling
|
||||
cat package.json | grep -E "axe|pa11y|lighthouse|eslint-plugin-jsx-a11y"
|
||||
|
||||
# Look for ARIA usage
|
||||
grep -r "aria-" --include="*.tsx" --include="*.jsx" --include="*.html" | head -20
|
||||
|
||||
# Check for role attributes
|
||||
grep -r 'role=' --include="*.tsx" --include="*.jsx" --include="*.html" | head -20
|
||||
```
|
||||
|
||||
### 3. Semantic HTML Review
|
||||
|
||||
**Proper HTML Structure**:
|
||||
- [ ] Semantic HTML elements used (`<header>`, `<nav>`, `<main>`, `<footer>`, `<article>`, `<section>`)
|
||||
- [ ] Headings in logical order (h1 → h2 → h3, no skipping)
|
||||
- [ ] Lists use `<ul>`, `<ol>`, `<dl>` appropriately
|
||||
- [ ] Tables use `<table>`, `<th>`, `<caption>` properly
|
||||
- [ ] Forms use `<form>`, `<label>`, `<fieldset>`, `<legend>`
|
||||
- [ ] Buttons use `<button>` (not styled divs)
|
||||
- [ ] Links use `<a>` with href attribute
|
||||
|
||||
**Document Structure**:
|
||||
- [ ] Single `<h1>` per page describing main content
|
||||
- [ ] Landmark regions defined (`<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>`)
|
||||
- [ ] Skip to main content link present
|
||||
- [ ] Page has meaningful `<title>`
|
||||
- [ ] Language attribute on `<html>` element
|
||||
|
||||
**Code Examples - Semantic HTML**:
|
||||
|
||||
```html
|
||||
<!-- ❌ BAD: Non-semantic markup -->
|
||||
<div class="header">
|
||||
<div class="nav">
|
||||
<div class="nav-item" onclick="navigate('/home')">Home</div>
|
||||
<div class="nav-item" onclick="navigate('/about')">About</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div class="title">Welcome</div>
|
||||
<div class="text">Content here</div>
|
||||
</div>
|
||||
|
||||
<!-- ✅ GOOD: Semantic HTML -->
|
||||
<header>
|
||||
<nav aria-label="Main navigation">
|
||||
<ul>
|
||||
<li><a href="/home">Home</a></li>
|
||||
<li><a href="/about">About</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<h1>Welcome</h1>
|
||||
<p>Content here</p>
|
||||
</main>
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- ❌ BAD: Incorrect heading hierarchy -->
|
||||
<h1>Main Title</h1>
|
||||
<h3>Subsection</h3> <!-- Skipped h2! -->
|
||||
<h2>Another Section</h2> <!-- Wrong order! -->
|
||||
|
||||
<!-- ✅ GOOD: Logical heading order -->
|
||||
<h1>Main Title</h1>
|
||||
<h2>Section</h2>
|
||||
<h3>Subsection</h3>
|
||||
<h2>Another Section</h2>
|
||||
<h3>Another Subsection</h3>
|
||||
```
|
||||
|
||||
### 4. ARIA (Accessible Rich Internet Applications)
|
||||
|
||||
**ARIA Attributes**:
|
||||
- [ ] ARIA used only when semantic HTML insufficient
|
||||
- [ ] ARIA roles appropriate and correct
|
||||
- [ ] ARIA properties accurately reflect state
|
||||
- [ ] ARIA labels provide meaningful descriptions
|
||||
- [ ] Dynamic content changes announced
|
||||
|
||||
**Common ARIA Patterns**:
|
||||
- [ ] Buttons: `role="button"` with `aria-pressed` for toggles
|
||||
- [ ] Dialogs: `role="dialog"`, `aria-modal="true"`, `aria-labelledby`
|
||||
- [ ] Tabs: `role="tablist"`, `role="tab"`, `role="tabpanel"`, `aria-selected`
|
||||
- [ ] Menus: `role="menu"`, `role="menuitem"`, `aria-haspopup`
|
||||
- [ ] Alerts: `role="alert"` or `aria-live="assertive"`
|
||||
- [ ] Loading: `aria-busy="true"`, `aria-live="polite"`
|
||||
|
||||
**ARIA Best Practices**:
|
||||
- [ ] First rule of ARIA: Don't use ARIA (prefer semantic HTML)
|
||||
- [ ] ARIA doesn't change behavior, only semantics
|
||||
- [ ] ARIA attributes are valid and supported
|
||||
- [ ] Required ARIA attributes present
|
||||
- [ ] ARIA properties reflect current state
|
||||
|
||||
**Code Examples - ARIA**:
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Div as button without proper ARIA
|
||||
<div onClick={handleClick} className="button">
|
||||
Click me
|
||||
</div>
|
||||
|
||||
// ✅ GOOD: Proper button element (no ARIA needed)
|
||||
<button onClick={handleClick}>
|
||||
Click me
|
||||
</button>
|
||||
|
||||
// ✅ ACCEPTABLE: Div with complete button semantics
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={handleClick}
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
|
||||
aria-label="Click me"
|
||||
>
|
||||
Click me
|
||||
</div>
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: No ARIA for custom dropdown
|
||||
<div className="dropdown">
|
||||
<div onClick={toggle}>Menu</div>
|
||||
{isOpen && (
|
||||
<div className="menu">
|
||||
<div onClick={handleOption1}>Option 1</div>
|
||||
<div onClick={handleOption2}>Option 2</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
// ✅ GOOD: Proper ARIA for dropdown
|
||||
<div className="dropdown">
|
||||
<button
|
||||
aria-haspopup="true"
|
||||
aria-expanded={isOpen}
|
||||
onClick={toggle}
|
||||
>
|
||||
Menu
|
||||
</button>
|
||||
{isOpen && (
|
||||
<ul role="menu">
|
||||
<li role="menuitem">
|
||||
<button onClick={handleOption1}>Option 1</button>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<button onClick={handleOption2}>Option 2</button>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Loading state not announced
|
||||
{isLoading && <div className="spinner">Loading...</div>}
|
||||
|
||||
// ✅ GOOD: Loading state announced to screen readers
|
||||
{isLoading && (
|
||||
<div role="status" aria-live="polite">
|
||||
<span className="spinner" aria-hidden="true"></span>
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
### 5. Keyboard Navigation
|
||||
|
||||
**Keyboard Accessibility**:
|
||||
- [ ] All interactive elements keyboard accessible
|
||||
- [ ] Tab order is logical and follows visual order
|
||||
- [ ] Focus indicators visible and clear
|
||||
- [ ] No keyboard traps (can always tab away)
|
||||
- [ ] Skip links for keyboard users
|
||||
- [ ] Shortcuts don't conflict with browser/screen reader
|
||||
- [ ] Custom controls have keyboard support
|
||||
|
||||
**Keyboard Interactions**:
|
||||
- [ ] Enter/Space activates buttons and links
|
||||
- [ ] Arrow keys navigate lists and menus
|
||||
- [ ] Escape closes dialogs and menus
|
||||
- [ ] Tab moves to next element
|
||||
- [ ] Shift+Tab moves to previous element
|
||||
- [ ] Home/End navigate to start/end
|
||||
|
||||
**Focus Management**:
|
||||
- [ ] Focus visible (no `outline: none` without alternative)
|
||||
- [ ] Focus moved appropriately (dialogs, route changes)
|
||||
- [ ] Focus restored when closing dialogs
|
||||
- [ ] Focus not lost during dynamic updates
|
||||
- [ ] Focus indicator meets contrast requirements (3:1)
|
||||
|
||||
**Code Examples - Keyboard Navigation**:
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: No keyboard support for custom control
|
||||
<div onClick={handleClick} className="custom-button">
|
||||
Click me
|
||||
</div>
|
||||
|
||||
// ✅ GOOD: Full keyboard support
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={handleClick}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleClick();
|
||||
}
|
||||
}}
|
||||
className="custom-button"
|
||||
>
|
||||
Click me
|
||||
</div>
|
||||
```
|
||||
|
||||
```css
|
||||
/* ❌ BAD: Removed focus indicator */
|
||||
*:focus {
|
||||
outline: none; /* Never do this without alternative! */
|
||||
}
|
||||
|
||||
/* ✅ GOOD: Enhanced focus indicator */
|
||||
*:focus {
|
||||
outline: 2px solid #4A90E2;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* ✅ BETTER: Visible focus, hidden for mouse users */
|
||||
*:focus-visible {
|
||||
outline: 2px solid #4A90E2;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Dialog doesn't trap focus
|
||||
function Dialog({ isOpen, onClose, children }) {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="dialog">
|
||||
<button onClick={onClose}>Close</button>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ GOOD: Dialog with focus trap
|
||||
function Dialog({ isOpen, onClose, children }) {
|
||||
const dialogRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
// Focus first focusable element
|
||||
const firstFocusable = dialogRef.current?.querySelector(
|
||||
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
||||
);
|
||||
(firstFocusable as HTMLElement)?.focus();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={dialogRef}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
onKeyDown={(e) => e.key === 'Escape' && onClose()}
|
||||
>
|
||||
<button onClick={onClose}>Close</button>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Screen Reader Compatibility
|
||||
|
||||
**Screen Reader Considerations**:
|
||||
- [ ] All content accessible to screen readers
|
||||
- [ ] Images have alt text (or marked decorative)
|
||||
- [ ] Form inputs have associated labels
|
||||
- [ ] Error messages announced
|
||||
- [ ] Dynamic content changes announced
|
||||
- [ ] Hidden content not read by screen readers
|
||||
- [ ] Reading order matches visual order
|
||||
|
||||
**Text Alternatives**:
|
||||
- [ ] Images have descriptive alt text
|
||||
- [ ] Decorative images have `alt=""` or `aria-hidden="true"`
|
||||
- [ ] Icon buttons have accessible names
|
||||
- [ ] SVG graphics have `<title>` and `<desc>`
|
||||
- [ ] Video/audio has captions and transcripts
|
||||
- [ ] Complex images have long descriptions
|
||||
|
||||
**Form Accessibility**:
|
||||
- [ ] Labels associated with inputs (`<label for="...">` or wrapping)
|
||||
- [ ] Required fields indicated (`required` or `aria-required`)
|
||||
- [ ] Error messages associated with fields (`aria-describedby`)
|
||||
- [ ] Fieldsets group related inputs
|
||||
- [ ] Form validation errors announced
|
||||
- [ ] Help text associated with inputs
|
||||
|
||||
**Code Examples - Screen Readers**:
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: No alt text
|
||||
<img src="/logo.png" />
|
||||
|
||||
// ✅ GOOD: Descriptive alt text
|
||||
<img src="/logo.png" alt="Company Logo" />
|
||||
|
||||
// ✅ GOOD: Decorative image
|
||||
<img src="/decorative-border.png" alt="" />
|
||||
<img src="/background.png" aria-hidden="true" />
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Icon button without accessible name
|
||||
<button onClick={handleDelete}>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
|
||||
// ✅ GOOD: Icon button with accessible name
|
||||
<button onClick={handleDelete} aria-label="Delete item">
|
||||
<TrashIcon aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
// ✅ ALSO GOOD: Visually hidden text
|
||||
<button onClick={handleDelete}>
|
||||
<TrashIcon aria-hidden="true" />
|
||||
<span className="sr-only">Delete item</span>
|
||||
</button>
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Form without labels
|
||||
<input type="text" placeholder="Enter your name" />
|
||||
|
||||
// ✅ GOOD: Properly labeled form field
|
||||
<label htmlFor="name">Name</label>
|
||||
<input type="text" id="name" placeholder="Enter your name" />
|
||||
|
||||
// ✅ ALSO GOOD: Wrapping label
|
||||
<label>
|
||||
Name
|
||||
<input type="text" placeholder="Enter your name" />
|
||||
</label>
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Error not associated with field
|
||||
<input type="email" id="email" />
|
||||
{error && <div className="error">Invalid email</div>}
|
||||
|
||||
// ✅ GOOD: Error associated with field
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
aria-invalid={!!error}
|
||||
aria-describedby={error ? "email-error" : undefined}
|
||||
/>
|
||||
{error && (
|
||||
<div id="email-error" className="error" role="alert">
|
||||
Invalid email
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
### 7. Color and Contrast
|
||||
|
||||
**Color Contrast** (WCAG AA):
|
||||
- [ ] Normal text: 4.5:1 contrast ratio minimum
|
||||
- [ ] Large text (18pt+ or 14pt+ bold): 3:1 minimum
|
||||
- [ ] UI components: 3:1 contrast with adjacent colors
|
||||
- [ ] Focus indicators: 3:1 contrast with background
|
||||
- [ ] WCAG AAA: 7:1 for normal text, 4.5:1 for large text
|
||||
|
||||
**Color Usage**:
|
||||
- [ ] Information not conveyed by color alone
|
||||
- [ ] Color blind friendly palette
|
||||
- [ ] Links distinguishable without color (underline, icon)
|
||||
- [ ] Form validation errors not color-only
|
||||
- [ ] Charts/graphs have patterns or labels
|
||||
|
||||
**Code Examples - Color and Contrast**:
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Color only to indicate error
|
||||
<input
|
||||
type="text"
|
||||
style={{ borderColor: hasError ? 'red' : 'gray' }}
|
||||
/>
|
||||
|
||||
// ✅ GOOD: Multiple indicators for error
|
||||
<input
|
||||
type="text"
|
||||
aria-invalid={hasError}
|
||||
aria-describedby={hasError ? "error-message" : undefined}
|
||||
style={{
|
||||
borderColor: hasError ? 'red' : 'gray',
|
||||
borderWidth: hasError ? '2px' : '1px'
|
||||
}}
|
||||
/>
|
||||
{hasError && (
|
||||
<div id="error-message" role="alert">
|
||||
<ErrorIcon aria-hidden="true" />
|
||||
This field is required
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ❌ BAD: Link only differentiated by color
|
||||
<a href="/more" style={{ color: 'blue', textDecoration: 'none' }}>
|
||||
Read more
|
||||
</a>
|
||||
|
||||
// ✅ GOOD: Link with underline
|
||||
<a href="/more" style={{ color: 'blue', textDecoration: 'underline' }}>
|
||||
Read more
|
||||
</a>
|
||||
|
||||
// ✅ ALSO GOOD: Link with icon
|
||||
<a href="/more" style={{ color: 'blue' }}>
|
||||
Read more <ArrowIcon aria-hidden="true" />
|
||||
</a>
|
||||
```
|
||||
|
||||
### 8. Responsive and Adaptive Design
|
||||
|
||||
**Viewport and Zoom**:
|
||||
- [ ] Content adapts to viewport size
|
||||
- [ ] Text can be resized to 200% without loss of functionality
|
||||
- [ ] No horizontal scrolling at 320px width
|
||||
- [ ] Touch targets at least 44x44 pixels (mobile)
|
||||
- [ ] Pinch-to-zoom not disabled
|
||||
|
||||
**Media Queries**:
|
||||
- [ ] Reduced motion preferences respected
|
||||
- [ ] High contrast mode supported
|
||||
- [ ] Dark mode accessible
|
||||
- [ ] Print styles appropriate
|
||||
|
||||
**Code Examples - Responsive**:
|
||||
|
||||
```css
|
||||
/* ❌ BAD: Disables zoom */
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
|
||||
/* ✅ GOOD: Allows zoom */
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
```
|
||||
|
||||
```css
|
||||
/* ✅ GOOD: Respect reduced motion preference */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// ✅ GOOD: Touch targets sized appropriately
|
||||
<button style={{
|
||||
minWidth: '44px',
|
||||
minHeight: '44px',
|
||||
padding: '12px'
|
||||
}}>
|
||||
Click me
|
||||
</button>
|
||||
```
|
||||
|
||||
### 9. Multimedia Accessibility
|
||||
|
||||
**Video Accessibility**:
|
||||
- [ ] Captions for all audio content
|
||||
- [ ] Audio descriptions for visual content
|
||||
- [ ] Transcript provided
|
||||
- [ ] Controls keyboard accessible
|
||||
- [ ] Auto-play disabled or user-controlled
|
||||
|
||||
**Audio Accessibility**:
|
||||
- [ ] Transcripts provided
|
||||
- [ ] Visual indicators for audio cues
|
||||
- [ ] User can control volume and playback
|
||||
|
||||
**Code Examples - Multimedia**:
|
||||
|
||||
```html
|
||||
<!-- ✅ GOOD: Video with captions and transcript -->
|
||||
<video controls>
|
||||
<source src="video.mp4" type="video/mp4">
|
||||
<track kind="captions" src="captions.vtt" srclang="en" label="English">
|
||||
<track kind="descriptions" src="descriptions.vtt" srclang="en" label="English">
|
||||
</video>
|
||||
<details>
|
||||
<summary>Video Transcript</summary>
|
||||
<p>[Full transcript here]</p>
|
||||
</details>
|
||||
```
|
||||
|
||||
### 10. Automated Testing
|
||||
|
||||
**Run Accessibility Audits**:
|
||||
```bash
|
||||
# Lighthouse audit
|
||||
npx lighthouse https://your-site.com --only-categories=accessibility --view
|
||||
|
||||
# axe-core testing
|
||||
npm install --save-dev @axe-core/cli
|
||||
npx axe https://your-site.com
|
||||
|
||||
# pa11y testing
|
||||
npm install --save-dev pa11y
|
||||
npx pa11y https://your-site.com
|
||||
|
||||
# ESLint accessibility plugin (React)
|
||||
npm install --save-dev eslint-plugin-jsx-a11y
|
||||
```
|
||||
|
||||
**Manual Testing**:
|
||||
- [ ] Test with keyboard only (no mouse)
|
||||
- [ ] Test with screen reader (NVDA, JAWS, VoiceOver)
|
||||
- [ ] Test with browser zoom at 200%
|
||||
- [ ] Test in high contrast mode
|
||||
- [ ] Test with CSS disabled
|
||||
- [ ] Test on mobile devices
|
||||
|
||||
## Review Depth Implementation
|
||||
|
||||
**Quick Depth** (10-15 min):
|
||||
- Semantic HTML check
|
||||
- Alt text verification
|
||||
- Form label check
|
||||
- Keyboard navigation test
|
||||
- Automated audit (Lighthouse)
|
||||
|
||||
**Standard Depth** (30-45 min):
|
||||
- Complete WCAG AA checklist
|
||||
- ARIA usage review
|
||||
- Keyboard navigation thorough test
|
||||
- Focus management review
|
||||
- Color contrast check
|
||||
- Screen reader spot checks
|
||||
|
||||
**Deep Depth** (60-90+ min):
|
||||
- Complete WCAG AAA checklist
|
||||
- Comprehensive screen reader testing
|
||||
- Keyboard-only navigation of entire scope
|
||||
- Color blindness simulation
|
||||
- Reduced motion testing
|
||||
- High contrast mode testing
|
||||
- Mobile accessibility testing
|
||||
- Automated testing suite
|
||||
|
||||
## Output Format
|
||||
|
||||
```markdown
|
||||
# Accessibility Review: [Scope]
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Reviewed**: [What was reviewed]
|
||||
**Depth**: [Quick|Standard|Deep]
|
||||
**WCAG Level Target**: [A|AA|AAA]
|
||||
**Accessibility Rating**: [Excellent|Good|Needs Work|Poor]
|
||||
|
||||
### Overall Assessment
|
||||
**[Compliant|Partially Compliant|Non-Compliant] with WCAG [Level]**
|
||||
|
||||
[Brief explanation]
|
||||
|
||||
### Priority Actions
|
||||
1. [Critical a11y issue 1]
|
||||
2. [Critical a11y issue 2]
|
||||
|
||||
---
|
||||
|
||||
## Critical Issues 🚨
|
||||
|
||||
**[Must fix for basic accessibility]**
|
||||
|
||||
### [Issue 1 Title]
|
||||
**File**: `path/to/component.tsx:42`
|
||||
**WCAG Criterion**: [X.X.X - Criterion Name - Level A/AA/AAA]
|
||||
**Issue**: [Description of accessibility barrier]
|
||||
**Impact**: [How this affects users]
|
||||
**Affected Users**: [Screen reader users, keyboard users, low vision users, etc.]
|
||||
**Fix**:
|
||||
|
||||
```tsx
|
||||
// Current (inaccessible)
|
||||
[problematic code]
|
||||
|
||||
// Accessible implementation
|
||||
[fixed code]
|
||||
```
|
||||
|
||||
**Testing**: [How to verify the fix]
|
||||
|
||||
[Repeat for each critical issue]
|
||||
|
||||
---
|
||||
|
||||
## High Priority Issues ⚠️
|
||||
|
||||
**[Should fix for good accessibility]**
|
||||
|
||||
[Similar format for high priority issues]
|
||||
|
||||
---
|
||||
|
||||
## Medium Priority Issues ℹ️
|
||||
|
||||
**[Consider fixing for enhanced accessibility]**
|
||||
|
||||
[Similar format for medium priority issues]
|
||||
|
||||
---
|
||||
|
||||
## Low Priority Issues 💡
|
||||
|
||||
**[Nice to have for optimal accessibility]**
|
||||
|
||||
[Similar format for low priority issues]
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Strengths ✅
|
||||
|
||||
- ✅ [Good practice 1 with examples]
|
||||
- ✅ [Good practice 2 with examples]
|
||||
- ✅ [Good practice 3 with examples]
|
||||
|
||||
---
|
||||
|
||||
## WCAG 2.1 Compliance Summary
|
||||
|
||||
### Level A (Minimum)
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| 1.1.1 Non-text Content | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 1.3.1 Info and Relationships | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 1.3.2 Meaningful Sequence | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.1.1 Keyboard | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.1.2 No Keyboard Trap | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.4.1 Bypass Blocks | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 3.1.1 Language of Page | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 4.1.1 Parsing | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 4.1.2 Name, Role, Value | ✅ / ⚠️ / ❌ | [Details] |
|
||||
|
||||
### Level AA (Recommended)
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| 1.4.3 Contrast (Minimum) | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 1.4.5 Images of Text | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.4.5 Multiple Ways | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.4.6 Headings and Labels | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 2.4.7 Focus Visible | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 3.1.2 Language of Parts | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 3.2.3 Consistent Navigation | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 3.3.3 Error Suggestion | ✅ / ⚠️ / ❌ | [Details] |
|
||||
| 3.3.4 Error Prevention (Legal) | ✅ / ⚠️ / ❌ | [Details] |
|
||||
|
||||
### Level AAA (Enhanced) - Optional
|
||||
|
||||
[If deep review includes AAA]
|
||||
|
||||
---
|
||||
|
||||
## Detailed Accessibility Analysis
|
||||
|
||||
### 🏗️ Semantic HTML
|
||||
|
||||
**Overall**: [Excellent|Good|Needs Work]
|
||||
|
||||
**Strengths**:
|
||||
- ✅ [Well-structured areas]
|
||||
|
||||
**Issues**:
|
||||
- ⚠️ [Semantic HTML issues with file references]
|
||||
|
||||
**Heading Structure**:
|
||||
```
|
||||
h1: [Page title]
|
||||
h2: [Section 1]
|
||||
h3: [Subsection]
|
||||
h2: [Section 2]
|
||||
```
|
||||
|
||||
### 🎯 ARIA Usage
|
||||
|
||||
**Overall**: [Appropriate|Overused|Underused]
|
||||
|
||||
**Proper ARIA**:
|
||||
- ✅ [Good ARIA usage examples]
|
||||
|
||||
**ARIA Issues**:
|
||||
- ⚠️ [ARIA problems with file references]
|
||||
|
||||
### ⌨️ Keyboard Navigation
|
||||
|
||||
**Overall**: [Fully Accessible|Partially Accessible|Not Accessible]
|
||||
|
||||
**Tab Order**: [Logical|Needs Work]
|
||||
|
||||
**Keyboard Support**:
|
||||
- ✅ [Components with full keyboard support]
|
||||
- ⚠️ [Components with keyboard issues]
|
||||
|
||||
**Focus Management**: [Good|Needs Improvement]
|
||||
|
||||
### 📢 Screen Reader Compatibility
|
||||
|
||||
**Tested with**: [NVDA|JAWS|VoiceOver|Narrator]
|
||||
|
||||
**Screen Reader Experience**: [Excellent|Good|Poor]
|
||||
|
||||
**Issues Found**:
|
||||
- ⚠️ [Screen reader issues]
|
||||
|
||||
**Missing Alternatives**:
|
||||
- ⚠️ [Missing alt text, labels, etc.]
|
||||
|
||||
### 🎨 Color and Contrast
|
||||
|
||||
**Contrast Ratio Analysis**:
|
||||
|
||||
| Element | Foreground | Background | Ratio | WCAG AA | WCAG AAA |
|
||||
|---------|-----------|------------|-------|---------|----------|
|
||||
| Body text | [Color] | [Color] | [X:1] | ✅ / ❌ | ✅ / ❌ |
|
||||
| Links | [Color] | [Color] | [X:1] | ✅ / ❌ | ✅ / ❌ |
|
||||
| Buttons | [Color] | [Color] | [X:1] | ✅ / ❌ | ✅ / ❌ |
|
||||
|
||||
**Color Usage**: [Accessible|Issues Found]
|
||||
|
||||
### 📱 Responsive and Mobile
|
||||
|
||||
**Mobile Accessibility**: [Excellent|Good|Needs Work]
|
||||
|
||||
**Touch Target Sizes**: [Adequate|Too Small]
|
||||
|
||||
**Zoom Support**: [Enabled|Disabled]
|
||||
|
||||
---
|
||||
|
||||
## Testing Results
|
||||
|
||||
### Automated Testing
|
||||
|
||||
**Lighthouse Score**: [X/100]
|
||||
|
||||
**axe-core Results**:
|
||||
- Critical issues: [X]
|
||||
- Serious issues: [X]
|
||||
- Moderate issues: [X]
|
||||
- Minor issues: [X]
|
||||
|
||||
### Manual Testing
|
||||
|
||||
**Keyboard-Only Navigation**: [Pass|Fail] - [Details]
|
||||
|
||||
**Screen Reader Testing**: [Pass|Fail] - [Details]
|
||||
|
||||
**Zoom to 200%**: [Pass|Fail] - [Details]
|
||||
|
||||
**High Contrast Mode**: [Pass|Fail] - [Details]
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Immediate (This Week)
|
||||
- [ ] [Critical fix 1]
|
||||
- [ ] [Critical fix 2]
|
||||
|
||||
### Short-term (This Month)
|
||||
- [ ] [High priority fix 1]
|
||||
- [ ] [High priority fix 2]
|
||||
|
||||
### Long-term (This Quarter)
|
||||
- [ ] [Strategic improvement 1]
|
||||
- [ ] [Strategic improvement 2]
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
**Testing Tools**:
|
||||
- Lighthouse (Chrome DevTools)
|
||||
- axe DevTools (browser extension)
|
||||
- WAVE (browser extension)
|
||||
- Screen reader (NVDA, JAWS, VoiceOver)
|
||||
|
||||
**Guidelines**:
|
||||
- WCAG 2.1: https://www.w3.org/WAI/WCAG21/quickref/
|
||||
- ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
|
||||
|
||||
---
|
||||
|
||||
## Review Metadata
|
||||
|
||||
- **Reviewer**: 10x Fullstack Engineer (Accessibility Focus)
|
||||
- **Review Date**: [Date]
|
||||
- **WCAG Level**: [A|AA|AAA]
|
||||
- **A11y Issues**: Critical: X, High: X, Medium: X, Low: X
|
||||
- **Compliance Status**: [Compliant|Partially Compliant|Non-Compliant]
|
||||
```
|
||||
|
||||
## Agent Invocation
|
||||
|
||||
This operation MUST leverage the **10x-fullstack-engineer** agent with accessibility expertise.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Semantic HTML First**: Use native elements before ARIA
|
||||
2. **Test with Real Users**: Automated tools catch ~30-40% of issues
|
||||
3. **Keyboard First**: If keyboard works, most other things will follow
|
||||
4. **Don't Assume**: Test with actual assistive technology
|
||||
5. **Progressive Enhancement**: Start accessible, add features
|
||||
6. **Inclusive Design**: Consider all users from the beginning
|
||||
Reference in New Issue
Block a user