agentsclimarketplace

A11y gate

Skill jcdavis131/cursor-agent-skills/skills/a11y-gate

42 agent-discipline skills for Cursor, distilled by watching an autonomous terminal coding agent (Claude Code + Fable 5). Includes the derivation method.

Install
npx -y skills add jcdavis131/cursor-agent-skills --skill a11y-gate

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 26 days oldThe repository was created 26 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 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

Statically verify new UI primitives for accessibility — animations gated behind prefers-reduced-motion, keyboard accessible, ARIA present — before declaring the primitive done. Use when authoring or modifying a UI primitive (component, page section, interactive widget), especially interactive/animated ones. Pairs well as a fill-the-wait task while builds run.

SKILL.md

4.2 KB, as published. Nobody here has run it

A11y Gate

New UI primitives can ship with unguarded animations, missing keyboard support, or absent ARIA. A static a11y check on each new primitive catches these before they ship. It's cheap, and it's a perfect fill-the-wait task while builds run.

The three checks

For every new UI primitive, statically verify:

1. Animations gated behind prefers-reduced-motion

Any animation (transitions, keyframes, motion components) must respect the user's reduced-motion preference:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Or, with a motion library, gate the animation on a reduced-motion check. An ungated animation is a vestibular issue for some users — not a cosmetic nicety.

2. Keyboard accessible

Every interactive element is reachable and operable by keyboard:

  • Focusable elements have a visible focus indicator.
  • Interactive widgets (menus, dialogs, tabs, feeds) have arrow-key + enter/space + escape handling.
  • No keyboard traps (focus must be able to leave the widget).
  • Tab order is logical (DOM order, or tabindex only when necessary).

3. ARIA present and correct

  • Interactive widgets have the right ARIA role (role="dialog", role="tablist", etc.).
  • State is exposed (aria-expanded, aria-selected, aria-busy).
  • Labels are present (aria-label, aria-labelledby, or visible label associated).
  • Don't over-ARIA — if a native element conveys the semantics, use the native element and skip the ARIA.

How to run it

A static check (no full screen-reader run) — read the primitive's JSX/CSS and confirm the three things:

a11y gate — <Primitive>:
  [x] animations gated (prefers-reduced-motion)
  [x] keyboard: focusable + visible focus + no traps + arrow/enter/esc on widgets
  [x] ARIA: roles + state + labels, no over-ARIA

Report the result as a one-line verdict. If any check fails, fix before marking the primitive done.

When to run

  • After authoring a new UI primitive (component, page section, widget).
  • After modifying an interactive or animated primitive.
  • As a fill-the-wait task while builds run — it's static, no network, no build dependency.

When NOT to run

  • Pure static/display primitives with no interaction or animation — the three checks are vacuous.
  • A primitive already covered by an automated a11y test in the suite — let the suite handle it.

Dynamic feeds use aria-live

A feed or list that updates over time (a race log, a run feed, a live event stream) needs aria-live so screen readers announce updates:

<ol className="bh-feed" aria-live="polite" aria-label="Race log feed">
  • aria-live="polite" — announce updates without interrupting the user (use assertive only for urgent alerts).
  • aria-label — name the feed so the announcement is contextualized ("Race log feed: entry 42…").
  • A feed without aria-live is silent to screen-reader users even though it's visually updating — the dynamic content is invisible to them.

Anti-patterns

  • "We'll do an a11y pass later." Later never comes; the primitive ships unguarded.
  • Ungated animations "because they're subtle". Subtle to you is not subtle to a vestibular user.
  • Over-ARIA. Adding role="button" to a <button> is noise; use the native element.
  • Keyboard support added "in a follow-up". A widget that's mouse-only on ship is a regression.
  • No visible focus indicator. Keyboard users can't see where they are.

Pair with

  • validate-gate — the a11y gate is the frontend-specific gate alongside typecheck/lint.
  • fill-the-wait — run the a11y gate while builds run; it's static and independent.
  • use-design-system — shared primitives must clear the a11y gate once, then every consumer inherits it.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.