better-accessibility

Reviews and fixes UI code for keyboard, ARIA, form, and screen-reader accessibility.

2.7k|171|Updated Mar 28, 2026
One-click install
npx skills add https://github.com/compozy/compozy --skill better-accessibility
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: better-accessibility
Source: https://github.com/compozy/compozy/tree/main/.agents/skills/better-accessibility
Command: npx skills add https://github.com/compozy/compozy --skill better-accessibility

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

Interfaces often ship with invisible focus rings, unlabeled icon buttons, keyboard-inaccessible widgets, and forms that screen readers cannot announce, blocking users who rely on assistive technology. This Skill provides concrete principles, code patterns, and a structured review format for finding and fixing those accessibility defects in product UI code.

Core Features & Use Cases

  • Keyboard and Focus Engineering: Implements :focus-visible rings, skip links, roving tabindex, focus trapping with inert, and ARIA APG keyboard patterns for tabs, menus, dialogs, and comboboxes.
  • Semantics, ARIA, and Screen Readers: Enforces native-elements-first rules, accessible names, landmarks, live regions (role="status" / role="alert"), alt text by purpose, and correct SVG handling.
  • Forms, Hit Areas, and Motion: Covers labels, autocomplete tokens, error announcement with aria-invalid/aria-describedby, WCAG 2.5.8 target sizes with pseudo-element hit-area expansion, prefers-reduced-motion, and 200% zoom/reflow survival.
  • Use Case: When a user asks to "make this modal accessible" or reports that a menu is not keyboard navigable, the Skill walks the interface as a keyboard-only and screen-reader user, then outputs findings grouped by principle with severity, location, before/after code, and a Block/Needs changes/Approve verdict.

Quick Start

Review the dialog component in src/Dialog.tsx for accessibility issues and fix any keyboard, focus, and ARIA problems you find.

Frequently Asked Questions about better-accessibility

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I make a modal dialog keyboard accessible?

Use native `<dialog>` with `showModal()` for a free focus trap, inert background, and Escape handling. Otherwise add `role="dialog"`, `aria-modal="true"`, set `inert` on background content, focus the first focusable element on open, and return focus to the trigger on close.

How do I style focus rings without removing them for keyboard users?

Style `:focus-visible` instead of bare `:focus` so keyboard users get a ring while mouse clicks do not. Never use `outline: none` without a verified replacement, and check the full indicator against every adjacent color it crosses.

What is the difference between aria-disabled and the disabled attribute?

Native `disabled` removes the control from the tab order, blocks activation, and excludes it from form submission. `aria-disabled="true"` only announces the state, so you must block pointer, keyboard, and form behavior in code and style the state explicitly.

When should I use role="alert" versus role="status" for announcements?

Use `role="status"` (polite) for non-urgent updates like toasts, saved confirmations, and result counts. Reserve `role="alert"` (assertive) for urgent errors not tied to a control, since it interrupts whatever the screen reader is reading.

What is the minimum touch target size required by WCAG?

WCAG 2.5.8 Level AA requires a 24×24 CSS-pixel target or one of its spacing, equivalent-control, inline, or essential exceptions. For usability, aim for 44×44px on touch and 40×40px on desktop, extending small elements with a pseudo-element on the wrapper.

Why is a placeholder not an acceptable form label?

A placeholder disappears once the user types and usually fails contrast requirements, leaving the field unlabeled. Every input needs a programmatic `<label for>` or wrapping `<label>`, with placeholders used only as format examples alongside the label.