A11y fix
Accessibility expertise for AI coding agents.
npx -y skills add badass-courses/a11y-agent --skill a11y-fixAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Fix accessibility issues in current code. Works through findings from a11y-audit, a11y-scan, or a11y-review. Makes changes, explains rationale, notes what to test manually. Use when asked to "fix accessibility", "make this accessible", or after any a11y assessment.
SKILL.md
4.8 KB, as published. Nobody here has run it
Fix accessibility issues in the current code. Target {{area}} if specified, otherwise work through all identified issues from most critical to least.
→ Consult the a11y-agent skill and its reference files for correct patterns.
Fix Process
For each issue:
- Identify the problem — what fails and which WCAG criterion applies
- Implement the fix — use the correct semantic pattern
- Explain why — brief rationale for the change
- Flag what to test — note keyboard and screen reader testing needed
Fix Priority Order
- Keyboard access — divs→buttons, add focus management, skip links
- Accessible names — labels on inputs, aria-labels on icon buttons, alt on images
- Semantic structure — heading hierarchy, landmarks, lists
- ARIA states — expanded, pressed, selected, invalid, current
- Focus management — modal trapping, return focus, roving tabindex
- Screen reader announcements — live regions for dynamic content
- Visual — contrast, focus indicators, reflow, motion
Common Fixes
div → button
Replace <div onClick> with <button>. Update CSS to reset button styles:
.your-button {
background: none;
border: none;
padding: 0;
cursor: pointer;
font: inherit;
color: inherit;
}
Add form labels
<!-- Before -->
<input placeholder="Email">
<!-- After -->
<label for="email">Email</label>
<input id="email" type="email" placeholder="[email protected]">
Fix heading hierarchy
Don't change visual appearance — add CSS utility classes instead:
<!-- Before: skipped h2 -->
<h1>Site Name</h1>
<h3>Section Title</h3>
<!-- After: correct hierarchy with style class -->
<h1>Site Name</h1>
<h2 class="heading-sm">Section Title</h2>
Add focus indicator
/* Remove the bad wildcard reset if present */
/* * { outline: none; } ← DELETE THIS */
/* Add visible focus styles */
:focus-visible {
outline: 2px solid var(--focus-color, #005fcc);
outline-offset: 2px;
}
Restore focus outline that was removed
Look for * { outline: 0 } or * { outline: none } in stylesheets and remove it.
prefers-reduced-motion
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Mega menu — hidden items still tabbable
/* Before: items invisible but tabbable */
.submenu { display: flex; opacity: 0; }
.submenu.active { opacity: 1; }
/* After: items fully hidden when inactive */
.submenu { display: none; }
.submenu.active { display: flex; }
Add aria-expanded on the trigger button. Bind Escape to close and return focus to trigger.
Client-side routing — missing focus management
After route change, update document.title and move focus to new content:
useEffect(() => {
document.title = `${pageTitle} | Site Name`;
mainRef.current?.focus();
}, [location.pathname]);
Add tabindex="-1" to the focus target if it's not natively focusable.
Form validation — errors not announced
The live region element MUST exist at page load. Inject error text into it:
<!-- Present at page load, starts empty -->
<p role="alert" aria-atomic="true">{errorMessage}</p>
On submit failure: set error message text, mark fields with aria-invalid="true", link errors via aria-describedby, focus the first invalid field.
Modal — background not inert
function openModal() {
document.querySelector('main').inert = true;
dialogRef.current.focus();
}
function closeModal() {
document.querySelector('main').inert = false;
triggerRef.current.focus(); // Return focus to trigger
}
After Each Fix
- Tab through the component — does keyboard access work?
- Run axe DevTools or a11y-scan — did violations decrease?
- Test with a screen reader if the fix involves ARIA or announcements
- Check contrast if the fix involves visual changes
- Zoom to 200% if the fix involves layout
After Fixing
Remind the developer to manually test:
- Tab through the component with keyboard only
- Test with VoiceOver (Mac/Safari) or NVDA (Windows/Chrome)
- Check contrast with CCA or DevTools
- Zoom to 200% and verify reflow
- Run axe DevTools scan
Automated tests can verify regressions but can't replace manual testing with assistive technology.