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 frontendThis skill uses the workspace's default tool permissions.
**Semantic HTML is the foundation. ARIA is the patch. Keyboard access is non-negotiable. If an element looks
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
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.