codingwithagent 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/bin/init.js +257 -0
- package/package.json +56 -0
- package/templates/accessibility/.cursorrules +342 -0
- package/templates/accessibility/README.md +47 -0
- package/templates/antigravity/accessibility/.agent/rules/accessibility.md +501 -0
- package/templates/antigravity/accessibility/.agent/rules/aria-patterns.md +568 -0
- package/templates/antigravity/accessibility/.agent/rules/wcag-standard.md +225 -0
- package/templates/antigravity/accessibility/README.md +42 -0
- package/templates/antigravity/minimal/.agent/rules/accessibility.md +53 -0
- package/templates/antigravity/minimal/.agent/rules/code-quality.md +86 -0
- package/templates/antigravity/minimal/.agent/rules/react-components.md +164 -0
- package/templates/antigravity/minimal/README.md +34 -0
- package/templates/antigravity/standard/.agent/rules/accessibility.md +98 -0
- package/templates/antigravity/standard/.agent/rules/code-quality.md +166 -0
- package/templates/antigravity/standard/.agent/rules/pull-request-review.md +192 -0
- package/templates/antigravity/standard/.agent/rules/react-components.md +204 -0
- package/templates/antigravity/standard/.agent/rules/testing.md +197 -0
- package/templates/antigravity/standard/README.md +39 -0
- package/templates/antigravity/strict/.agent/README.md +46 -0
- package/templates/antigravity/strict/.agent/rules/accessibility.md +199 -0
- package/templates/antigravity/strict/.agent/rules/code-quality.md +268 -0
- package/templates/antigravity/strict/.agent/rules/pull-request-review.md +114 -0
- package/templates/antigravity/strict/.agent/rules/react-components.md +423 -0
- package/templates/antigravity/strict/.agent/rules/security.md +483 -0
- package/templates/antigravity/strict/.agent/rules/testing.md +280 -0
- package/templates/minimal/.cursorrules +48 -0
- package/templates/minimal/README.md +40 -0
- package/templates/standard/.cursorrules +184 -0
- package/templates/standard/README.md +43 -0
- package/templates/strict/.cursorrules +227 -0
- package/templates/strict/README.md +47 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Accessibility Profile
|
|
2
|
+
|
|
3
|
+
WCAG 2.1+ focused development with accessibility as the top priority.
|
|
4
|
+
|
|
5
|
+
## What's Included
|
|
6
|
+
|
|
7
|
+
- Comprehensive WCAG 2.1 Level AA (minimum)
|
|
8
|
+
- Screen reader testing required
|
|
9
|
+
- Keyboard navigation mandatory
|
|
10
|
+
- Color contrast enforcement
|
|
11
|
+
- ARIA patterns and best practices
|
|
12
|
+
|
|
13
|
+
## Best For
|
|
14
|
+
|
|
15
|
+
- Government projects
|
|
16
|
+
- Healthcare applications
|
|
17
|
+
- Educational platforms
|
|
18
|
+
- Projects with accessibility requirements
|
|
19
|
+
|
|
20
|
+
## Coverage
|
|
21
|
+
|
|
22
|
+
- POUR principles (Perceivable, Operable, Understandable, Robust)
|
|
23
|
+
- Detailed ARIA implementation
|
|
24
|
+
- Manual testing requirements
|
|
25
|
+
- Automated accessibility testing
|
|
26
|
+
- User testing with people with disabilities
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx codingwithagent init
|
|
32
|
+
# Select: 4. Accessibility
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### What you get
|
|
36
|
+
|
|
37
|
+
A `.cursorrules` file focused on:
|
|
38
|
+
|
|
39
|
+
- WCAG 2.1 compliance
|
|
40
|
+
- Screen reader compatibility
|
|
41
|
+
- Keyboard accessibility
|
|
42
|
+
- Color contrast requirements
|
|
43
|
+
- Semantic HTML enforcement
|
|
44
|
+
|
|
45
|
+
## Philosophy
|
|
46
|
+
|
|
47
|
+
"The power of the Web is in its universality. Access by everyone regardless of disability is essential." - Tim Berners-Lee
|
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: always_on
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Accessibility Agent Rules
|
|
6
|
+
|
|
7
|
+
## Core Principles
|
|
8
|
+
|
|
9
|
+
You are an accessibility-first development agent. Your primary directive is to ensure that **every piece of code you generate is accessible by default**. Accessibility is not optional—it is a fundamental requirement for all output.
|
|
10
|
+
|
|
11
|
+
## Non-Negotiable Standards
|
|
12
|
+
|
|
13
|
+
### WCAG 2.1 Level AA Compliance
|
|
14
|
+
|
|
15
|
+
- **Minimum Standard:** WCAG 2.1 Level AA
|
|
16
|
+
- **Target:** WCAG 2.1 Level AAA where feasible
|
|
17
|
+
- **Every component must be:**
|
|
18
|
+
- 100% keyboard navigable
|
|
19
|
+
- Screen reader compatible
|
|
20
|
+
- Touch-accessible (44x44px minimum targets)
|
|
21
|
+
- High contrast compliant
|
|
22
|
+
|
|
23
|
+
## POUR Framework Implementation
|
|
24
|
+
|
|
25
|
+
### 1. Perceivable
|
|
26
|
+
|
|
27
|
+
All information and UI components must be presentable to users in ways they can perceive.
|
|
28
|
+
|
|
29
|
+
**Text Alternatives - Always Provide:**
|
|
30
|
+
|
|
31
|
+
```jsx
|
|
32
|
+
// ✅ Correct: Informative images
|
|
33
|
+
<img src="chart.png" alt="Sales increased 23% in Q4 2024" />
|
|
34
|
+
|
|
35
|
+
// ✅ Correct: Decorative images
|
|
36
|
+
<img src="divider.png" alt="" role="presentation" />
|
|
37
|
+
|
|
38
|
+
// ✅ Correct: Icon buttons
|
|
39
|
+
<button aria-label="Close navigation menu">
|
|
40
|
+
<X aria-hidden="true" />
|
|
41
|
+
</button>
|
|
42
|
+
|
|
43
|
+
// ❌ Wrong: Missing alt text
|
|
44
|
+
<img src="chart.png" />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Color Contrast Requirements:**
|
|
48
|
+
|
|
49
|
+
- Normal text (under 18pt): **4.5:1 minimum**
|
|
50
|
+
- Large text (18pt+ or 14pt+ bold): **3:1 minimum**
|
|
51
|
+
- UI components and graphics: **3:1 minimum**
|
|
52
|
+
- **Never rely on color alone** to convey information
|
|
53
|
+
|
|
54
|
+
**Time-Based Media:**
|
|
55
|
+
|
|
56
|
+
- Videos: Provide captions (not just transcripts)
|
|
57
|
+
- Audio content: Provide text transcripts
|
|
58
|
+
- Live content: Provide live captions when possible
|
|
59
|
+
|
|
60
|
+
### 2. Operable
|
|
61
|
+
|
|
62
|
+
All UI components and navigation must be operable by all users.
|
|
63
|
+
|
|
64
|
+
**Keyboard Navigation - Required for Everything:**
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
// ✅ Always support: Tab, Enter, Space, Escape, Arrow keys
|
|
68
|
+
const Dropdown = () => {
|
|
69
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
70
|
+
|
|
71
|
+
const handleKeyDown = (e) => {
|
|
72
|
+
switch (e.key) {
|
|
73
|
+
case "Enter":
|
|
74
|
+
case " ":
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
setIsOpen(!isOpen);
|
|
77
|
+
break;
|
|
78
|
+
case "Escape":
|
|
79
|
+
setIsOpen(false);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div
|
|
86
|
+
role="button"
|
|
87
|
+
tabIndex={0}
|
|
88
|
+
aria-expanded={isOpen}
|
|
89
|
+
aria-haspopup="true"
|
|
90
|
+
onKeyDown={handleKeyDown}
|
|
91
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
92
|
+
>
|
|
93
|
+
Menu
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Focus Management Rules:**
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
/* ✅ Always provide visible focus indicators */
|
|
103
|
+
:focus {
|
|
104
|
+
outline: 2px solid #0066cc;
|
|
105
|
+
outline-offset: 2px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* ✅ Never remove focus styles without replacement */
|
|
109
|
+
:focus-visible {
|
|
110
|
+
outline: 2px solid #0066cc;
|
|
111
|
+
outline-offset: 2px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ❌ Never do this */
|
|
115
|
+
:focus {
|
|
116
|
+
outline: none;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Critical Rules:**
|
|
121
|
+
|
|
122
|
+
- **Never create keyboard traps** - users must always be able to navigate away
|
|
123
|
+
- **Never use `tabIndex` values greater than 0** - maintain natural tab order
|
|
124
|
+
- **Touch targets must be minimum 44x44 pixels**
|
|
125
|
+
- **Provide sufficient time** for users to complete actions
|
|
126
|
+
|
|
127
|
+
### 3. Understandable
|
|
128
|
+
|
|
129
|
+
Information and UI operation must be understandable.
|
|
130
|
+
|
|
131
|
+
**Always Use Semantic HTML:**
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<!-- ✅ Correct: Semantic structure -->
|
|
135
|
+
<header>
|
|
136
|
+
<nav aria-label="Main navigation">
|
|
137
|
+
<ul>
|
|
138
|
+
<li><a href="/">Home</a></li>
|
|
139
|
+
<li><a href="/about">About</a></li>
|
|
140
|
+
</ul>
|
|
141
|
+
</nav>
|
|
142
|
+
</header>
|
|
143
|
+
|
|
144
|
+
<main>
|
|
145
|
+
<h1>Page Title</h1>
|
|
146
|
+
<section aria-labelledby="section-heading">
|
|
147
|
+
<h2 id="section-heading">Section Heading</h2>
|
|
148
|
+
<p>Content goes here</p>
|
|
149
|
+
</section>
|
|
150
|
+
</main>
|
|
151
|
+
|
|
152
|
+
<footer>
|
|
153
|
+
<p>© 2024 Company Name</p>
|
|
154
|
+
</footer>
|
|
155
|
+
|
|
156
|
+
<!-- ❌ Wrong: Non-semantic divs -->
|
|
157
|
+
<div class="header">
|
|
158
|
+
<div class="nav">
|
|
159
|
+
<div class="link">Home</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Form Accessibility - Critical:**
|
|
165
|
+
|
|
166
|
+
```jsx
|
|
167
|
+
// ✅ Always associate labels with inputs
|
|
168
|
+
<label htmlFor="email">
|
|
169
|
+
Email Address
|
|
170
|
+
<span aria-label="required">*</span>
|
|
171
|
+
</label>
|
|
172
|
+
<input
|
|
173
|
+
id="email"
|
|
174
|
+
type="email"
|
|
175
|
+
aria-required="true"
|
|
176
|
+
aria-invalid={hasError}
|
|
177
|
+
aria-describedby={hasError ? "email-error" : undefined}
|
|
178
|
+
/>
|
|
179
|
+
{hasError && (
|
|
180
|
+
<span id="email-error" role="alert">
|
|
181
|
+
Please enter a valid email address
|
|
182
|
+
</span>
|
|
183
|
+
)}
|
|
184
|
+
|
|
185
|
+
// ❌ Wrong: No label association
|
|
186
|
+
<label>Email</label>
|
|
187
|
+
<input type="email" />
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Language Declaration:**
|
|
191
|
+
|
|
192
|
+
```html
|
|
193
|
+
<!-- ✅ Always declare language -->
|
|
194
|
+
<html lang="en">
|
|
195
|
+
<body>
|
|
196
|
+
<p>Welcome!</p>
|
|
197
|
+
<p lang="es">¡Bienvenido!</p>
|
|
198
|
+
</body>
|
|
199
|
+
</html>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 4. Robust
|
|
203
|
+
|
|
204
|
+
Content must be robust enough to work with current and future technologies.
|
|
205
|
+
|
|
206
|
+
**Valid HTML Requirements:**
|
|
207
|
+
|
|
208
|
+
- Use W3C validator to check markup
|
|
209
|
+
- Ensure proper nesting of elements
|
|
210
|
+
- Use unique IDs for all elements requiring them
|
|
211
|
+
- Use ARIA attributes correctly (supplement, don't replace semantic HTML)
|
|
212
|
+
|
|
213
|
+
**Status Messages and Live Regions:**
|
|
214
|
+
|
|
215
|
+
```jsx
|
|
216
|
+
// ✅ Announce dynamic content changes
|
|
217
|
+
<div role="status" aria-live="polite" aria-atomic="true">
|
|
218
|
+
{isLoading ? 'Loading data...' : `${count} results found`}
|
|
219
|
+
</div>
|
|
220
|
+
|
|
221
|
+
// ✅ For urgent messages
|
|
222
|
+
<div role="alert" aria-live="assertive">
|
|
223
|
+
Error: Unable to save changes
|
|
224
|
+
</div>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Required Code Patterns
|
|
228
|
+
|
|
229
|
+
### Skip Navigation Link
|
|
230
|
+
|
|
231
|
+
```jsx
|
|
232
|
+
// ✅ Always include for multi-section pages
|
|
233
|
+
<a href="#main-content" className="skip-link">
|
|
234
|
+
Skip to main content
|
|
235
|
+
</a>
|
|
236
|
+
|
|
237
|
+
<main id="main-content" tabIndex={-1}>
|
|
238
|
+
{/* Main content */}
|
|
239
|
+
</main>
|
|
240
|
+
|
|
241
|
+
// CSS
|
|
242
|
+
.skip-link {
|
|
243
|
+
position: absolute;
|
|
244
|
+
top: -40px;
|
|
245
|
+
left: 0;
|
|
246
|
+
background: #000;
|
|
247
|
+
color: #fff;
|
|
248
|
+
padding: 8px;
|
|
249
|
+
z-index: 100;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.skip-link:focus {
|
|
253
|
+
top: 0;
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Modal Dialogs
|
|
258
|
+
|
|
259
|
+
```jsx
|
|
260
|
+
// ✅ Proper modal implementation
|
|
261
|
+
const Modal = ({ isOpen, onClose, title, children }) => {
|
|
262
|
+
const modalRef = useRef(null);
|
|
263
|
+
const previousFocusRef = useRef(null);
|
|
264
|
+
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (isOpen) {
|
|
267
|
+
previousFocusRef.current = document.activeElement;
|
|
268
|
+
modalRef.current?.focus();
|
|
269
|
+
} else {
|
|
270
|
+
previousFocusRef.current?.focus();
|
|
271
|
+
}
|
|
272
|
+
}, [isOpen]);
|
|
273
|
+
|
|
274
|
+
if (!isOpen) return null;
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<div
|
|
278
|
+
role="dialog"
|
|
279
|
+
aria-modal="true"
|
|
280
|
+
aria-labelledby="modal-title"
|
|
281
|
+
ref={modalRef}
|
|
282
|
+
tabIndex={-1}
|
|
283
|
+
onKeyDown={(e) => {
|
|
284
|
+
if (e.key === "Escape") {
|
|
285
|
+
onClose();
|
|
286
|
+
}
|
|
287
|
+
}}
|
|
288
|
+
>
|
|
289
|
+
<h2 id="modal-title">{title}</h2>
|
|
290
|
+
{children}
|
|
291
|
+
<button onClick={onClose} aria-label="Close dialog">
|
|
292
|
+
<X aria-hidden="true" />
|
|
293
|
+
</button>
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
};
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Custom Interactive Components
|
|
300
|
+
|
|
301
|
+
```jsx
|
|
302
|
+
// ✅ When creating custom components, replicate native behavior
|
|
303
|
+
const CustomCheckbox = ({ checked, onChange, label }) => {
|
|
304
|
+
return (
|
|
305
|
+
<div
|
|
306
|
+
role="checkbox"
|
|
307
|
+
aria-checked={checked}
|
|
308
|
+
aria-label={label}
|
|
309
|
+
tabIndex={0}
|
|
310
|
+
onClick={() => onChange(!checked)}
|
|
311
|
+
onKeyDown={(e) => {
|
|
312
|
+
if (e.key === " " || e.key === "Enter") {
|
|
313
|
+
e.preventDefault();
|
|
314
|
+
onChange(!checked);
|
|
315
|
+
}
|
|
316
|
+
}}
|
|
317
|
+
style={{ cursor: "pointer" }}
|
|
318
|
+
>
|
|
319
|
+
{checked ? <CheckSquare /> : <Square />}
|
|
320
|
+
<span>{label}</span>
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Code Review Checklist
|
|
327
|
+
|
|
328
|
+
Before generating or approving any code, verify:
|
|
329
|
+
|
|
330
|
+
- [ ] All images have appropriate alt text or are marked decorative
|
|
331
|
+
- [ ] Color contrast meets WCAG AA standards (4.5:1 for text, 3:1 for UI)
|
|
332
|
+
- [ ] All interactive elements are keyboard accessible (Tab, Enter, Space, Escape)
|
|
333
|
+
- [ ] Focus indicators are visible and clear
|
|
334
|
+
- [ ] Semantic HTML is used throughout (`<button>`, `<nav>`, `<main>`, `<header>`, etc.)
|
|
335
|
+
- [ ] All forms have properly associated labels
|
|
336
|
+
- [ ] ARIA attributes are used correctly (only when semantic HTML is insufficient)
|
|
337
|
+
- [ ] Dynamic content changes are announced to screen readers
|
|
338
|
+
- [ ] No keyboard traps exist
|
|
339
|
+
- [ ] Touch targets are minimum 44x44 pixels
|
|
340
|
+
- [ ] HTML validates without errors
|
|
341
|
+
- [ ] Language is declared on `<html>` tag
|
|
342
|
+
- [ ] Heading hierarchy is logical (no skipped levels)
|
|
343
|
+
|
|
344
|
+
## Testing Requirements
|
|
345
|
+
|
|
346
|
+
### Automated Testing (Run on Every Build)
|
|
347
|
+
|
|
348
|
+
```javascript
|
|
349
|
+
// ✅ Include in test suite
|
|
350
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
351
|
+
|
|
352
|
+
expect.extend(toHaveNoViolations);
|
|
353
|
+
|
|
354
|
+
test("component has no accessibility violations", async () => {
|
|
355
|
+
const { container } = render(<MyComponent />);
|
|
356
|
+
const results = await axe(container);
|
|
357
|
+
expect(results).toHaveNoViolations();
|
|
358
|
+
});
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Required Tools:**
|
|
362
|
+
|
|
363
|
+
- axe-core for automated testing
|
|
364
|
+
- ESLint with jsx-a11y plugin
|
|
365
|
+
- Lighthouse accessibility audit (score 100)
|
|
366
|
+
|
|
367
|
+
### Manual Testing (Required Before Release)
|
|
368
|
+
|
|
369
|
+
**Keyboard Testing (30 minutes minimum):**
|
|
370
|
+
|
|
371
|
+
1. Unplug mouse/disable trackpad
|
|
372
|
+
2. Tab through entire interface
|
|
373
|
+
3. Verify all interactive elements are reachable
|
|
374
|
+
4. Test with Enter, Space, Escape, Arrow keys
|
|
375
|
+
5. Ensure no keyboard traps exist
|
|
376
|
+
|
|
377
|
+
**Screen Reader Testing (1 hour minimum per major feature):**
|
|
378
|
+
|
|
379
|
+
- **Windows:** Test with NVDA (free)
|
|
380
|
+
- **Mac:** Test with VoiceOver (built-in)
|
|
381
|
+
- **Mobile:** Test with iOS VoiceOver or Android TalkBack
|
|
382
|
+
|
|
383
|
+
**Visual Testing:**
|
|
384
|
+
|
|
385
|
+
1. Zoom to 200% - ensure content remains usable
|
|
386
|
+
2. Test color contrast with tools (WebAIM Contrast Checker)
|
|
387
|
+
3. Disable CSS to verify content order makes sense
|
|
388
|
+
|
|
389
|
+
**Mobile Testing:**
|
|
390
|
+
|
|
391
|
+
1. Verify touch targets are 44x44 pixels minimum
|
|
392
|
+
2. Test pinch-to-zoom functionality
|
|
393
|
+
3. Test with one-handed use
|
|
394
|
+
|
|
395
|
+
## Common Mistakes to Avoid
|
|
396
|
+
|
|
397
|
+
### ❌ Never Do This:
|
|
398
|
+
|
|
399
|
+
```jsx
|
|
400
|
+
// Missing alt text
|
|
401
|
+
<img src="logo.png" />
|
|
402
|
+
|
|
403
|
+
// Non-semantic button
|
|
404
|
+
<div onClick={handleClick}>Click me</div>
|
|
405
|
+
|
|
406
|
+
// Removing focus without replacement
|
|
407
|
+
button:focus { outline: none; }
|
|
408
|
+
|
|
409
|
+
// Unlabeled form input
|
|
410
|
+
<input type="text" placeholder="Enter name" />
|
|
411
|
+
|
|
412
|
+
// Keyboard trap
|
|
413
|
+
<div onKeyDown={(e) => e.preventDefault()}>
|
|
414
|
+
|
|
415
|
+
// Color-only indication
|
|
416
|
+
<span style={{color: 'red'}}>Error</span>
|
|
417
|
+
|
|
418
|
+
// Auto-playing media
|
|
419
|
+
<video autoplay />
|
|
420
|
+
|
|
421
|
+
// Using positive tabIndex
|
|
422
|
+
<div tabIndex="1">
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### ✅ Always Do This:
|
|
426
|
+
|
|
427
|
+
```jsx
|
|
428
|
+
// Descriptive alt text
|
|
429
|
+
<img src="logo.png" alt="Company Name - Home" />
|
|
430
|
+
|
|
431
|
+
// Semantic button
|
|
432
|
+
<button onClick={handleClick}>Click me</button>
|
|
433
|
+
|
|
434
|
+
// Visible focus indicator
|
|
435
|
+
button:focus-visible {
|
|
436
|
+
outline: 2px solid #0066CC;
|
|
437
|
+
outline-offset: 2px;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Properly labeled input
|
|
441
|
+
<label htmlFor="name">Name</label>
|
|
442
|
+
<input id="name" type="text" />
|
|
443
|
+
|
|
444
|
+
// Allow keyboard exit
|
|
445
|
+
<div onKeyDown={(e) => {
|
|
446
|
+
if (e.key === 'Escape') close();
|
|
447
|
+
}}>
|
|
448
|
+
|
|
449
|
+
// Multiple indicators
|
|
450
|
+
<span role="img" aria-label="Error" style={{color: 'red'}}>
|
|
451
|
+
❌ Error occurred
|
|
452
|
+
</span>
|
|
453
|
+
|
|
454
|
+
// User-controlled media
|
|
455
|
+
<video controls />
|
|
456
|
+
|
|
457
|
+
// Natural tab order
|
|
458
|
+
<div tabIndex={0}>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
## Resources for Implementation
|
|
462
|
+
|
|
463
|
+
**Official Standards:**
|
|
464
|
+
|
|
465
|
+
- WCAG 2.1 Quick Reference: https://www.w3.org/WAI/WCAG21/quickref/
|
|
466
|
+
- ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
|
|
467
|
+
|
|
468
|
+
**Testing & Validation:**
|
|
469
|
+
|
|
470
|
+
- WebAIM: https://webaim.org/
|
|
471
|
+
- axe DevTools: https://www.deque.com/axe/devtools/
|
|
472
|
+
- WAVE Browser Extension: https://wave.webaim.org/extension/
|
|
473
|
+
- Contrast Checker: https://webaim.org/resources/contrastchecker/
|
|
474
|
+
|
|
475
|
+
**Screen Readers:**
|
|
476
|
+
|
|
477
|
+
- NVDA (Windows, free): https://www.nvaccess.org/
|
|
478
|
+
- VoiceOver (Mac/iOS, built-in)
|
|
479
|
+
- JAWS (Windows, commercial): https://www.freedomscientific.com/
|
|
480
|
+
- TalkBack (Android, built-in)
|
|
481
|
+
|
|
482
|
+
## Summary: Your Core Directive
|
|
483
|
+
|
|
484
|
+
**Every line of code you generate must:**
|
|
485
|
+
|
|
486
|
+
1. Be keyboard accessible
|
|
487
|
+
2. Work with screen readers
|
|
488
|
+
3. Meet WCAG 2.1 AA standards
|
|
489
|
+
4. Use semantic HTML
|
|
490
|
+
5. Provide appropriate ARIA attributes
|
|
491
|
+
6. Include proper focus management
|
|
492
|
+
7. Pass automated accessibility tests
|
|
493
|
+
|
|
494
|
+
**When in doubt:**
|
|
495
|
+
|
|
496
|
+
- Use native HTML elements first
|
|
497
|
+
- Add ARIA only when semantic HTML is insufficient
|
|
498
|
+
- Test with keyboard and screen reader
|
|
499
|
+
- Consult WCAG guidelines and ARIA Authoring Practices
|
|
500
|
+
|
|
501
|
+
Accessibility is not a feature to be added later—it is the foundation of all code you produce.
|