원클릭으로
accessibility
// Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
// Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
Creates structured plans from requirements. Generates comprehensive plans with steps, dependencies, risks, and success criteria. Coordinates with specialist agents for planning input and validates plan completeness. Uses template-renderer for formatted output.
Create, validate, and convert skills for the agent ecosystem. Enforces standardized structure for consistency. Enables self-evolution by creating new skills on demand, converting MCP servers and codebases to skills.
Research-backed skill refresh workflow for updating existing skills with TDD checkpoints, memory-aware integration, and EVOLVE/reflection trigger handling.
Use when you want to improve response quality through meta-cognitive reasoning. Applies 15+ reasoning methods to reconsider and refine initial outputs.
N-round opposing-stance debates for trade-off analysis. Assigns pro/con roles to agents, runs structured debate rounds with quality scoring, and produces a moderator synthesis with confidence-rated recommendation. Generalizable to architecture, technology, security, and design decisions.
Force adversarial code review stance that eliminates confirmation bias — reviewer must find issues or re-analyze
| verified | true |
| lastVerifiedAt | "2026-02-19T07:30:00.000Z" |
| name | accessibility |
| description | Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance. |
| version | 2.2.0 |
| model | sonnet |
| invoked_by | both |
| user_invocable | true |
| tools | ["Read","Write","Edit"] |
| globs | src/**/*.* |
| best_practices | ["Use semantic HTML as foundation","Add ARIA only when semantic HTML insufficient","Test with real assistive technologies","Follow WCAG 2.2 AA minimum (published October 2023, ISO/IEC 40500:2025)","Ensure touch/pointer targets meet 24x24 CSS pixel minimum","Provide keyboard/single-pointer alternatives for all drag interactions","Do not require cognitive function tests in authentication flows"] |
| error_handling | graceful |
| streaming | supported |
| source | builtin |
| trust_score | 100 |
| provenance_sha | 2a8a150aa22634b9 |
Review component structure for proper semantic elements:
Check for:
<header>, <nav>, <main>, <article>, <section>, <aside>, <footer> instead of generic <div><button> for clickable elements (not <div onclick>)<a> for navigation links<form>, <input>, <label> for forms<h1> through <h6>)Example:
<!-- ❌ BAD -->
<div class="header">
<div claass="nav">
<div class="nav-item" onclick="navigate()">Home</div>
</div>
</div>
<!-- ✅ GOOD -->
<header>
<nav>
<a href="/">Home</a>
</nav>
</header>
Add ARIA attributess ONLY when semantic HTML is insufficient:
Common Patterns:
| Use Case | ARIA Attributes | Example |
|---|---|---|
| Custom button | role="button", tabindex="0" | <div role="button" tabindex="0"> |
| Modal dialog | role="dialog", aria-modal="true" | <div role="dialog" aria-modal="true"> |
| Alert | role="alert", aria-live="assertive" | <div role="alert">Error occurred</div> |
| Tab panel | role="tabpanel", aria-labelledby | <div role="tabpanel" aria-labelledby="tab-1"> |
Rules:
<button role="button"> is unnecessary)aria-label for icon buttons without textaria-hidden="true" for decorative elementsaria-live regions for dynamic contentExample:
<!-- Icon button needs aria-label -->
<button aria-label="Close dialog">
<i class="icon-close" aria-hidden="true"></i>
</button>
<!-- Dynamic content needs live region -->
<div role="alert" aria-live="assertive">Form submitted successfully</div>
Verify all interactive elements are keyboard accessible:
Requirements:
Focus Management:
:focus styles)Example:
// Focus trap in modal
function openModal(modal) {
modal.style.display = 'block';
const firstFocusable = modal.querySelector('button, input, a');
firstFocusable.focus();
trapFocus(modal); // Prevent escape from modal
}
function trapFocus(container) {
const focusableElements = container.querySelectorAll('button, input, select, textarea, a[href]');
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
container.addEventListener('keydown', e => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
e.preventDefault();
} else if (!e.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
e.preventDefault();
}
}
});
}
WCAG 2.2 added 9 new success criteria. Verify compliance with the applicable ones:
When a keyboard-focused element scrolls into view, it must not be completely hidden by sticky headers/footers or overlapping UI. At least part of the focused element must always be visible.
/* Prevent focus from hiding behind sticky headers */
:focus-visible {
scroll-margin-top: 80px; /* Height of sticky header + buffer */
scroll-margin-bottom: 60px; /* Height of sticky footer + buffer */
}
Test: Tab through all interactive elements — verify none are fully hidden behind banners, cookie notices, or sticky bars.
The focused component must be fully visible (not just partially). Sticky UI must not overlap focus at all.
Focus indicators must have: area of at least the perimeter of the unfocused component times 2 CSS pixels, and contrast ratio of at least 3:1 between focused and unfocused states.
/* Meeting 2.4.13 Focus Appearance (AAA) */
:focus-visible {
outline: 3px solid #005fcc;
outline-offset: 2px;
/* 3px thickness > 2px minimum; #005fcc on white = 7.1:1 contrast */
}
All drag-and-drop functionality MUST have a single-pointer (click/tap) alternative. Users who cannot perform precise drag gestures must be able to accomplish the same task.
<!-- Sortable list: drag alternative via buttons -->
<ul>
<li draggable="true" id="item-1">
Item 1
<button aria-label="Move Item 1 up" onclick="moveUp('item-1')">↑</button>
<button aria-label="Move Item 1 down" onclick="moveDown('item-1')">↓</button>
</li>
</ul>
<!-- Slider: keyboard alternative provided natively -->
<input type="range" min="0" max="100" value="50" aria-label="Volume" />
<!-- Alternatively: add an input[type=number] companion -->
<input type="number" min="0" max="100" value="50" aria-label="Volume value" />
Test: Identify all drag interactions. Verify each has a non-drag equivalent (buttons, context menus, keyboard shortcuts).
All pointer targets (buttons, links, checkboxes, radio inputs) must be at least 24x24 CSS pixels, OR have sufficient spacing so the 24x24 area does not overlap another target.
/* Ensure minimum target size */
button,
a,
input[type='checkbox'],
input[type='radio'],
select {
min-width: 24px;
min-height: 24px;
}
/* Inline links: use padding to increase hit area without visual size change */
a {
padding: 4px 0;
}
/* Recommended: 44x44 CSS pixels for primary actions (mobile-friendly) */
.primary-action {
min-width: 44px;
min-height: 44px;
}
Test: Measure all interactive elements. Verify none fall below 24x24 CSS pixels (use browser DevTools element inspector).
If a help mechanism (contact link, chat widget, phone number, FAQ link) appears on multiple pages, it must appear in the same relative order in the page content.
<!-- Help mechanism must appear consistently across pages -->
<footer>
<nav aria-label="Help resources">
<!-- This order must not change between pages -->
<a href="/faq">FAQ</a>
<a href="/contact">Contact Support</a>
<a href="tel:+18005551234">1-800-555-1234</a>
</nav>
</footer>
Test: Navigate between pages. Verify help links/widgets appear in the same order each time.
Information previously entered by the user must be auto-populated or available for selection when the same information is requested again in the same session/process (e.g., multi-step checkout forms).
<!-- Step 2: Billing address — pre-fill from Step 1 shipping -->
<fieldset>
<legend>Billing Address</legend>
<label>
<input type="checkbox" id="same-as-shipping" />
Same as shipping address
</label>
<!-- When checked: auto-populate billing fields from shipping fields -->
</fieldset>
Exceptions: Re-entering passwords for security confirmation, selecting items from a list.
Authentication processes MUST NOT require users to complete a cognitive function test (solve puzzle, identify images, remember/transcribe a code) unless an accessible alternative is provided.
Allowed alternatives:
<!-- GOOD: Allow paste in password fields -->
<input type="password" id="password" autocomplete="current-password" />
<!-- Do NOT add: onpaste="return false" -->
<!-- GOOD: Provide alternative to image CAPTCHA -->
<div role="group" aria-labelledby="captcha-label">
<span id="captcha-label">Verify you are human</span>
<img src="captcha.png" alt="CAPTCHA challenge" />
<input type="text" aria-describedby="captcha-label" />
<a href="?audio-captcha">Use audio CAPTCHA instead</a>
<a href="?email-login">Use email link instead</a>
</div>
Test: Identify all authentication steps. Verify no step requires a cognitive test without an alternative method.
No cognitive function test is required, even with alternatives provided.
Check all text meets WCAG contrast ratios:
Standards:
| Text Size | WCAG AA | WCAG AAA |
|---|---|---|
| Normal text (< 18pt) | 4.5:1 | 7:1 |
| Large text (≥ 18pt or 14pt bold) | 3:1 | 4.5:1 |
| UI components | 3:1 | - |
Tools:
Example:
/* ❌ BAD - Innsufficient contrast */
.text {
color: #777;
background: #fff;
} /* 4.47:1 - fails AA */
/* ✅ GOOD - Sufficient contrast */
.text {
color: #595959;
background: #fff;
} /* 7:1 - passes AAA */
/* ✅ GOOD - Don't rely on color alone */
.error {
color: #d00;
border-left: 4px solid #d00; /* Visual indicator beyond color */
}
.error::before {
content: '⚠️ ';
} /* Icon indicator */
Ensure proper sscreen reader experience:
Alt Text for Images:
<!-- ❌ BAD - Missing or redundant alt -->
<img src="logo.png" />
<img src="decorative.png" alt="decorative image" />
<!-- ✅ GOOD -->
<img src="logo.png" alt="Company y Logo" />
<img src="decorative.png" alt="" role="presentation" />
ARIA Labels for Icon Buttons:
<!-- ❌ BAD - No label for screen readers -->
<button><i class="icon-delete"></i></button>
<!-- ✅ GOOD -->
<but tton aria-label="Delete item">
<i class="icon-delete" aria-hidden="true"></i>
</button>
Live Regions for Dynamic Content:
<!-- Announce errors immediately -->
<div role="alert" aria-live="assertive">Error: Invalid email address</div>
<!-- Announce status updates politely -->
<div aria-live="polite" aria-atomic="true">Loading results... 3 of 10 loaded</div>
Ensure all form inputs are properly labeled and validated:
Requirements:
<label> elements<fieldset> and <legend> for grouped inputsaria-describedbyaria-required="true" or required attributeExample:
<!-- ✅ GOOD Form Structure -->
<form>
<fieldset>
<legend>Personal Information</legend>
<label for="name">Name (required)</label>
<input id="name" type="textt" required aria-required="true" aria-describedby="name-error" />
<span id="name-error" role="alert" class="error" aria-live="polite">
<!-- Error message appears here -->
</span>
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="email-hint" />
<span id="email-hint" class="hint">We'll never share your email</span>
</fieldset>
</form>
Document findings with:
Skill({ skill: 'accessibility' });
Input: React component with custom modal Output:
Skill({ skill: 'accessibility', args: 'color-contrast' });
Input: CSS file with color definitions Output:
Skill({ skill: 'accessibility', args: 'forms' });
Input: Form component Output:
<best_practices>
<div> for everything (no semantic meaning)tabindex > 0 (disrupts natural tab order)| Anti-Pattern | Problem | Fix |
|---|---|---|
<div onclick> | Not keyboard accessible | Use <button> |
| No alt text | Screen readers can't describe | Add meaningful alt attribute |
| Color-only info | Color blind users miss it | Add text/icons |
| No focus indicators | Users lost in navigation | Add :focus-visible styles |
| Auto-play media | Disruptive for screen readers | Add controls, pause option |
<div> for everything | No semantic structure | Use semantic HTML |
| Sticky header without scroll-margin | Focus hidden behind sticky bar (2.4.11) | Add scroll-margin-top to :focus-visible |
| Drag-only sortable lists | Users with motor disabilities can't sort (2.5.7) | Add Up/Down buttons for each item |
| 16x16px icon buttons | Below 24x24 minimum target size (2.5.8) | Set min-width: 24px; min-height: 24px |
| CAPTCHA without alternative | Cognitive barrier to authentication (3.3.8) | Provide email magic link or passkey option |
onpaste="return false" | Blocks password manager paste (3.3.8) | Remove paste block from password fields |
| Repeated form fields in checkout | Redundant data entry (3.3.7) | Auto-populate with previously entered values |
Before finalizing accessibility review:
WCAG 2.1 AA (existing requirements):
alt="" for decorative)WCAG 2.2 AA (new requirements — October 2023, ISO/IEC 40500:2025):
<button>, <nav>, <main>, etc.).outline: none without a replacement is an immediate WCAG failure. Keyboard users become completely lost..claude/rules/accessibility.md - Complete accessibility rulesBefore starting:
cat .claude/context/memory/learnings.md
Check for:
After completing:
.claude/context/memory/learnings.md.claude/context/memory/issues.md.claude/context/memory/decisions.mdASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.