Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:16:40 +08:00
commit f125e90b9f
370 changed files with 67769 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# Changelog
All notable changes to the accessibility-audit skill will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.1.0] - 2025-11-27
### Added
- Initial Claudex marketplace release
- Risk-based severity scoring (Impact x Likelihood model)
- MUI framework awareness to prevent false positives
- Multi-layer analysis workflow (static, runtime, manual)
- Comprehensive WCAG 2.2 Level AA criteria reference
- Gap report and remediation plan examples

View File

@@ -0,0 +1,51 @@
# Accessibility Audit
WCAG 2.2 Level AA accessibility auditing with risk-based severity scoring for React/TypeScript applications.
## Overview
This skill provides comprehensive accessibility auditing that goes beyond simple WCAG conformance checking. It uses a **risk-based severity model** where Severity = Impact x Likelihood, meaning a Level A failure can be LOW severity while a Level AA failure can be CRITICAL.
## Key Features
- **Risk-based severity scoring** - Prioritizes issues by real user impact
- **MUI framework awareness** - Avoids false positives on built-in accessibility features
- **Multi-layer analysis** - Static (ESLint), runtime (jest-axe, Playwright), and manual validation
- **Actionable output** - Gap reports with remediation priorities
## Quick Start
```bash
# Install required tooling
npm install --save-dev eslint-plugin-jsx-a11y jest-axe @axe-core/playwright
# Run audit
# Use trigger: "Run accessibility audit on [component/page]"
```
## Trigger Phrases
- "accessibility audit"
- "WCAG compliance"
- "a11y review"
- "screen reader"
- "keyboard navigation"
- "color contrast"
## Severity Levels
| Severity | Impact | Examples |
|----------|--------|----------|
| Critical | Blocks access | Keyboard traps, missing alt on actions |
| High | Significantly degrades UX | Poor contrast on CTAs, no skip navigation |
| Medium | Minor usability impact | Missing autocomplete, unclear link text |
| Low | Best practice | Could add tooltips, more descriptive titles |
## Related Skills
- `codebase-auditor` - General code quality analysis
- `bulletproof-react-auditor` - React architecture review
## Documentation
See [SKILL.md](SKILL.md) for the complete workflow and reference materials.

View File

@@ -0,0 +1,85 @@
---
name: accessibility-audit
version: 0.1.0
description: WCAG 2.2 Level AA accessibility auditing with risk-based severity scoring
author: Connor
triggers:
- accessibility audit
- WCAG compliance
- a11y review
- screen reader
- keyboard navigation
- color contrast
---
# Accessibility Audit Skill
Comprehensive WCAG 2.2 Level AA accessibility auditing for React/TypeScript applications with MUI framework awareness.
## Quick Reference
| Severity | Impact | Examples |
|----------|--------|----------|
| **Critical** | Blocks access completely | Keyboard traps, missing alt on actions, no focus visible |
| **High** | Significantly degrades UX | Poor contrast on CTAs, no skip navigation, small touch targets |
| **Medium** | Minor usability impact | Missing autocomplete, unclear link text |
| **Low** | Best practice enhancement | Could add tooltips, more descriptive titles |
## Key Principle
> **Severity = Impact x Likelihood**, NOT WCAG conformance level.
> A Level A failure can be LOW severity; a Level AA failure can be CRITICAL.
## Required Tooling
```bash
# Install required tools
npm install --save-dev eslint-plugin-jsx-a11y jest-axe @axe-core/playwright
# Configure ESLint
# Add to .eslintrc: extends: ['plugin:jsx-a11y/recommended']
```
## Workflow
| Phase | Description |
|-------|-------------|
| 1. Setup | Install tooling, create output directories |
| 2. Static Analysis | ESLint jsx-a11y scan |
| 3. Runtime Analysis | jest-axe and Playwright |
| 4. Manual Validation | Keyboard, screen reader, contrast |
| 5. Report Generation | JSON + Markdown outputs |
### Phase 1: Setup
See [workflow/setup.md](workflow/setup.md) for installation and configuration.
### Phase 4: Manual Validation
See [workflow/manual-validation.md](workflow/manual-validation.md) for keyboard and screen reader testing.
## Reference
- [Severity Rubric](reference/severity-rubric.md) - Impact x Likelihood calculation
- [MUI Framework Awareness](reference/mui-awareness.md) - Built-in accessibility features
## Common False Positives to Avoid
| Component | Built-in Behavior | Don't Flag |
|-----------|-------------------|------------|
| MUI `<SvgIcon>` | Auto `aria-hidden="true"` | Icons without titleAccess |
| MUI `<Alert>` | Default `role="alert"` | Missing role attribute |
| MUI `<Button>` | 36.5px min height | Target size < 44px |
| MUI `<TextField>` | Auto label association | Missing label |
| MUI `<Autocomplete>` | Manages ARIA attrs | Missing aria-expanded |
## Quick Audit Command
```
Run accessibility audit on [component/page] following WCAG 2.2 AA standards
```
## Related Skills
- `codebase-auditor` - General code quality analysis
- `bulletproof-react-auditor` - React architecture review

View File

@@ -0,0 +1,83 @@
# MUI Framework Awareness
MUI components have built-in accessibility features. Audit rules MUST account for framework defaults to avoid false positives.
## Component Defaults
### SvgIcon
- **Behavior**: Automatically adds `aria-hidden="true"` when `titleAccess` prop is undefined
- **Source**: `node_modules/@mui/material/SvgIcon/SvgIcon.js`
**Rule**: Do NOT flag MUI icons as missing aria-hidden unless titleAccess is set
```tsx
// Only flag if titleAccess is set (should have aria-label or be visible):
<SvgIcon titleAccess="Icon name" />
// Do NOT flag (auto aria-hidden):
<SearchIcon />
<Timeline />
```
### Alert
- **Behavior**: Defaults to `role="alert"` (assertive live region)
**Rule**: Do NOT recommend adding `role="alert"` - it's already there
```tsx
// Only suggest role="status" if polite announcement is more appropriate:
<Alert severity="success" role="status">Item saved</Alert>
```
### Button
- **Behavior**: Has minimum 36.5px height by default
**Rule**: Usually meets 24x24px target size requirement
```tsx
// Only flag if size="small" or custom sx reduces below 24px:
<Button size="small" sx={{ minHeight: '20px' }} /> // Flag this
<Button>Normal</Button> // Don't flag
```
### TextField
- **Behavior**: Automatically associates label with input via id
**Rule**: Do NOT flag as missing label if `label` prop is provided
```tsx
// This is accessible (auto-associated):
<TextField label="Email" />
// Only flag if no label and no aria-label:
<TextField /> // Flag this
```
### Autocomplete
- **Behavior**: Manages `aria-expanded`, `aria-controls`, `aria-activedescendant`
**Rule**: Do NOT flag ARIA attributes - they're managed by component
```tsx
// All ARIA is handled internally:
<Autocomplete options={options} renderInput={(params) => <TextField {...params} />} />
```
## False Positive Checklist
Before flagging a MUI component violation:
1. [ ] Check if MUI provides default accessibility behavior
2. [ ] Verify the violation exists in rendered output (use browser DevTools)
3. [ ] Test with actual screen reader to confirm issue
4. [ ] Check MUI documentation for accessibility notes
## Common False Positives
| Automated Finding | Why It's False | Reality |
|-------------------|----------------|---------|
| "Icon missing aria-hidden" | MUI adds it automatically | Check rendered HTML |
| "Alert missing role" | Default is role="alert" | Only change if polite needed |
| "Button too small" | 36.5px default height | Check actual rendered size |
| "Input missing label" | TextField manages labels | Check for label prop |
| "Missing aria-expanded" | Autocomplete manages it | Check rendered state |

View File

@@ -0,0 +1,80 @@
# Severity Rubric
## Core Principle
**Severity = Impact x Likelihood**, NOT WCAG conformance level.
- Level A vs AA is a *conformance tier*, not a risk rating
- A Level A failure can be LOW severity (decorative image missing alt)
- A Level AA failure can be CRITICAL (focus outline removed)
## Severity Levels
### Critical
- **Description**: Completely blocks access for users with disabilities
- **Impact**: Prevents task completion
- **Examples**:
- Keyboard trap preventing navigation (2.1.2, Level A)
- Missing alt text on primary action image (1.1.1, Level A)
- Form submission inaccessible via keyboard (2.1.1, Level A)
- Focus outline removed from focusable elements (2.4.7, Level AA)
### High
- **Description**: Significantly degrades experience or blocks common workflows
- **Impact**: Makes tasks difficult or requires workarounds
- **Examples**:
- No skip navigation on complex site (2.4.1, Level A)
- Poor contrast on primary CTA button (1.4.3, Level AA)
- Missing error suggestions on required form (3.3.3, Level AA)
- Touch targets too small on mobile (2.5.8, Level AA)
### Medium
- **Description**: Minor usability impact, affects subset of users
- **Impact**: Causes confusion or requires extra effort
- **Examples**:
- Decorative icon not hidden but in acceptable context (1.1.1, Level A)
- Link text needs slight improvement for clarity (2.4.4, Level A)
- Missing autocomplete on optional field (1.3.5, Level AA)
### Low
- **Description**: Best practice enhancement, minimal user impact
- **Impact**: Nice-to-have improvement
- **Examples**:
- Could add tooltips for better UX (not required)
- Page title could be more descriptive (2.4.2, Level A - but functional)
## Calculation Guide
### Impact Assessment
| Level | Description | Severity Modifier |
|-------|-------------|-------------------|
| Blocker | Prevents access | Critical/High |
| Degraded | Makes difficult | High/Medium |
| Friction | Adds effort | Medium/Low |
| Minor | Barely noticeable | Low |
### Likelihood Assessment
| Level | Description | Severity Modifier |
|-------|-------------|-------------------|
| Core flow | All users hit it | Increase severity |
| Common | Many users hit it | Base severity |
| Edge case | Few users hit it | Decrease severity |
| Rare | Almost never | Low |
## Examples
### Same Criterion, Different Severity
**Missing alt text (1.1.1, Level A)**:
- Hero image: Impact=Blocker, Likelihood=All users → **CRITICAL**
- Decorative footer icon: Impact=Minor, Likelihood=Rare → **LOW**
**No skip link (2.4.1, Level A)**:
- 3-item navigation: Impact=Friction, Likelihood=Common → **MEDIUM**
- 50-item navigation: Impact=Degraded, Likelihood=All users → **HIGH**
**Poor contrast (1.4.3, Level AA)**:
- Primary CTA button: **CRITICAL**
- Body text: **HIGH**
- Footer link: **MEDIUM**
- Decorative text: **LOW**

View File

@@ -0,0 +1,125 @@
# Phase 4: Manual Validation
These checks CANNOT be automated and require human judgment.
## 1. Color Contrast Validation
**Tool**: [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
### Process
1. Extract all colors from theme configuration
2. Calculate contrast ratios for each text/background pair
3. Document results in gap report
### Requirements
| Element Type | Minimum Ratio |
|--------------|---------------|
| Normal text (< 18pt) | 4.5:1 |
| Large text (>= 18pt or 14pt bold) | 3:1 |
| UI components | 3:1 |
| Focus indicators | 3:1 |
### Severity by Element
- Primary CTA button low contrast = **CRITICAL**
- Body text low contrast = **HIGH**
- Footer link low contrast = **MEDIUM**
- Decorative text low contrast = **LOW**
## 2. Keyboard Navigation Testing
### Basic Test
1. Start at top of page
2. Press Tab repeatedly through all interactive elements
3. Verify:
- [ ] Logical order (left-to-right, top-to-bottom)
- [ ] No keyboard traps (can always Tab away)
- [ ] All functionality accessible
- [ ] Focus indicator visible on every element
### Key Combinations to Test
| Key | Expected Behavior |
|-----|-------------------|
| Tab | Move to next focusable element |
| Shift+Tab | Move to previous focusable element |
| Enter | Activate buttons/links |
| Space | Activate buttons, toggle checkboxes |
| Escape | Close modals/menus |
| Arrow keys | Navigate within components (menus, tabs) |
### Common Keyboard Traps
- Modal dialogs without Escape handling
- Date pickers without keyboard support
- Custom dropdowns that don't cycle
## 3. Screen Reader Testing
### Recommended Tools
- **Mac**: VoiceOver (built-in, Cmd+F5)
- **Windows**: NVDA (free), JAWS (paid)
- **iOS**: VoiceOver (built-in)
- **Android**: TalkBack (built-in)
### What to Test
1. **Landmarks**: Header, nav, main, footer announced
2. **Headings**: Logical hierarchy (h1 → h2 → h3)
3. **Forms**: Labels announced, errors read
4. **Dynamic content**: Status messages announced
5. **Images**: Alt text read appropriately
### VoiceOver Commands (Mac)
| Command | Action |
|---------|--------|
| VO + Right Arrow | Next element |
| VO + Left Arrow | Previous element |
| VO + U | Open rotor (landmarks, headings, links) |
| VO + Space | Activate |
## 4. Zoom and Reflow Testing
### 200% Zoom Test
1. Browser zoom to 200%
2. Verify:
- [ ] No horizontal scrolling
- [ ] No text truncation
- [ ] No overlapping elements
- [ ] All functionality accessible
### 320px Width Test (Mobile Reflow)
1. Resize browser to 320px width
2. Verify:
- [ ] Content reflows to single column
- [ ] No horizontal scroll
- [ ] Touch targets still accessible
- [ ] Text remains readable
## 5. WCAG Interpretation Decisions
Some criteria require human judgment:
### 2.4.5 Multiple Ways
- **Question**: Is this a "set of Web pages"?
- **If < 3 pages**: Likely exempt
- **If >= 3 pages**: Need 2+ navigation methods
### 3.2.6 Consistent Help
- **Question**: Does a help mechanism exist?
- **If no help exists**: Compliant (no requirement)
- **If help exists**: Must be consistently placed
### 1.3.5 Identify Input Purpose
- **Question**: Is this collecting user data from the 53 specified purposes?
- Search inputs: **NOT** in scope
- User email/phone: **IN** scope
## Checklist
- [ ] All color combinations checked against contrast requirements
- [ ] Full keyboard navigation test completed
- [ ] Screen reader testing with at least one tool
- [ ] 200% zoom test passed
- [ ] 320px reflow test passed
- [ ] Applicability decisions documented
## Next Step
Proceed with Report Generation (JSON + Markdown outputs).

View File

@@ -0,0 +1,89 @@
# Phase 1: Setup & Preparation
## Required Tooling Installation
### Static Analysis (Required)
```bash
npm install --save-dev eslint-plugin-jsx-a11y
```
Configure `.eslintrc.js`:
```javascript
module.exports = {
extends: ['plugin:jsx-a11y/recommended'],
// ... other config
};
```
### Runtime Analysis (Required)
```bash
npm install --save-dev jest-axe @axe-core/react
```
### E2E Analysis (Required)
```bash
npm install --save-dev @axe-core/playwright
```
### Optional Tools
```bash
npm install --save-dev @storybook/addon-a11y pa11y-ci
```
## Verification Commands
```bash
# Verify installations
npm list eslint-plugin-jsx-a11y jest-axe @axe-core/playwright
# Check ESLint config
grep -l "jsx-a11y" .eslintrc* 2>/dev/null || echo "jsx-a11y not configured"
```
## Output Directory Setup
```bash
mkdir -p docs/accessibility
```
## Prepare Report Templates
### Gap Report JSON Structure
```json
{
"meta": {
"project": "PROJECT_NAME",
"auditDate": "YYYY-MM-DD",
"auditor": "Claude Code",
"protocolVersion": "2.0.0",
"wcagVersion": "2.2",
"wcagLevel": "AA"
},
"summary": {
"totalCriteria": 60,
"passing": 0,
"failing": 0,
"notApplicable": 0,
"compliancePercentage": 0,
"severityBreakdown": {
"critical": 0,
"high": 0,
"medium": 0,
"low": 0
}
},
"findings": []
}
```
## Pre-Audit Checklist
- [ ] eslint-plugin-jsx-a11y installed and configured
- [ ] jest-axe available for component tests
- [ ] @axe-core/playwright available for E2E tests
- [ ] docs/accessibility/ directory exists
- [ ] Project uses React + TypeScript (protocol optimized for this stack)
## Next Step
Continue with Static Analysis (ESLint jsx-a11y scan).