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.
Files changed (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/bin/init.js +257 -0
  4. package/package.json +56 -0
  5. package/templates/accessibility/.cursorrules +342 -0
  6. package/templates/accessibility/README.md +47 -0
  7. package/templates/antigravity/accessibility/.agent/rules/accessibility.md +501 -0
  8. package/templates/antigravity/accessibility/.agent/rules/aria-patterns.md +568 -0
  9. package/templates/antigravity/accessibility/.agent/rules/wcag-standard.md +225 -0
  10. package/templates/antigravity/accessibility/README.md +42 -0
  11. package/templates/antigravity/minimal/.agent/rules/accessibility.md +53 -0
  12. package/templates/antigravity/minimal/.agent/rules/code-quality.md +86 -0
  13. package/templates/antigravity/minimal/.agent/rules/react-components.md +164 -0
  14. package/templates/antigravity/minimal/README.md +34 -0
  15. package/templates/antigravity/standard/.agent/rules/accessibility.md +98 -0
  16. package/templates/antigravity/standard/.agent/rules/code-quality.md +166 -0
  17. package/templates/antigravity/standard/.agent/rules/pull-request-review.md +192 -0
  18. package/templates/antigravity/standard/.agent/rules/react-components.md +204 -0
  19. package/templates/antigravity/standard/.agent/rules/testing.md +197 -0
  20. package/templates/antigravity/standard/README.md +39 -0
  21. package/templates/antigravity/strict/.agent/README.md +46 -0
  22. package/templates/antigravity/strict/.agent/rules/accessibility.md +199 -0
  23. package/templates/antigravity/strict/.agent/rules/code-quality.md +268 -0
  24. package/templates/antigravity/strict/.agent/rules/pull-request-review.md +114 -0
  25. package/templates/antigravity/strict/.agent/rules/react-components.md +423 -0
  26. package/templates/antigravity/strict/.agent/rules/security.md +483 -0
  27. package/templates/antigravity/strict/.agent/rules/testing.md +280 -0
  28. package/templates/minimal/.cursorrules +48 -0
  29. package/templates/minimal/README.md +40 -0
  30. package/templates/standard/.cursorrules +184 -0
  31. package/templates/standard/README.md +43 -0
  32. package/templates/strict/.cursorrules +227 -0
  33. package/templates/strict/README.md +47 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Nitish Kafle
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # ๐Ÿค– Agentic Code Standards
2
+
3
+ **Production-ready coding standards and best practices for AI coding agents**
4
+
5
+ Stop fighting with inconsistent AI code output. Get enterprise-grade standards that work across **all major AI coding tools** โ€” Cursor, Windsurf, Google Antigravity, GitHub Copilot, Cline, and more.
6
+
7
+ ## ๐ŸŽฏ What You Get
8
+
9
+ - โ™ฟ **Accessibility-First**: WCAG 2.1 AA+ compliance built-in
10
+ - โš›๏ธ **Modern Stack**: React, TypeScript, Node.js, Python best practices
11
+ - ๐Ÿงช **Testing Ready**: Unit, integration, E2E testing standards
12
+ - ๐Ÿ”’ **Security**: OpenSSF-aligned secure coding practices
13
+ - ๐Ÿ“Š **Code Quality**: Maintainable, scalable patterns from day one
14
+ - ๐ŸŒ **Universal**: One standard, every AI coding agent
15
+
16
+ ## ๐Ÿš€ Quick Start
17
+
18
+ # Using npx (no installation needed!)
19
+
20
+ ```bash
21
+ npx codingwithagent init
22
+ ```
23
+
24
+ # Or install globally
25
+
26
+ ```
27
+ npm i -g codingwithagent
28
+ codingwithagent init
29
+ ```
30
+
31
+ ## Choose your setup:
32
+
33
+ - Minimal (essential rules only)
34
+ - Standard (recommended baseline) โญ
35
+ - Strict (all rules enforced)
36
+ - Accessibility-focused
37
+ - Custom (pick and choose)
package/bin/init.js ADDED
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Agentic Code Standards CLI
5
+ * Interactive installer for AI coding agent standards
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const readline = require('readline');
11
+
12
+ const rl = readline.createInterface({
13
+ input: process.stdin,
14
+ output: process.stdout
15
+ });
16
+
17
+ // ANSI colors
18
+ const colors = {
19
+ reset: '\x1b[0m',
20
+ bright: '\x1b[1m',
21
+ cyan: '\x1b[36m',
22
+ green: '\x1b[32m',
23
+ yellow: '\x1b[33m',
24
+ blue: '\x1b[34m',
25
+ red: '\x1b[31m'
26
+ };
27
+
28
+ function log(message, color = 'reset') {
29
+ console.log(`${colors[color]}${message}${colors.reset}`);
30
+ }
31
+
32
+ function header() {
33
+ console.log('');
34
+ log('๐Ÿค– Agentic Code Standards', 'cyan');
35
+ log('โ”'.repeat(60), 'cyan');
36
+ log('Production-ready standards for AI coding agents', 'bright');
37
+ console.log('');
38
+ }
39
+
40
+ function detectAITool() {
41
+ const cwd = process.cwd();
42
+
43
+ if (fs.existsSync(path.join(cwd, '.cursorrules'))) return 'cursor';
44
+ if (fs.existsSync(path.join(cwd, '.windsurfrules'))) return 'windsurf';
45
+ if (fs.existsSync(path.join(cwd, '.agent'))) return 'antigravity';
46
+ if (fs.existsSync(path.join(cwd, '.github', 'copilot-instructions.md'))) return 'copilot';
47
+
48
+ return null;
49
+ }
50
+
51
+ function question(prompt) {
52
+ return new Promise((resolve) => {
53
+ rl.question(`${colors.bright}${prompt}${colors.reset} `, resolve);
54
+ });
55
+ }
56
+
57
+ async function selectProfile() {
58
+ console.log('');
59
+ log('๐Ÿ“‹ Choose your profile:', 'blue');
60
+ console.log('');
61
+ log(' 1. Minimal Essential rules only (great for getting started)');
62
+ log(' 2. Standard Recommended baseline โญ (most popular)');
63
+ log(' 3. Strict All rules enforced (maximum code quality)');
64
+ log(' 4. Accessibility WCAG 2.1+ focused (a11y priority)');
65
+ console.log('');
66
+
67
+ const answer = await question('Enter number (1-4) [default: 2]:');
68
+ const choice = answer.trim() || '2';
69
+
70
+ const profiles = {
71
+ '1': 'minimal',
72
+ '2': 'standard',
73
+ '3': 'strict',
74
+ '4': 'accessibility'
75
+ };
76
+
77
+ return profiles[choice] || 'standard';
78
+ }
79
+
80
+ async function selectTool() {
81
+ const detected = detectAITool();
82
+
83
+ if (detected) {
84
+ console.log('');
85
+ log(`โœ… Detected: ${detected.charAt(0).toUpperCase() + detected.slice(1)}`, 'green');
86
+ const answer = await question(`Continue with ${detected}? (Y/n):`);
87
+ if (!answer.trim() || answer.toLowerCase() === 'y') {
88
+ return detected;
89
+ }
90
+ }
91
+
92
+ console.log('');
93
+ log('๐Ÿ› ๏ธ Select your AI coding tool:', 'blue');
94
+ console.log('');
95
+ log(' 1. Cursor (.cursorrules)');
96
+ log(' 2. Windsurf (.windsurfrules)');
97
+ log(' 3. Antigravity (.agent/rules/)');
98
+ log(' 4. GitHub Copilot (.github/copilot-instructions.md)');
99
+ log(' 5. Universal Works with most tools โญ');
100
+ console.log('');
101
+
102
+ const answer = await question('Enter number (1-5) [default: 5]:');
103
+ const choice = answer.trim() || '5';
104
+
105
+ const tools = {
106
+ '1': 'cursor',
107
+ '2': 'windsurf',
108
+ '3': 'antigravity',
109
+ '4': 'copilot',
110
+ '5': 'universal'
111
+ };
112
+
113
+ return tools[choice] || 'universal';
114
+ }
115
+
116
+ function copyTemplate(profile, tool) {
117
+ const templatesDir = path.join(__dirname, '..', 'templates');
118
+ const cwd = process.cwd();
119
+
120
+ try {
121
+ if (tool === 'antigravity') {
122
+ // Copy Antigravity .agent/rules/ structure
123
+ const sourceDir = path.join(templatesDir, 'antigravity', profile, '.agent', 'rules');
124
+ const targetDir = path.join(cwd, '.agent', 'rules');
125
+
126
+ if (!fs.existsSync(targetDir)) {
127
+ fs.mkdirSync(targetDir, { recursive: true });
128
+ }
129
+
130
+ const files = fs.readdirSync(sourceDir);
131
+ files.forEach(file => {
132
+ fs.copyFileSync(
133
+ path.join(sourceDir, file),
134
+ path.join(targetDir, file)
135
+ );
136
+ });
137
+
138
+ console.log('');
139
+ log(`โœจ Created .agent/rules/ with ${profile} profile`, 'green');
140
+ log(` Files: ${files.join(', ')}`, 'cyan');
141
+
142
+ } else if (tool === 'copilot') {
143
+ const sourceFile = path.join(templatesDir, profile, '.cursorrules');
144
+ const targetDir = path.join(cwd, '.github');
145
+ const targetFile = path.join(targetDir, 'copilot-instructions.md');
146
+
147
+ if (!fs.existsSync(targetDir)) {
148
+ fs.mkdirSync(targetDir, { recursive: true });
149
+ }
150
+
151
+ fs.copyFileSync(sourceFile, targetFile);
152
+
153
+ console.log('');
154
+ log(`โœจ Created .github/copilot-instructions.md with ${profile} profile`, 'green');
155
+
156
+ } else {
157
+ const sourceFile = path.join(templatesDir, profile, '.cursorrules');
158
+ let targetFile;
159
+
160
+ if (tool === 'windsurf') {
161
+ targetFile = path.join(cwd, '.windsurfrules');
162
+ } else {
163
+ targetFile = path.join(cwd, '.cursorrules');
164
+ }
165
+
166
+ fs.copyFileSync(sourceFile, targetFile);
167
+
168
+ console.log('');
169
+ log(`โœจ Created ${path.basename(targetFile)} with ${profile} profile`, 'green');
170
+ }
171
+
172
+ return true;
173
+ } catch (error) {
174
+ console.log('');
175
+ log(`โŒ Error: ${error.message}`, 'red');
176
+ return false;
177
+ }
178
+ }
179
+
180
+ function showNextSteps(tool, profile) {
181
+ console.log('');
182
+ log('๐ŸŽ‰ Setup complete!', 'green');
183
+ console.log('');
184
+ log('Next steps:', 'bright');
185
+ log(' 1. Review your rules file(s)');
186
+ log(' 2. Customize for your project needs');
187
+ log(' 3. Start coding with your AI agent!');
188
+ console.log('');
189
+
190
+ log('๐Ÿ“š Documentation:', 'blue');
191
+ log(' https://github.com/netshdev/codingwithagent');
192
+ console.log('');
193
+
194
+ if (tool === 'antigravity') {
195
+ log('๐Ÿ’ก Tip: Antigravity auto-loads rules from .agent/rules/', 'yellow');
196
+ } else if (tool === 'copilot') {
197
+ log('๐Ÿ’ก Tip: Copilot reads instructions from .github/copilot-instructions.md', 'yellow');
198
+ } else {
199
+ log('๐Ÿ’ก Tip: Your AI agent will automatically use these rules', 'yellow');
200
+ }
201
+
202
+ console.log('');
203
+ log('โญ Star us on GitHub if this helped!', 'cyan');
204
+ console.log('');
205
+ }
206
+
207
+ async function main() {
208
+ try {
209
+ header();
210
+
211
+ const profile = await selectProfile();
212
+ const tool = await selectTool();
213
+
214
+ console.log('');
215
+ log('โš™๏ธ Installing...', 'cyan');
216
+
217
+ const success = copyTemplate(profile, tool);
218
+
219
+ if (success) {
220
+ showNextSteps(tool, profile);
221
+ }
222
+
223
+ rl.close();
224
+ process.exit(success ? 0 : 1);
225
+
226
+ } catch (error) {
227
+ console.log('');
228
+ log(`โŒ Error: ${error.message}`, 'red');
229
+ log('Please report this issue on GitHub', 'yellow');
230
+ rl.close();
231
+ process.exit(1);
232
+ }
233
+ }
234
+
235
+ // Handle command line args
236
+ const args = process.argv.slice(2);
237
+
238
+ if (args.length === 0 || args[0] === 'init') {
239
+ main();
240
+ } else if (args[0] === '--version' || args[0] === '-v') {
241
+ const packageJson = require('../package.json');
242
+ console.log(packageJson.version);
243
+ process.exit(0);
244
+ } else if (args[0] === '--help' || args[0] === '-h') {
245
+ console.log('');
246
+ log('Usage: npx codingwithagent [command]', 'cyan');
247
+ console.log('');
248
+ log('Commands:');
249
+ log(' init Initialize standards (default)');
250
+ log(' --version, -v Show version');
251
+ log(' --help, -h Show this help');
252
+ console.log('');
253
+ process.exit(0);
254
+ } else {
255
+ log('Unknown command. Use --help for usage information.', 'red');
256
+ process.exit(1);
257
+ }
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "codingwithagent",
3
+ "version": "1.0.0",
4
+ "description": "Production-ready coding standards for AI coding agents. Works with Cursor, Windsurf, Antigravity, and GitHub Copilot.",
5
+ "main": "bin/init.js",
6
+ "bin": {
7
+ "codingwithagent": "./bin/init.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "prepublishOnly": "node -e \"console.log('Publishing codingwithagent...')\"",
12
+ "postinstall": "echo 'Run: npx codingwithagent init'"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/netshdev/codingwithagent.git"
17
+ },
18
+ "keywords": [
19
+ "ai",
20
+ "coding-standards",
21
+ "cursor",
22
+ "windsurf",
23
+ "antigravity",
24
+ "copilot",
25
+ "accessibility",
26
+ "wcag",
27
+ "react",
28
+ "typescript",
29
+ "code-quality",
30
+ "best-practices",
31
+ "a11y",
32
+ "linting",
33
+ "development",
34
+ "productivity",
35
+ "cursorrules",
36
+ "windsurfrules"
37
+ ],
38
+ "author": "Nitish Kafle <kaflenit@gmail.com>",
39
+ "license": "MIT",
40
+ "bugs": {
41
+ "url": "https://github.com/netshdev/codingwithagent/issues"
42
+ },
43
+ "homepage": "https://github.com/netshdev/codingwithagent#readme",
44
+ "engines": {
45
+ "node": ">=14.0.0"
46
+ },
47
+ "files": [
48
+ "bin/",
49
+ "templates/",
50
+ "README.md",
51
+ "LICENSE",
52
+ "CHANGELOG.md"
53
+ ],
54
+ "dependencies": {},
55
+ "devDependencies": {}
56
+ }
@@ -0,0 +1,342 @@
1
+ # Agentic Code Standards - Accessibility-Focused Profile
2
+
3
+ # Version: 1.0.0
4
+
5
+ # Profile: WCAG 2.1+ priority - accessibility first
6
+
7
+ ## Mission
8
+
9
+ Every user, regardless of ability, deserves equal access to your application. This profile prioritizes accessibility above all else while maintaining code quality.
10
+
11
+ ## WCAG 2.1 Level AA Compliance (Minimum)
12
+
13
+ ### Perceivable - Everyone Can "See" This
14
+
15
+ #### Text Alternatives
16
+
17
+ - ALL images MUST have alt text (or alt="" if decorative)
18
+ - Complex images (charts, diagrams) MUST have detailed descriptions
19
+ - Icons with meaning MUST have accessible labels
20
+ - Decorative images MUST have empty alt attributes
21
+
22
+ #### Multimedia
23
+
24
+ - ALL videos MUST have captions
25
+ - ALL audio content MUST have transcripts
26
+ - Captions MUST be accurate and synchronized
27
+ - Audio descriptions MUST be provided for visual-only content
28
+
29
+ #### Adaptable Content
30
+
31
+ - Use semantic HTML (nav, main, header, footer, article, section)
32
+ - Proper heading hierarchy (h1 โ†’ h2 โ†’ h3, no skipping)
33
+ - Meaningful landmarks for screen reader navigation
34
+ - Reading order MUST match visual order
35
+ - Content MUST be understandable when CSS is disabled
36
+
37
+ #### Distinguishable
38
+
39
+ - **Color Contrast Requirements:**
40
+ - Normal text: 4.5:1 minimum (7:1 for AAA)
41
+ - Large text (18pt+ or 14pt+ bold): 3:1 minimum
42
+ - UI components and graphics: 3:1 minimum
43
+ - Use Color Contrast Analyzer tool
44
+ - NEVER use color alone to convey information
45
+ - Add patterns, icons, or text in addition to color
46
+ - Audio MUST have option to pause/stop
47
+ - No auto-playing audio >3 seconds
48
+
49
+ ### Operable - Everyone Can Use This
50
+
51
+ #### Keyboard Accessible
52
+
53
+ - ALL functionality MUST work with keyboard only
54
+ - Visible focus indicators REQUIRED (2px outline minimum)
55
+ - Focus order MUST be logical and intuitive
56
+ - NO keyboard traps (user can always escape)
57
+ - NEVER use `tabIndex > 0`
58
+ - Support standard keys: Tab, Enter, Space, Escape, Arrow keys
59
+
60
+ #### Enough Time
61
+
62
+ - NO time limits unless:
63
+ - User can turn off the limit
64
+ - User can adjust limit to 10x default
65
+ - User is warned and given 20 seconds to extend
66
+ - Provide pause/stop for moving content
67
+ - Auto-updates MUST have controls
68
+
69
+ #### Seizures and Physical Reactions
70
+
71
+ - NOTHING flashes more than 3 times per second
72
+ - Avoid large flashing areas
73
+ - Provide warnings for flashing content
74
+ - Animation MUST respect `prefers-reduced-motion`
75
+
76
+ #### Navigable
77
+
78
+ - Skip navigation links for keyboard users
79
+ - Descriptive page titles
80
+ - Meaningful link text (avoid "click here", "read more")
81
+ - Multiple ways to find pages (search, sitemap, navigation)
82
+ - Clear focus indicators
83
+ - Breadcrumbs for complex navigation
84
+
85
+ ### Understandable - Everyone Can Comprehend This
86
+
87
+ #### Readable
88
+
89
+ - Set language of page: `<html lang="en">`
90
+ - Set language of parts: `<span lang="es">Hola</span>`
91
+ - Use plain language (8th grade reading level or below)
92
+ - Define unusual words and abbreviations
93
+ - Expansion available for abbreviations
94
+
95
+ #### Predictable
96
+
97
+ - Consistent navigation across pages
98
+ - Consistent identification (icons, buttons)
99
+ - NO automatic context changes on focus
100
+ - NO automatic context changes on input (without warning)
101
+ - Forms submit ONLY on explicit action
102
+
103
+ #### Input Assistance
104
+
105
+ - Labels for ALL form inputs
106
+ - Clear error messages with suggestions
107
+ - Error prevention for legal/financial/data transactions
108
+ - Confirmation pages for submissions
109
+ - Ability to review and correct before final submission
110
+
111
+ ### Robust - All Devices Can Use This
112
+
113
+ #### Compatible
114
+
115
+ - Valid HTML (pass W3C validator)
116
+ - Proper ARIA attributes when needed
117
+ - Name, role, value for all UI components
118
+ - Status messages programmatically determinable
119
+ - Works with assistive technologies
120
+ - Test with NVDA, JAWS, VoiceOver, TalkBack
121
+
122
+ ## ARIA - Use Carefully
123
+
124
+ ### When to Use ARIA
125
+
126
+ - Only when semantic HTML isn't sufficient
127
+ - Custom widgets (tabs, accordions, modals)
128
+ - Live regions for dynamic content
129
+ - Relationship indicators
130
+
131
+ ### ARIA Rules
132
+
133
+ 1. First Rule of ARIA: Don't use ARIA (use semantic HTML first)
134
+ 2. Never change semantic meaning
135
+ 3. All interactive ARIA controls must be keyboard accessible
136
+ 4. Don't hide visible and actionable elements from screen readers
137
+ 5. All interactive elements must have an accessible name
138
+
139
+ ### Common ARIA Patterns
140
+
141
+ - `role="button"` - Only if you can't use `<button>`
142
+ - `aria-label` - Provide name when visual label isn't present
143
+ - `aria-labelledby` - Associate existing label
144
+ - `aria-describedby` - Additional description
145
+ - `aria-live` - Announce dynamic content changes
146
+ - `aria-expanded` - State of collapsible content
147
+ - `aria-hidden="true"` - Hide decorative elements
148
+
149
+ ## Forms Accessibility
150
+
151
+ ### Form Field Requirements
152
+
153
+ - ALL inputs MUST have associated `<label>` elements
154
+ - Use `<label for="inputId">` or wrap input
155
+ - Required fields MUST be indicated (not just with color/asterisk)
156
+ - Error messages MUST be programmatically associated
157
+ - Validation MUST happen on blur or submit, not on input
158
+
159
+ ### Form Patterns
160
+
161
+ ```javascript
162
+ // Good: Associated label
163
+ <label htmlFor="email">Email Address *</label>
164
+ <input id="email" type="email" required aria-describedby="email-help" />
165
+ <small id="email-help">We'll never share your email</small>
166
+
167
+ // Good: Error handling
168
+ <input
169
+ id="email"
170
+ type="email"
171
+ aria-invalid={hasError}
172
+ aria-describedby="email-error"
173
+ />
174
+ {hasError && <p id="email-error" role="alert">Please enter a valid email</p>}
175
+ ```
176
+
177
+ ### Form Validation
178
+
179
+ - Inline validation on blur
180
+ - Clear error messages with solutions
181
+ - Error summary at top of form
182
+ - Focus management to first error
183
+ - Success confirmation
184
+
185
+ ## React Accessibility
186
+
187
+ ### Component Requirements
188
+
189
+ - Semantic HTML elements preferred over divs
190
+ - Button elements for actions, links for navigation
191
+ - Proper heading hierarchy maintained
192
+ - Focus management in modals and dynamic content
193
+ - Announce dynamic content with aria-live
194
+
195
+ ### Focus Management
196
+
197
+ ```javascript
198
+ // Good: Focus management in modal
199
+ useEffect(() => {
200
+ if (isOpen) {
201
+ modalRef.current?.focus();
202
+ }
203
+ }, [isOpen]);
204
+
205
+ // Good: Trap focus in modal
206
+ const handleKeyDown = (e) => {
207
+ if (e.key === "Escape") closeModal();
208
+ if (e.key === "Tab") trapFocus(e);
209
+ };
210
+ ```
211
+
212
+ ### Live Regions
213
+
214
+ ```javascript
215
+ // Good: Announce loading state
216
+ <div role="status" aria-live="polite" aria-atomic="true">
217
+ {isLoading ? "Loading..." : `${results.length} results found`}
218
+ </div>
219
+ ```
220
+
221
+ ## Testing Requirements
222
+
223
+ ### Automated Testing
224
+
225
+ - axe-core or jest-axe in unit tests
226
+ - Lighthouse accessibility audit (score 100)
227
+ - pa11y or similar in CI/CD
228
+ - ESLint jsx-a11y plugin enabled
229
+
230
+ ### Manual Testing
231
+
232
+ 1. Keyboard navigation (Tab, Enter, Space, Escape)
233
+ 2. Screen reader testing:
234
+ - NVDA (Windows - free)
235
+ - JAWS (Windows - paid)
236
+ - VoiceOver (Mac/iOS - built-in)
237
+ - TalkBack (Android - built-in)
238
+ 3. Color contrast analyzer
239
+ 4. Zoom to 200% (text must remain readable)
240
+ 5. Browser with CSS disabled
241
+ 6. prefers-reduced-motion testing
242
+
243
+ ### Testing Checklist
244
+
245
+ - [ ] All functionality keyboard accessible
246
+ - [ ] Visible focus indicators
247
+ - [ ] Logical focus order
248
+ - [ ] Screen reader announces content correctly
249
+ - [ ] Color contrast passes
250
+ - [ ] Alt text for images
251
+ - [ ] Form labels associated
252
+ - [ ] Error messages clear
253
+ - [ ] No automatic timeouts
254
+ - [ ] No flashing content
255
+ - [ ] Semantic HTML used
256
+ - [ ] Zoom to 200% works
257
+
258
+ ## Code Examples
259
+
260
+ ### Accessible Button
261
+
262
+ ```javascript
263
+ // Good: Semantic button
264
+ <button onClick={handleClick} aria-pressed={isPressed}>
265
+ Toggle {isPressed ? 'On' : 'Off'}
266
+ </button>
267
+
268
+ // Bad: Div as button
269
+ <div onClick={handleClick}>Click me</div>
270
+ ```
271
+
272
+ ### Accessible Modal
273
+
274
+ ```javascript
275
+ const Modal = ({ isOpen, onClose, children }) => {
276
+ const modalRef = useRef();
277
+
278
+ useEffect(() => {
279
+ if (isOpen) {
280
+ modalRef.current?.focus();
281
+ }
282
+ }, [isOpen]);
283
+
284
+ return (
285
+ <div
286
+ role="dialog"
287
+ aria-modal="true"
288
+ aria-labelledby="modal-title"
289
+ ref={modalRef}
290
+ tabIndex={-1}
291
+ onKeyDown={(e) => e.key === "Escape" && onClose()}
292
+ >
293
+ <h2 id="modal-title">Modal Title</h2>
294
+ {children}
295
+ <button onClick={onClose}>Close</button>
296
+ </div>
297
+ );
298
+ };
299
+ ```
300
+
301
+ ### Accessible Navigation
302
+
303
+ ```javascript
304
+ <nav aria-label="Main navigation">
305
+ <ul>
306
+ <li>
307
+ <a href="/" aria-current={isHome && "page"}>
308
+ Home
309
+ </a>
310
+ </li>
311
+ <li>
312
+ <a href="/about">About</a>
313
+ </li>
314
+ <li>
315
+ <a href="/contact">Contact</a>
316
+ </li>
317
+ </ul>
318
+ </nav>
319
+ ```
320
+
321
+ ## Resources
322
+
323
+ ### Guidelines
324
+
325
+ - WCAG 2.1: https://www.w3.org/WAI/WCAG21/quickref/
326
+ - ARIA Authoring Practices: https://www.w3.org/WAI/ARIA/apg/
327
+ - WebAIM: https://webaim.org/
328
+
329
+ ### Testing Tools
330
+
331
+ - axe DevTools: https://www.deque.com/axe/devtools/
332
+ - WAVE: https://wave.webaim.org/
333
+ - Color Contrast Analyzer: https://www.tpgi.com/color-contrast-checker/
334
+
335
+ ### Screen Readers
336
+
337
+ - NVDA (free): https://www.nvaccess.org/
338
+ - VoiceOver: Built into Mac/iOS
339
+ - TalkBack: Built into Android
340
+
341
+ Accessibility is not optional.
342
+ Full documentation: https://github.com/netshdev/codingwithagent