Help us improve
Share bugs, ideas, or general feedback.
From frontend
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.
npx claudepluginhub xobotyi/cc-foundry --plugin frontendHow this skill is triggered — by the user, by Claude, or both
Slash command
/frontend:accessibilityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Semantic HTML is the foundation. ARIA is the patch. Keyboard access is non-negotiable. If an element looks
Enforces WCAG AA and ARIA best practices for screen readers, keyboard navigation, and focus management. Use when building or auditing user-facing interfaces for accessibility compliance.
Implements WCAG 2.1/2.2 compliance, ARIA patterns, keyboard navigation, focus management, and accessibility testing for web components.
Audits and improves web accessibility following WCAG 2.2 guidelines, including POUR principles, alt text for images/icons, color contrast, and focus states. Use for a11y audits and compliance.
Share bugs, ideas, or general feedback.
Semantic HTML is the foundation. ARIA is the patch. Keyboard access is non-negotiable. If an element looks interactive, it must be interactive for everyone.
Target WCAG 2.2 AA conformance unless the project explicitly specifies otherwise. AA includes all A criteria.
semantic-html.md: Landmarks, headings,
images, tables, lists, language markuparia.md: Roles, states, properties, naming, live regions,
common mistakeskeyboard.md: Focus order, visibility, roving tabindex,
focus traps, restorationforms.md: Labels, grouping, required fields, validation,
autocompletecomponent-patterns.md: Dialog,
tabs, accordion, disclosure, menu, combobox, tooltipwcag.md: Full WCAG 2.2 AA criteria tables and compliance
checklistUse the right element for the right job. Native elements provide built-in keyboard support, screen reader announcements, and focus management that ARIA can only approximate.
<main>.<header>/<footer> map to banner/contentinfo only as direct children of <body> -- nested inside <article>,
<section>, etc. they lose their landmark role.<nav> elements with aria-label or aria-labelledby.<main role="main">, <nav role="navigation">).For the full landmark-to-role mapping table, see semantic-html.md.
<h1> per page identifying the primary content.<h1> then <h3> breaks the outline.<section> and major content area should begin with a heading.Use <button> for actions (submit, toggle, open dialog) -- activates via Enter and Space. Use <a href> for navigation
-- activates via Enter. Never <a href="#" onclick="..."> for actions. Never <button> for navigation.
<th> with scope="col" or scope="row" for headers.<caption> to describe the table's purpose.Use <ul> for unordered, <ol> for ordered, <dl>/<dt>/<dd> for term/description pairs. Screen readers announce
list type and item count.
<img> must have an alt attribute -- even if empty.background-image over <img alt="">.For alt treatment by image type, see semantic-html.md.
<html lang="..."> on every page (WCAG 3.1.1).<span lang="fr">bonjour</span> (WCAG 3.1.2).<abbr>.<title> on every page (WCAG 2.4.2).No ARIA is better than bad ARIA. ARIA modifies only the accessibility tree -- it does not change behavior, keyboard interaction, or appearance.
<h2 role="tab"> -- use
<div role="tab"><h2>...</h2></div>.role="button" must respond to Enter and Space.role="presentation" or aria-hidden="true" on focusable elements.Priority: aria-labelledby > aria-label > <label> > element content
title.
aria-label.aria-labelledby to compose names from multiple elements.aria-label and aria-labelledby replace native label text, not supplement.aria-label on elements with role="presentation" or role="none".aria-label on <div> without a role -- ignored by most AT.aria-describedby or aria-description for supplementary info after the name is established.aria-live="polite" for non-urgent updates.aria-live="assertive" sparingly -- only errors, alerts, urgent info.aria-live and content simultaneously may not be
announced.role="alert" container for reliable announcement.Place aria-expanded on the trigger element, not the panel.
For widget roles, state/relationship attribute tables, and common ARIA mistakes, see
aria.md.
All interactive functionality must be operable with a keyboard alone.
Tab/Shift+Tab between components. Arrow keys within composite widgets. Enter activates links, buttons, menu items. Space activates buttons, checkboxes, toggles. Escape closes overlays.
tabindex > 0. Rearrange DOM order instead.tabindex="0" makes non-interactive elements focusable (use sparingly).tabindex="-1" for programmatic focus only (dialog containers, skip targets).flex-direction: row-reverse, order, grid) must not
break this.outline: none without a custom focus style replacement.:focus-visible for keyboard-only focus styles.Use roving tabindex for composite widgets (tabs, toolbars, menus): active child gets tabindex="0", others get
tabindex="-1". Use aria-activedescendant when the container must maintain focus (combobox).
aria-modal="true".document.body.disabled attribute or tabindex="-1").aria-disabled="true" to keep element focusable but not operable.Every <input>, <select>, <textarea> must have a programmatic label.
Priority: <label for/id> > wrapping <label> > aria-labelledby > aria-label.
placeholder is not a label substitute -- disappears on input, unreliable in screen readers.<fieldset> + <legend>. Required for: radio groups, checkbox groups, related input sets
(address, date parts).role="group" with aria-labelledby when <fieldset> is impractical.required attribute or aria-required="true".aria-describedby or aria-errormessage.aria-invalid="true" on invalid fields.role="alert" on error container for immediate announcement.role="status".Use semantic type attributes (email, tel, url, number, password). Use autocomplete for user data inputs
(WCAG 1.3.5): given-name, family-name, email, tel, street-address, etc.
disabled attribute removes from tab sequence and announces state.aria-disabled="true" keeps element focusable -- prevent activation in JS.For full ARIA structure, keyboard contracts, and code examples for each pattern, see
component-patterns.md. Key rules:
<dialog> with .showModal() when possible. Focus trap, Escape to close, return focus to
trigger on close.role="tablist/tab/tabpanel", roving tabindex, arrow keys switch tabs, Tab enters active panel.<button> inside a heading, aria-expanded on button, aria-controls to panel.<button> with aria-expanded and aria-controls.aria-haspopup="true", arrows navigate, Enter activates. Never role="menu" for navigation -- use
<nav> with links.aria-activedescendant tracks highlighted option, arrows navigate, Enter selects, Escape closes.aria-describedby, must be hoverable and persistent. No interactive content
inside.role="alert" for urgent (assertive), role="status" for non-urgent (polite). Inject into
pre-existing container.For WCAG 2.2 AA compliance checklist with criterion numbers, see wcag.md.
When writing accessible code:
When reviewing code for accessibility:
The coding skill governs workflow; this skill governs accessibility choices. For CSS-related accessibility (contrast, focus styles, motion), the css skill complements this one.