Accessibility Skill
WCAG 2.2 compliance and ARIA implementation for inclusive, accessible web experiences.
π― Purpose
Provide atomic, single-responsibility operations for:
- WCAG 2.2 Level A/AA/AAA auditing
- ARIA roles, states, and properties
- Keyboard navigation patterns
- Screen reader optimization
- Focus management
- Color contrast verification
π₯ Input Schema
interface AccessibilityInput {
operation: 'audit' | 'fix' | 'pattern' | 'explain';
audit_level: 'A' | 'AA' | 'AAA';
markup?: string;
component_type?: ComponentType;
context?: {
user_agents: string[]; // Target screen readers
focus_management: boolean;
color_scheme: 'light' | 'dark' | 'both';
};
}
type ComponentType =
| 'interactive' // Buttons, links, controls
| 'form' // Form elements
| 'navigation' // Menus, breadcrumbs
| 'media' // Images, video, audio
| 'content' // Text, headings, lists
| 'widget'; // Custom components
π€ Output Schema
interface AccessibilityOutput {
success: boolean;
wcag_level: 'A' | 'AA' | 'AAA';
score: number; // 0-100
issues: A11yIssue[];
fixes: A11yFix[];
passed_criteria: string[];
failed_criteria: string[];
}
interface A11yIssue {
criterion: string; // e.g., "1.4.3"
level: 'A' | 'AA' | 'AAA';
impact: 'critical' | 'serious' | 'moderate' | 'minor';
element: string;
message: string;
fix: string;
}
π οΈ WCAG 2.2 Quick Reference
The Four Principles (POUR)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WCAG POUR β
ββββββββββββββββββ¬βββββββββββββββββ¬βββββββββββββββββ¬βββββββββββ€
β PERCEIVABLE β OPERABLE β UNDERSTANDABLE β ROBUST β
ββββββββββββββββββΌβββββββββββββββββΌβββββββββββββββββΌβββββββββββ€
β Text alt β Keyboard β Readable β Compatibleβ
β Captions β Enough time β Predictable β Parsing β
β Adaptable β Seizures β Input assist β β
β Distinguishableβ Navigable β β β
β β Input modality β β β
ββββββββββββββββββ΄βββββββββββββββββ΄βββββββββββββββββ΄βββββββββββ
WCAG 2.2 New Success Criteria (AA)
| Criterion | Name | Requirement | |-----------|------|-------------| | 2.4.11 | Focus Not Obscured | Focus never completely hidden | | 2.5.7 | Dragging Movements | Alternative to drag operations | | 2.5.8 | Target Size (Minimum) | 24x24px minimum touch targets | | 3.2.6 | Consistent Help | Help in same relative location | | 3.3.7 | Redundant Entry | Don't re-ask for same info | | 3.3.8 | Accessible Authentication | No cognitive tests for login |
π¨ ARIA Patterns
1. Interactive Widgets
Button
<!-- Native button (preferred) -->
<button type="button">Click me</button>
<!-- Custom button (when native not possible) -->
<div role="button"
tabindex="0"
aria-pressed="false"
onkeydown="handleKeydown(event)">
Toggle
</div>
Dialog (Modal)
<div role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc">
<h2 id="dialog-title">Confirm Action</h2>
<p id="dialog-desc">Are you sure you want to proceed?</p>
<button>Cancel</button>
<button>Confirm</button>
</div>
Tabs
<div role="tablist" aria-label="Settings">
<button role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1">
General
</button>
<button role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2"
tabindex="-1">
Privacy
</button>
</div>
<div role="tabpanel"
id="panel-1"
aria-labelledby="tab-1">
General settings content...
</div>
<div role="tabpanel"
id="panel-2"
aria-labelledby="tab-2"
hidden>
Privacy settings content...
</div>
2. Live Regions
<!-- Polite announcement (waits for pause) -->
<div aria-live="polite" aria-atomic="true">
3 items in cart
</div>
<!-- Assertive announcement (interrupts) -->
<div role="alert" aria-live="assertive">
Error: Please fix the form errors
</div>
<!-- Status message -->
<div role="status" aria-live="polite">
File uploaded successfully
</div>
3. Form Patterns
<form>
<!-- Required field -->
<label for="email">Email (required)</label>
<input type="email"
id="email"
name="email"
required
aria-required="true"
aria-describedby="email-hint email-error">
<p id="email-hint">We'll never share your email</p>
<p id="email-error" role="alert" aria-live="polite"></p>
<!-- Field with error -->
<label for="password">Password</label>
<input type="password"
id="password"
aria-invalid="true"
aria-errormessage="pwd-error">
<p id="pwd-error" role="alert">
Password must be at least 8 characters
</p>
<!-- Checkbox group -->
<fieldset>
<legend>Notifications</legend>
<label>
<input type="checkbox" name="notify" value="email">
Email
</label>
<label>
<input type="checkbox" name="notify" value="sms">
SMS
</label>
</fieldset>
</form>
β οΈ Error Handling
Error Codes
| Code | Description | WCAG | Recovery |
|------|-------------|------|----------|
| A11Y001 | Missing alt text | 1.1.1 | Add descriptive alt |
| A11Y002 | Low color contrast | 1.4.3 | Adjust colors to 4.5:1 |
| A11Y003 | Missing form label | 1.3.1 | Add <label> or aria-label |
| A11Y004 | No keyboard access | 2.1.1 | Add tabindex, handlers |
| A11Y005 | Missing skip link | 2.4.1 | Add skip to main content |
| A11Y006 | Empty link/button | 2.4.4 | Add accessible text |
| A11Y007 | Missing page title | 2.4.2 | Add descriptive <title> |
| A11Y008 | Missing lang attr | 3.1.1 | Add lang to <html> |
| A11Y009 | Focus not visible | 2.4.7 | Add focus styles |
| A11Y010 | Target too small | 2.5.8 | Increase to 24x24px |
Impact Levels
| Impact | Description | Examples | |--------|-------------|----------| | Critical | Blocks access completely | No keyboard, missing alt | | Serious | Major barrier | Low contrast, no labels | | Moderate | Significant difficulty | Missing skip link | | Minor | Inconvenience | Suboptimal reading order |
π Troubleshooting
Problem: Screen reader not announcing content
Debug Checklist:
β‘ Element has accessible name?
β‘ ARIA role correct?
β‘ aria-hidden not incorrectly set?
β‘ Content not CSS display:none?
β‘ Live region set up correctly?
Problem: Keyboard navigation broken
Debug Checklist:
β‘ All interactive elements focusable?
β‘ Tab order logical?
β‘ No keyboard traps?
β‘ Focus visible?
β‘ Custom widgets have key handlers?
β‘ Arrow key navigation for widgets?
Problem: Form not accessible
Debug Checklist:
β‘ All inputs have labels?
β‘ Required fields marked?
β‘ Errors announced via live region?
β‘ Error linked with aria-errormessage?
β‘ Fieldsets for groups?
β‘ Autocomplete attributes set?
Keyboard Navigation Patterns
| Component | Keys | Action | |-----------|------|--------| | Buttons | Enter, Space | Activate | | Links | Enter | Navigate | | Checkboxes | Space | Toggle | | Radio buttons | Arrow keys | Move selection | | Tabs | Arrow keys | Switch tabs | | Menus | Arrow, Enter, Esc | Navigate, select, close | | Dialogs | Esc, Tab | Close, move focus | | Listbox | Arrow, Enter | Navigate, select |
π Audit Scoring
| Category | Weight | Checks | |----------|--------|--------| | Perceivable | 25% | Alt text, contrast, captions | | Operable | 30% | Keyboard, focus, timing | | Understandable | 25% | Labels, errors, consistency | | Robust | 20% | Valid HTML, ARIA usage |
Score Interpretation:
- 90-100: Excellent (WCAG AA likely compliant)
- 70-89: Good (some issues to address)
- 50-69: Moderate (significant work needed)
- <50: Poor (major accessibility barriers)
π Usage Examples
# Audit markup for WCAG AA
skill: accessibility
operation: audit
audit_level: "AA"
markup: "<form>...</form>"
# Get accessible pattern
skill: accessibility
operation: pattern
component_type: widget
context:
user_agents: ["NVDA", "VoiceOver"]
# Fix accessibility issues
skill: accessibility
operation: fix
audit_level: "AA"
markup: "<img src='photo.jpg'>"
output_format: both