SKILL.md

  1---
  2name: frontend-accessibility
  3description: Generates accessible HTML, React, and frontend code following WCAG 2.2 AA guidelines. Use when creating UI components, forms, navigation, or any user-facing frontend code. Focuses on semantic HTML, keyboard accessibility, and screen reader compatibility.
  4user-invocable: true
  5license: LicenseRef-MutuaL-1.2
  6metadata:
  7  author: Amolith <amolith@secluded.site>
  8---
  9
 10Write accessible frontend code by default. Semantic HTML covers most needs; ARIA is for gaps HTML can't fill.
 11
 12## Core principles
 13
 141. **Semantic HTML first**: Use `<button>`, `<nav>`, `<main>`, `<form>` - not divs with roles
 152. **Keyboard accessible**: Everything clickable must be focusable and operable with Enter/Space
 163. **Screen reader context**: Labels, alt text, and heading hierarchy convey structure without vision
 174. **No ARIA is better than bad ARIA**: ARIA overrides native semantics and can make things *worse*
 18
 19## Quick reference
 20
 21### Images
 22```html
 23<!-- Informative: describe content -->
 24<img src="chart.png" alt="Sales increased 25% from Q1 to Q2">
 25
 26<!-- Decorative: empty alt -->
 27<img src="divider.png" alt="">
 28
 29<!-- Complex: summarize + link to details -->
 30<img src="flowchart.png" alt="User registration flow. Details in following section.">
 31```
 32
 33### Interactive elements
 34```html
 35<!-- Correct: semantic button -->
 36<button onclick="save()">Save</button>
 37
 38<!-- Wrong: div cosplaying as button -->
 39<div onclick="save()" role="button" tabindex="0">Save</div>
 40```
 41The div requires `role`, `tabindex`, `onkeydown` for Enter/Space, focus styles, and still won't work with voice control. Use `<button>`.
 42
 43### Forms
 44```html
 45<label for="email">Email address</label>
 46<input type="email" id="email" name="email" required aria-describedby="email-hint">
 47<span id="email-hint">We'll never share your email</span>
 48```
 49Every input needs a visible `<label>` with matching `for`/`id`. Use `aria-describedby` for hints, `aria-invalid` for errors.
 50
 51### Headings
 52```html
 53<h1>Page title</h1>           <!-- One per page -->
 54  <h2>Section</h2>            <!-- Don't skip levels -->
 55    <h3>Subsection</h3>
 56  <h2>Another section</h2>
 57```
 58Headings create navigable structure. Screen reader users jump by heading level.
 59
 60### Links
 61```html
 62<!-- Good: describes destination -->
 63<a href="/pricing">View pricing plans</a>
 64
 65<!-- Bad: meaningless out of context -->
 66<a href="/pricing">Click here</a>
 67```
 68
 69## When to use ARIA
 70
 71Use ARIA only when HTML has no semantic equivalent:
 72
 73| Need | Solution |
 74|------|----------|
 75| Button | `<button>` not `role="button"` |
 76| Navigation | `<nav>` not `role="navigation"` |
 77| Live updates | `aria-live="polite"` (no HTML equivalent) |
 78| Current page | `aria-current="page"` (no HTML equivalent) |
 79| Expanded state | `aria-expanded="true"` (no HTML equivalent) |
 80| Custom widget | ARIA + keyboard handling (last resort) |
 81
 82## Common violations to avoid
 83
 84See [antipatterns.md](references/antipatterns.md) for detailed examples.
 85
 861. **Missing form labels** - Every input needs `<label for="...">`
 872. **Empty alt on informative images** - `alt=""` marks image as decorative
 883. **Div/span as buttons** - Use `<button>`, not `<div onclick>`
 894. **Missing skip link** - Add "Skip to main content" for keyboard users
 905. **Low color contrast** - 4.5:1 for normal text, 3:1 for large text
 916. **Keyboard traps** - Focus must be able to leave modals/menus
 927. **Missing focus indicators** - Never `outline: none` without replacement
 93
 94## Motion and animation
 95
 96Respect user preferences for reduced motion:
 97
 98```css
 99/* Default: full animation */
100.animated {
101  transition: transform 0.3s ease;
102}
103
104/* Reduce or remove for users who prefer it */
105@media (prefers-reduced-motion: reduce) {
106  .animated {
107    transition: none;
108  }
109}
110```
111
112Or start safe and enhance:
113```css
114/* Safe default */
115.animated {
116  transition: none;
117}
118
119/* Only animate if user hasn't requested reduced motion */
120@media (prefers-reduced-motion: no-preference) {
121  .animated {
122    transition: transform 0.3s ease;
123  }
124}
125```
126
127Applies to: transitions, transforms, parallax, auto-playing video, animated illustrations. Essential for users with vestibular disorders.
128
129## Framework-specific notes
130
131### React/JSX
132- `htmlFor` instead of `for`
133- `className` instead of `class`
134- Fragments (`<>`) don't affect accessibility tree
135- Manage focus with refs when content changes dynamically
136
137### Component libraries
138If using Radix, Headless UI, or similar - they handle ARIA. Don't add redundant attributes.
139
140## Validation
141
142Generated code should pass:
143- **axe-core**: Catches ~57% of WCAG issues automatically
144- **Manual keyboard test**: Tab through everything, operate with Enter/Space
145- **Screen reader spot check**: VoiceOver (Mac), NVDA (Windows), Orca (Linux)
146
147Automated tools miss context-dependent issues (alt text quality, heading hierarchy logic, reading order). Human review still required.
148
149## Detailed patterns
150
151See [patterns.md](references/patterns.md) for:
152- Modal dialogs and focus management
153- Custom select/combobox
154- Tabs and tab panels
155- Accordions
156- Toast notifications
157- Data tables