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