This skill should be used when the user asks about accessibility concerns, including WCAG compliance (any success criterion including SC 1.3.5 autocomplete, SC 2.4.11 focus obscured), ARIA roles and attributes, screen reader behavior, axe-core or WAVE audit failures, color and non-text contrast, keyboard navigation, focus trapping and management, skip links, touch targets, VPAT reports, or accessible form patterns. Also triggers when the user asks whether a UI library such as shadcn or Radix handles keyboard interactions — but only if the question is specifically about accessibility behavior, not general usage.
From hugin-coworknpx claudepluginhub michelve/hugin-marketplace --plugin hugin-coworkThis skill uses the workspace's default tool permissions.
LICENSE.txtevals/evals.jsonevals/run_loop_results/2026-03-12_103908/report.htmlevals/run_loop_results/2026-03-12_103908/results.jsonevals/run_loop_results/2026-03-12_104112/report.htmlevals/run_loop_results/2026-03-12_104112/results.jsonevals/run_loop_results/2026-03-12_105717/logs/improve_iter_1.jsonevals/run_loop_results/2026-03-12_105717/logs/improve_iter_2.jsonevals/run_loop_results/2026-03-12_105717/logs/improve_iter_3.jsonevals/run_loop_results/2026-03-12_105717/logs/improve_iter_4.jsonevals/run_loop_results/2026-03-12_105717/report.htmlevals/run_loop_results/2026-03-12_105717/results.jsonevals/run_loop_results/2026-03-12_111808/logs/improve_iter_1.jsonevals/run_loop_results/2026-03-12_111808/logs/improve_iter_2.jsonevals/run_loop_results/2026-03-12_111808/logs/improve_iter_3.jsonevals/run_loop_results/2026-03-12_111808/logs/improve_iter_4.jsonevals/run_loop_results/2026-03-12_111808/report.htmlevals/run_loop_results/2026-03-12_111808/results.jsonevals/run_loop_results/2026-03-12_112056/logs/improve_iter_1.jsonevals/run_loop_results/2026-03-12_112056/report.htmlSearches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Guides agent creation for Claude Code plugins with file templates, frontmatter specs (name, description, model), triggering examples, system prompts, and best practices.
Standard: WCAG 2.2 AA required · AAA aspirational Stack: React 19 · shadcn/ui · Tailwind CSS v4 · Radix UI (
radix-uiv1.4.3) POUR Principles: Perceivable · Operable · Understandable · Robust
Implement WCAG 2.2 AA compliant accessibility in React 19 components using the draft_v0 stack. Items marked (AAA) exceed the required AA level and are aspirational best practices to pursue where feasible.
| Principle | Key Topics | Reference Files |
|---|---|---|
| Perceivable | Alt text, landmarks, headings, data tables, color contrast, non-text contrast, text spacing, reflow | semantic-html.md, mobile-touch.md |
| Operable | Keyboard, focus management, focus not obscured, skip links, page titles, target size, dragging, pointer gestures | keyboard-navigation.md, focus-management.md, mobile-touch.md, wcag22-new-criteria.md |
| Understandable | ARIA, forms, error handling, auth, redundant entry, consistent help, live regions | aria-attributes.md, forms-a11y.md |
| Robust | Screen reader support, status messages, automated + manual testing, VPAT, CI/CD | testing-a11y.md |
WCAG 2.2 added 9 success criteria not present in WCAG 2.1. All AA items are required; AAA items are aspirational.
| SC | Title | Level | Requirement in One Line |
|---|---|---|---|
| 2.4.11 | Focus Not Obscured (Minimum) | AA | Focused element not fully hidden behind sticky/fixed UI chrome |
| 2.4.12 | Focus Not Obscured (Enhanced) | AAA | Focused element not obscured at all — not even partially |
| 2.4.13 | Focus Appearance | AAA | Focus indicator ≥ 2px perimeter, 3:1 contrast ratio |
| 2.5.7 | Dragging Movements | AA | Every drag action has a single-pointer (click/tap) alternative |
| 2.5.8 | Target Size (Minimum) | AA | Interactive targets ≥ 24×24 CSS pixels |
| 3.2.6 | Consistent Help | A | Help mechanisms in same relative position across pages |
| 3.3.7 | Redundant Entry | A | Previously entered data auto-populated or selectable |
| 3.3.8 | Accessible Authentication (Minimum) | AA | No cognitive puzzle required in auth unless alternative exists |
| 3.3.9 | Accessible Authentication (Enhanced) | AAA | No cognitive test in any auth step, no exceptions |
See wcag22-new-criteria.md for detailed implementation guidance, code examples, common failures, and test procedures for each criterion.
| Tool / Pattern | How to Use | Notes |
|---|---|---|
FocusScope | import { FocusScope } from 'radix-ui' | Focus trapping for modals/dialogs. Already installed (v1.4.3). |
sr-only | className="sr-only" | Visually hidden, screen-reader visible text. |
focus-visible: | focus-visible:ring-[3px] focus-visible:ring-ring/50 | Focus ring on keyboard interaction only (not mouse click). |
motion-reduce: | motion-reduce:transition-none | Respects prefers-reduced-motion OS preference. |
aria-*: | aria-invalid:border-destructive | Style elements based on ARIA state via Tailwind variant. |
scroll-mt-20 | focus-visible:scroll-mt-20 | Scroll margin for Focus Not Obscured (2.4.11 AA). |
min-h-6 min-w-6 | className="min-h-6 min-w-6" | 24×24px minimum target size (2.5.8 AA). |
min-h-[44px] min-w-[44px] | className="min-h-[44px] min-w-[44px]" | 44×44px recommended target size (2.5.5 AAA). |
| Custom hooks | src/client/hooks/ (@/hooks) | useKeyPress, useReducedMotion, useDocumentTitle, useAnnounce. |
shadcn/ui components are accessible by default — built on Radix UI primitives that handle ARIA roles, keyboard navigation, and focus management automatically. Do not re-implement what these components already provide.
| Component | What Radix Handles Automatically |
|---|---|
Dialog | role="dialog", aria-modal, focus trap (FocusScope), Escape to close, return focus on close |
AlertDialog | role="alertdialog", focus trap, prevents accidental Escape dismissal |
DropdownMenu | role="menu" / menuitem, roving tabindex, Arrow keys, Escape to close |
Select | role="listbox" / option, Arrow keys, type-ahead search |
Tabs | role="tablist" / tab / tabpanel, Arrow Left/Right navigation |
Checkbox | role="checkbox", Space to toggle, aria-checked |
Tooltip | role="tooltip", hoverable (pointer can move over it), dismissible with Escape, persistent |
Popover | Focus-managed popup, Escape to close, returns focus to trigger |
Accordion | aria-expanded, Arrow keys for panel navigation |
Slider | role="slider", aria-valuenow / min / max, Arrow key adjustments |
Switch | role="switch", aria-checked, Space/Enter to toggle |
Install via: npx shadcn@latest add dialog dropdown-menu select tabs — components appear in src/client/components/ui/ and must never be modified directly.
Use native HTML5 elements — they carry implicit ARIA roles and need no role attribute.
| Landmark | Element | aria-label needed? | Notes |
|---|---|---|---|
| Banner | <header> | No | Top-level only; one per page |
| Navigation | <nav> | Yes (if multiple exist) | Label each distinctly |
| Main | <main> | No | One per page; add id="main-content" tabIndex={-1} |
| Complementary | <aside> | Yes | Describe the supporting content |
| Contentinfo | <footer> | No | Top-level only; one per page |
| Search | <search> | No | Preferred over role="search" |
Rules: one <main> per page · label every <nav> when multiple exist · never nest <main> inside another landmark · give <main> id="main-content" tabIndex={-1} for skip-link targeting.
See semantic-html.md for the full AppLayout implementation.
Skip links bypass repeated navigation — required by WCAG 2.4.1 (Level A). Place <SkipLink /> as the first element in <App />. It uses sr-only focus:not-sr-only so it appears only on keyboard Tab.
Requirements:
#main-content) must have tabIndex={-1} to receive programmatic focusSee focus-management.md for the SkipLink component and App.tsx placement.
WCAG 2.4.2 (Level A): every page needs a unique, descriptive document.title that updates on route change.
useDocumentTitle(pageTitle) in every route component. Format: "Page Name — Site Name".<RouteAnnouncer /> once in <App /> — announces the new title to screen readers on navigation without moving focus.See focus-management.md for both implementations.
See keyboard-navigation.md for:
useKeyPress hookArrow + Home/End/Ctrl+Home/Ctrl+End)Previous/Next/Pause patternsSee aria-attributes.md for:
See focus-management.md for:
FocusScope (Radix UI) — focus trapping for modalsscroll-margin-top fix for sticky headersPlace live region containers in your layout so they persist between renders — the container must exist in the DOM before content is injected:
// Polite — screen reader finishes current speech before announcing
<div aria-live="polite" aria-atomic="true">
{statusMessage}
</div>
// Assertive — interrupts screen reader immediately (use sparingly)
<div role="alert" aria-live="assertive">
{errorMessage}
</div>
// Status updates (WCAG 4.1.3 A) — equivalent to aria-live="polite" + aria-atomic
<div role="status">
{`${resultCount} results found`}
</div>
For imperative announcements (filter applied, item saved, search complete) without moving focus, use the useAnnounce hook from @/hooks/useAnnounce.
See aria-attributes.md for the implementation.
See reduced-motion.md for:
useReducedMotion hookmotion-reduce: variant (preferred for most cases)useReducedMotion integration@media (prefers-reduced-motion: reduce) global overrides| Content | Required Ratio |
|---|---|
| Normal text (< 18pt / < 14pt bold) | 4.5:1 |
| Large text (≥ 18pt or ≥ 14pt bold) | 3:1 |
| UI components & graphical objects (borders, icons, chart lines) | 3:1 (SC 1.4.11) |
| Inactive/disabled UI, pure decoration | No requirement |
(AAA) Enhanced contrast (SC 1.4.6): Normal text 7:1 · Large text 4.5:1
Use Tailwind semantic token pairs — they map to oklch values in src/client/index.css:
| Pair | Token classes | Notes |
|---|---|---|
| Body text | text-foreground bg-background | ~16:1 — passes ✔ |
| Primary action | bg-primary text-primary-foreground | passes ✔ |
| Destructive / error | bg-destructive text-destructive-foreground | passes ✔ |
| Secondary surface | bg-secondary text-secondary-foreground | passes ✔ |
| Muted text | text-muted-foreground | ⚠ Verify at your font size |
Use WebAIM Contrast Checker or APCA Calculator to verify
oklchvalues when adding new combinations.
Input borders, button outlines, checkbox frames, focus rings, and icon-only controls must have 3:1 contrast against adjacent colors. Use border-input / border-primary tokens and verify them in the contrast checker when customizing.
Use Tailwind's focus-visible: variant (keyboard only — does not appear on mouse click). Follow the pattern from src/client/components/ui/button.tsx:
focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none
Add focus-visible:scroll-mt-20 to prevent the focused element hiding behind a sticky header (WCAG 2.4.11 AA).
focus: alone for ring styles — it triggers on mouse too--ring token consistentSee focus-management.md for the sticky-header fix.
// Icon-only button — always provide sr-only label
<button aria-label="Close modal">
<XIcon aria-hidden="true" className="h-4 w-4" />
</button>
// Or use sr-only span (either approach is valid)
<button>
<XIcon aria-hidden="true" className="h-4 w-4" />
<span className="sr-only">Close modal</span>
</button>
// Reverse sr-only to make content visible again
<span className="not-sr-only">Visible text</span>
See forms-a11y.md for:
autocomplete attributes and WCAG 1.3.5 Identify Input Purpose (AA)fieldset/legend for grouped inputs (radio groups, checkboxes, date parts)See semantic-html.md for:
img alt text decision tree (informative vs decorative vs functional)alt="" + aria-hidden="true"role="img", <title>, <desc>, aria-labelledby<caption>, scope, headers attribute for complex tablesSee mobile-touch.md for:
pointerup, not pointerdown — WCAG 2.5.2See testing-a11y.md for:
@axe-core/playwright automated audits (recommended for CI)vitest-axe component-level unit testsUse this checklist for every new component or page before merge. Each item maps to a WCAG 2.2 success criterion.
<img> has meaningful alt; decorative images use alt="" and aria-hidden="true"autocomplete attribute valuesdocument.title that updates on route change<html lang="en"> (or appropriate BCP-47 language code)role="status" without moving focusThese exceed the required AA level. Implement where feasible to provide a superior experience.
| SC | Title | Implementation Guidance |
|---|---|---|
| 1.4.6 | Contrast Enhanced | Normal text 7:1 · Large text 4.5:1 |
| 2.3.3 | Animation from Interactions | Motion triggered by interaction can be disabled by the user — see reduced-motion.md |
| 2.4.12 | Focus Not Obscured (Enhanced) | Focused element not obscured at all — increase scroll-margin-top to fully clear sticky UI |
| 2.4.13 | Focus Appearance | Focus indicator ≥ 2px perimeter, 3:1 contrast between focused and unfocused states |
| 2.5.5 | Target Size Enhanced | Interactive targets ≥ 44×44 CSS pixels — use min-h-[44px] min-w-[44px] |
| 2.5.6 | Concurrent Input Mechanisms | Do not restrict the user to a single input modality (e.g., do not disable mouse when touch is detected) |
| 3.1.5 | Reading Level | If content exceeds lower secondary school reading level, provide supplemental simpler version |
| 3.3.9 | Accessible Auth Enhanced | No cognitive function test (including CAPTCHA with alternatives) in any auth step |
| Platform | Metadata | Shell commands | Packaging |
|---|---|---|---|
| Claude Code | YAML frontmatter in SKILL.md | ✅ Full !command`` support | n/a |
| Cowork | skills-rules.json (see skills-rules.json in this skill) | ✅ | .skill file via python -m scripts.package_skill skills/accessibility; use present_files to deliver packaged results |
| Claude.ai | Paste SKILL.md body into Project instructions; attach reference files as knowledge | ❌ No shell commands | n/a |
| Resource | URL |
|---|---|
| WCAG 2.2 Specification | https://www.w3.org/TR/WCAG22/ |
| WCAG 2.2 Quick Reference | https://www.w3.org/WAI/WCAG22/quickref/ |
| Understanding WCAG 2.2 | https://www.w3.org/WAI/WCAG22/Understanding/ |
| What's New in WCAG 2.2 | https://www.w3.org/WAI/standards-guidelines/wcag/new-in-22/ |
| ARIA Authoring Practices Guide (APG) | https://www.w3.org/WAI/ARIA/apg/ |
| WebAIM Contrast Checker | https://webaim.org/resources/contrastchecker/ |
| APCA Contrast Calculator | https://apcacontrast.com/ |
| axe DevTools Browser Extension | https://www.deque.com/axe/browser-extensions/ |
| WAVE Evaluation Tool | https://wave.webaim.org/ |
| NVDA Screen Reader (free, Windows) | https://www.nvaccess.org/ |
| Deque University — free courses | https://dequeuniversity.com/ |
| Inclusive Components — patterns | https://inclusive-components.design/ |