skills/accessibility-standard/SKILL.md
Comprehensive web accessibility standards based on WCAG 2.2 AA, with anti-patterns, legal enforcement context (EAA, ADA Title II), WAI-ARIA patterns, and framework-specific fixes for modern web frameworks and libraries.
npx skillsauth add ngmthaq/my-copilot accessibility-standardInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Severity levels: CRITICAL (block merge) · IMPORTANT (fix this sprint) · SUGGESTION (future iteration)
Legal context: EAA enforced June 2025 (EU, fines up to €3M). ADA Title II digital rule effective April 2026 (US gov). WCAG 2.2 AA is a superset of all current legal requirements.
Five ARIA Rules: (1) Prefer native HTML. (2) Don't override native semantics. (3) ARIA controls must be keyboard operable. (4) Never aria-hidden="true" on focusable elements. (5) All interactive elements need an accessible name.
| ID | Severity | Pattern | Fix |
| --- | --------- | ------------------------------------- | ------------------------------------------------------ |
| S1 | CRITICAL | <html> missing lang= | <html lang="en"> |
| S3 | IMPORTANT | Heading level gaps (h1→h3) | Maintain h1>h2>h3 nesting; style with CSS |
| S4 | IMPORTANT | No landmark elements (div soup) | Use <header>, <nav>, <main>, <footer> |
| S6 | CRITICAL | Data table without <th> | Add <thead>, <th scope="col">, <caption> |
| S7 | IMPORTANT | "Click here" / "Read more" links | Use descriptive link text |
| S8 | CRITICAL | <div onClick> instead of <button> | Use native <button> — built-in focus, role, keyboard |
| ID | Severity | Pattern | Fix |
| --- | --------- | ----------------------------------------- | ----------------------------------------------------------------------------------- |
| A2 | CRITICAL | aria-hidden="true" on focusable element | Use disabled, remove href/tabindex, or use inert |
| A3 | CRITICAL | Role missing required props | tab→aria-selected; slider→aria-valuemin/max/now; combobox→aria-expanded |
| A5 | IMPORTANT | role="checkbox" on <div> | Use <input type="checkbox"> — native handles state/keyboard |
| A6 | CRITICAL | Icon-only button with no label | <button aria-label="Close"><svg aria-hidden="true"> |
| A8 | IMPORTANT | Toast/notification with no live region | <div role="status" aria-live="polite"> (errors: role="alert") |
| ID | Severity | Pattern | Fix |
| --- | --------- | --------------------------------------------- | --------------------------------------------------------------------------------- |
| K1 | CRITICAL | onClick on <div> without keyboard handler | Use <button>, or add role="button" tabIndex={0} + Enter/Space handlers |
| K2 | CRITICAL | tabindex="2" (positive value) | Only use 0 (tab order) or -1 (programmatic focus) |
| K3 | CRITICAL | Modal without focus trap or Escape | Use native <dialog showModal()> — traps focus, handles Escape, restores trigger |
| K4 | IMPORTANT | No skip link | <a href="#main">Skip to main content</a> as first focusable element |
| K5 | CRITICAL | outline: none with no replacement | button:focus-visible { outline: 2px solid #005fcc; outline-offset: 2px; } |
| K6 | IMPORTANT | onMouseOver without keyboard equivalent | Pair with onFocus/onBlur |
| K7 | IMPORTANT | Focus not restored after modal close | Store trigger ref; call triggerRef.current.focus() on close |
| ID | Severity | Pattern | Fix |
| --- | --------- | ------------------------------------------- | ------------------------------------------------------------------------ |
| F1 | CRITICAL | <input> without associated label | <label for="x"> + <input id="x">, or aria-label |
| F2 | CRITICAL | Error message not linked to input | <input aria-describedby="err" aria-invalid="true"> + <span id="err"> |
| F3 | IMPORTANT | Required field by color/* only | Add HTML required attr; <span aria-hidden="true">*</span> + note |
| F5 | IMPORTANT | Puzzle CAPTCHA / paste blocked on passwords | Use reCAPTCHA v3 or hCaptcha; never block paste/autofill (WCAG 3.3.8) |
| F6 | IMPORTANT | Placeholder used as label | Always pair placeholder with a visible <label> |
| ID | Severity | Pattern | Fix |
| --- | --------- | ------------------------------------------------ | ----------------------------------------------------------------- |
| V1 | CRITICAL | Text contrast below 4.5:1 (normal) / 3:1 (large) | Use contrast checker; #595959 on #fff = 7:1 ✓ |
| V2 | CRITICAL | Error/success state by color alone | Add icon, text label, or border as secondary indicator |
| V3 | IMPORTANT | font-size: 14px on content text | Use rem/em so text scales with user preferences |
| D1 | CRITICAL | <img> without alt= | Descriptive alt for informational images; alt="" for decorative |
| D3 | CRITICAL | <video> without captions | <track kind="captions" src="en.vtt" default> |
React/Next.js: Use htmlFor (not for) on labels. After SPA route change, ensure page has unique <title> (Next.js v13+ announces it automatically). Restore focus after conditional renders with useRef + useEffect.
Angular: Use <button> over (click) on divs. Use cdkTrapFocus for custom modals (or prefer CDK Dialog). Announce route changes via LiveAnnouncer. Bind [attr.aria-invalid] and [attr.aria-describedby] to form control state.
Vue: Use <button> over @click on divs. After v-if toggles, restore focus with nextTick. Sanitize and validate v-html content for heading hierarchy and alt text.
| Key | Behavior | | ---------------- | ----------------------------------- | | Tab / Shift+Tab | Next / previous focusable element | | Enter | Activate button or link | | Space | Activate button, toggle checkbox | | Escape | Close modal, dialog, dropdown | | Arrow Up/Down | Navigate menu, listbox, radio group | | Arrow Left/Right | Navigate tabs, slider, radio group | | Home / End | First / last item in list or menu |
Perceivable
alt="" for decorative)header, nav, main, footer)<html lang="..."> set correctlyOperable
prefers-reduced-motionUnderstandable
aria-labelaria-describedbyrequired or aria-requiredRobust
aria-hidden="true" on focusable elementsdocumentation
Guidelines and protocols for Technical Leaders to manage and oversee technical projects effectively while adhering to the core mandate of being the central orchestration layer for all engineering work.
data-ai
Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database performance analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Provides execution plan analysis, pagination optimization, batch operations, and performance monitoring guidance.
development
SOLID — Enforces the SOLID principle of object-oriented design (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion) for maintainable and scalable code.
development
Separation of Concerns (SoC) — Enforces the Separation of Concerns principle by ensuring each module, layer, and component addresses exactly one well-defined concern. Use when writing, reviewing, or refactoring code that mixes UI with business logic, business logic with data access, presentation with formatting, or cross-cutting concerns (auth, logging, validation) with core logic.