Help us improve
Share bugs, ideas, or general feedback.
From storybook-assistant
Use this skill when the user writes/edits components, asks to "fix accessibility issues", "add ARIA labels", "improve accessibility", "check WCAG compliance", "remediate a11y violations", mentions "screen reader support", "keyboard navigation", or wants AI-powered accessibility fixes with one-click application. Automatically analyzes components for a11y issues and suggests context-aware fixes. Trigger on PostToolUse hook or explicit request.
npx claudepluginhub flight505/storybook-assistantHow this skill is triggered — by the user, by Claude, or both
Slash command
/storybook-assistant:accessibility-remediationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Automatically detect and fix accessibility issues in components with AI-powered analysis, context-aware fix suggestions, and one-click application. Goes beyond detection to provide ranked remediation options based on WCAG 2.2 best practices.
Web accessibility discipline: semantic HTML first, ARIA only when needed, keyboard access always. Invoke whenever task involves any interaction with accessible web content -- writing, reviewing, refactoring, or debugging HTML/CSS/JS for WCAG compliance, ARIA usage, keyboard navigation, focus management, screen reader support, or accessible component patterns.
Audits specific design system components for WCAG 2.1 AA accessibility across keyboard navigation, screen readers, color contrast, focus management, and ARIA. Provides PASS/FAIL/WARN with remediation guidance.
Implements WCAG 2.1/2.2 compliance, ARIA patterns, keyboard navigation, focus management, and accessibility testing for web components.
Share bugs, ideas, or general feedback.
Automatically detect and fix accessibility issues in components with AI-powered analysis, context-aware fix suggestions, and one-click application. Goes beyond detection to provide ranked remediation options based on WCAG 2.2 best practices.
This skill transforms accessibility from a manual checklist into an automated workflow with intelligent fix suggestions.
Automatically check components for WCAG 2.2 violations:
AI understands component purpose and suggests appropriate fixes:
Apply fixes instantly without manual implementation:
Built-in support for latest accessibility standards:
When you create or edit a component, the accessibility-auditor agent automatically:
You can also explicitly request accessibility analysis:
User: "Check this Button component for accessibility issues"
Claude: [Runs accessibility-auditor agent]
User: "Fix the accessibility violations in Modal.tsx"
Claude: [Analyzes, suggests fixes, applies selected fix]
Problem: Buttons, links, or inputs without labels
Examples:
// ❌ Bad: Button has no accessible name
<button onClick={handleClose}>×</button>
// ✅ Fix Option 1: Visible text with icon (BEST)
<button onClick={handleClose}>
<span aria-hidden="true">×</span>
<span className="sr-only">Close dialog</span>
</button>
// ✅ Fix Option 2: aria-label (GOOD)
<button onClick={handleClose} aria-label="Close dialog">×</button>
// ✅ Fix Option 3: title attribute (ACCEPTABLE)
<button onClick={handleClose} title="Close dialog">×</button>
AI Suggestion:
Context: Close button in modal header
Recommendation: Option 1 (best for all users - visible + announced)
WCAG: 4.1.2 Name, Role, Value (Level A)
Problem: Text/UI elements don't meet WCAG contrast ratios
Examples:
// ❌ Bad: Contrast ratio 2.1:1 (fails WCAG AA)
<button style={{ color: '#999', background: '#fff' }}>Submit</button>
// ✅ Fix: Contrast ratio 4.6:1 (passes AA)
<button style={{ color: '#666', background: '#fff' }}>Submit</button>
// ✅ Better: Contrast ratio 7.2:1 (passes AAA)
<button style={{ color: '#333', background: '#fff' }}>Submit</button>
AI Suggestion:
Issue: Text color #999 on white background (2.1:1 - fails)
Required: 4.5:1 for normal text (WCAG AA)
Suggested colors:
- #666 (4.6:1) ✓ WCAG AA
- #555 (5.8:1) ✓ WCAG AA
- #333 (7.2:1) ✓ WCAG AAA
WCAG: 1.4.3 Contrast (Minimum) (Level AA)
Problem: Form inputs without associated labels
Examples:
// ❌ Bad: No label association
<input type="email" placeholder="Email" />
// ✅ Fix Option 1: Proper label element (BEST)
<label htmlFor="email">
Email address
<input id="email" type="email" placeholder="you@example.com" />
</label>
// ✅ Fix Option 2: Label with nesting (GOOD)
<label>
Email address
<input type="email" placeholder="you@example.com" />
</label>
// ✅ Fix Option 3: aria-label (ACCEPTABLE)
<input type="email" aria-label="Email address" placeholder="Email" />
AI Suggestion:
Context: Email input in login form
Recommendation: Option 1 (explicit label with htmlFor - most robust)
WCAG: 3.3.2 Labels or Instructions (Level A)
Problem: Interactive elements lack visible focus state
Examples:
// ❌ Bad: Focus outline removed
<button style={{ outline: 'none' }} onClick={handleClick}>
Click me
</button>
// ✅ Fix Option 1: Custom focus-visible (BEST)
<button
className="focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={handleClick}
>
Click me
</button>
// ✅ Fix Option 2: Custom outline (GOOD)
<button
style={{ outline: 'none' }}
className="focus:outline-blue focus:outline-2 focus:outline-offset-2"
onClick={handleClick}
>
Click me
</button>
// ✅ Fix Option 3: Default outline (ACCEPTABLE)
<button onClick={handleClick}>Click me</button>
AI Suggestion:
Issue: outline: none removes focus indicator
Solution: Use :focus-visible for keyboard-only focus styling
WCAG: 2.4.7 Focus Visible (Level AA)
Problem: Incorrect or redundant ARIA attributes
Examples:
// ❌ Bad: Redundant role on button
<button role="button" onClick={handleClick}>Submit</button>
// ✅ Fix: Remove redundant role (native button already has role)
<button onClick={handleClick}>Submit</button>
// ❌ Bad: Invalid ARIA attribute
<div role="button" onClick={handleClick}>Click</div>
// ✅ Fix: Use semantic button element (BEST)
<button onClick={handleClick}>Click</button>
// ✅ Fix: Add keyboard support if div required (ACCEPTABLE)
<div
role="button"
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
tabIndex={0}
>
Click
</div>
AI Suggestion:
Issue: Redundant role="button" on <button> element
Solution: Remove role attribute (native HTML provides this)
WCAG: 4.1.2 Name, Role, Value (Level A)
Problem: Images without alternative text
Examples:
// ❌ Bad: No alt attribute
<img src="/avatar.jpg" />
// ✅ Fix Option 1: Descriptive alt (BEST - informative images)
<img src="/avatar.jpg" alt="Profile photo of John Doe" />
// ✅ Fix Option 2: Empty alt (GOOD - decorative images)
<img src="/decorative-pattern.png" alt="" aria-hidden="true" />
// ✅ Fix Option 3: aria-label (ACCEPTABLE - when alt insufficient)
<img
src="/complex-chart.png"
alt="Sales data visualization"
aria-label="Bar chart showing 40% increase in Q4 sales"
/>
AI Suggestion:
Context: User avatar in profile card
Recommendation: Descriptive alt text with user name
WCAG: 1.1.1 Non-text Content (Level A)
// User creates Modal component
export function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content">
<button onClick={onClose}>×</button>
{children}
</div>
</div>
);
}
AI Detection (Automatic):
❌ 4 accessibility issues detected in Modal.tsx
Issue 1: Missing accessible name (Line 7)
Element: <button>×</button>
WCAG: 4.1.2 Name, Role, Value (Level A)
Fix options:
[1] Add sr-only text: <button><span aria-hidden>×</span><span class="sr-only">Close</span></button>
[2] Add aria-label: <button aria-label="Close modal">×</button>
[3] Add title: <button title="Close">×</button>
Issue 2: Missing ARIA role (Line 5)
Element: <div className="modal-overlay">
WCAG: 4.1.2 Name, Role, Value (Level A)
Fix: Add role="dialog" and aria-modal="true"
Issue 3: Missing focus trap (Line 6)
Element: Modal content
WCAG: 2.4.3 Focus Order (Level A)
Fix: Implement focus trap to prevent tabbing out of modal
Issue 4: No Escape key handler (Line 5)
Element: Modal
WCAG: 2.1.2 No Keyboard Trap (Level A)
Fix: Add onKeyDown handler for Escape key
Apply fixes? [All] [Select] [Custom] [Skip]
User selects: "All"
AI applies fixes:
import { useEffect, useRef } from 'react';
import { FocusTrap } from './FocusTrap';
export function Modal({ isOpen, onClose, children }) {
const modalRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!isOpen) return;
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('keydown', handleEscape);
modalRef.current?.focus();
return () => document.removeEventListener('keydown', handleEscape);
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div
className="modal-overlay"
onClick={onClose}
aria-hidden={!isOpen}
>
<FocusTrap>
<div
ref={modalRef}
className="modal-content"
role="dialog"
aria-modal="true"
tabIndex={-1}
onClick={(e) => e.stopPropagation()}
>
<button
onClick={onClose}
aria-label="Close modal"
>
<span aria-hidden="true">×</span>
<span className="sr-only">Close</span>
</button>
{children}
</div>
</FocusTrap>
</div>
);
}
Verification:
✓ All issues resolved
✓ Modal now passes WCAG 2.2 Level AA
✓ Added focus trap component (FocusTrap.tsx)
✓ Added sr-only CSS utility
Run accessibility test? [Yes] [No]
This skill works seamlessly with the testing-suite skill:
Combined workflow:
1. Create component → AI detects issues → Apply fixes
2. Run tests → Verify with axe-core → Pass ✓
3. Create stories → Test keyboard navigation → Pass ✓
4. Commit → CI runs a11y tests → Deploy ✓
AI remembers your fix preferences:
You've chosen aria-label for icon buttons 5 times.
Default suggestion updated to rank aria-label first for icon buttons.
Fix multiple components at once:
User: "Fix all accessibility issues in src/components/"
Scanning 23 components...
✓ Button.tsx: 2 issues fixed
✓ Input.tsx: 3 issues fixed
✓ Modal.tsx: 4 issues fixed
⚠️ Dropdown.tsx: 1 issue requires custom fix
✓ Card.tsx: 1 issue fixed
21/23 components now pass WCAG AA
2 components need manual review
Define project-specific a11y rules:
# .storybook/a11y-config.yml
rules:
- id: 'custom-button-label'
description: 'All buttons must have aria-label or visible text'
severity: 'error'
fix: 'suggest-aria-label'
- id: 'custom-min-contrast'
description: 'Require WCAG AAA contrast (7:1) for all text'
severity: 'warning'
fix: 'suggest-darker-color'
This skill includes Python scripts for deep analysis:
Analyzes component AST for accessibility issues:
See: skills/accessibility-remediation/scripts/analyze_component.py
Generates context-aware fix suggestions:
See: skills/accessibility-remediation/scripts/generate_fixes.py
Complete reference of all WCAG 2.2 success criteria with:
See: skills/accessibility-remediation/references/wcag-rules.md
Library of proven fix patterns:
See: skills/accessibility-remediation/examples/fix-patterns.md
If AI suggests unnecessary fixes:
User: "This is a false positive - the component is decorative"
Claude: Understood. I'll:
1. Mark this pattern as acceptable
2. Update detection rules
3. Remember for future similar cases
Would you like to add this to .storybook/a11y-ignore.yml?
For components with complex accessibility needs:
User: "This datepicker needs custom keyboard navigation"
Claude: This component requires manual implementation:
1. Arrow keys for date navigation
2. Page Up/Down for month navigation
3. Home/End for week navigation
4. Escape to close
I can provide a reference implementation from accessible datepicker patterns.
Would you like me to generate a template?
Transform accessibility from manual checklist to automated workflow:
Result: Ship accessible components by default with 80% less effort.