@neyugn/agent-kits 0.1.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 +514 -0
- package/README.vi.md +410 -0
- package/README.zh.md +410 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +422 -0
- package/kits/coder/ARCHITECTURE.md +289 -0
- package/kits/coder/agents/ai-engineer.md +344 -0
- package/kits/coder/agents/backend-specialist.md +270 -0
- package/kits/coder/agents/cloud-architect.md +363 -0
- package/kits/coder/agents/code-reviewer.md +284 -0
- package/kits/coder/agents/data-engineer.md +401 -0
- package/kits/coder/agents/database-specialist.md +251 -0
- package/kits/coder/agents/debugger.md +209 -0
- package/kits/coder/agents/devops-engineer.md +281 -0
- package/kits/coder/agents/documentation-writer.md +296 -0
- package/kits/coder/agents/frontend-specialist.md +298 -0
- package/kits/coder/agents/i18n-specialist.md +348 -0
- package/kits/coder/agents/integration-specialist.md +314 -0
- package/kits/coder/agents/mobile-developer.md +271 -0
- package/kits/coder/agents/multi-tenant-architect.md +281 -0
- package/kits/coder/agents/orchestrator.md +263 -0
- package/kits/coder/agents/performance-analyst.md +327 -0
- package/kits/coder/agents/project-planner.md +277 -0
- package/kits/coder/agents/queue-specialist.md +282 -0
- package/kits/coder/agents/realtime-specialist.md +267 -0
- package/kits/coder/agents/security-auditor.md +253 -0
- package/kits/coder/agents/test-engineer.md +315 -0
- package/kits/coder/agents/ux-researcher.md +388 -0
- package/kits/coder/rules/.cursorrules +287 -0
- package/kits/coder/rules/CLAUDE.md +287 -0
- package/kits/coder/rules/CODEX.md +287 -0
- package/kits/coder/rules/GEMINI.md +287 -0
- package/kits/coder/scripts/checklist.py +318 -0
- package/kits/coder/scripts/kit_status.py +292 -0
- package/kits/coder/scripts/skills_manager.py +243 -0
- package/kits/coder/scripts/verify_all.py +391 -0
- package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
- package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
- package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
- package/kits/coder/skills/api-patterns/SKILL.md +316 -0
- package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
- package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
- package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
- package/kits/coder/skills/brainstorming/SKILL.md +370 -0
- package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
- package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
- package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
- package/kits/coder/skills/clean-code/SKILL.md +240 -0
- package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
- package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
- package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
- package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
- package/kits/coder/skills/database-design/SKILL.md +255 -0
- package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
- package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
- package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
- package/kits/coder/skills/database-design/scripts/validate.py +56 -0
- package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
- package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
- package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
- package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
- package/kits/coder/skills/frontend-design/SKILL.md +127 -0
- package/kits/coder/skills/github-actions/SKILL.md +349 -0
- package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
- package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
- package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
- package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
- package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
- package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
- package/kits/coder/skills/mobile-design/SKILL.md +305 -0
- package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
- package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
- package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
- package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
- package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
- package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
- package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
- package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
- package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
- package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
- package/kits/coder/skills/plan-writing/SKILL.md +360 -0
- package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
- package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
- package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
- package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
- package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
- package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
- package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
- package/kits/coder/skills/react-patterns/SKILL.md +319 -0
- package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
- package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
- package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
- package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
- package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
- package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
- package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
- package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
- package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
- package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
- package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
- package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
- package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
- package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
- package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
- package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
- package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
- package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
- package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/kits/coder/workflows/.gitkeep +20 -0
- package/kits/coder/workflows/create.md +152 -0
- package/kits/coder/workflows/debug.md +223 -0
- package/kits/coder/workflows/deploy.md +283 -0
- package/kits/coder/workflows/orchestrate.md +243 -0
- package/kits/coder/workflows/plan.md +134 -0
- package/kits/coder/workflows/test.md +237 -0
- package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
- package/package.json +49 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: accessibility-patterns
|
|
3
|
+
description: WCAG compliance, inclusive design, and assistive technology patterns. Use when auditing accessibility, implementing a11y features, or ensuring digital products are accessible to all users.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash
|
|
5
|
+
version: 1.0
|
|
6
|
+
priority: MEDIUM
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Accessibility Patterns - Inclusive Design Excellence
|
|
10
|
+
|
|
11
|
+
> **Philosophy:** Accessibility is not a feature, it's a fundamental requirement. Design for everyone from the start.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🎯 Core Principles
|
|
16
|
+
|
|
17
|
+
| Principle | Rule |
|
|
18
|
+
| ------------------- | --------------------------------------------- |
|
|
19
|
+
| **Perceivable** | Information must be presentable to all senses |
|
|
20
|
+
| **Operable** | UI must be operable by all users |
|
|
21
|
+
| **Understandable** | Information and UI must be understandable |
|
|
22
|
+
| **Robust** | Content must work with assistive technologies |
|
|
23
|
+
| **Inclusive First** | Build accessibility in, don't bolt it on |
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
❌ WRONG: Build first, add accessibility later
|
|
27
|
+
✅ CORRECT: Consider accessibility in every design decision
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 📊 WCAG Compliance Levels
|
|
33
|
+
|
|
34
|
+
| Level | Description | Legal Requirement? |
|
|
35
|
+
| ------- | ------------------------------- | ----------------------- |
|
|
36
|
+
| **A** | Minimum accessibility | Often required |
|
|
37
|
+
| **AA** | Standard for most organizations | Most common requirement |
|
|
38
|
+
| **AAA** | Highest accessibility standard | Rarely fully achievable |
|
|
39
|
+
|
|
40
|
+
> **Target AA for most projects.** It covers the most critical accessibility needs.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 🎨 Visual Accessibility
|
|
45
|
+
|
|
46
|
+
### Color Contrast
|
|
47
|
+
|
|
48
|
+
| Element | AA Ratio | AAA Ratio |
|
|
49
|
+
| ------------------ | -------- | --------- |
|
|
50
|
+
| Normal text | 4.5:1 | 7:1 |
|
|
51
|
+
| Large text (18px+) | 3:1 | 4.5:1 |
|
|
52
|
+
| UI components | 3:1 | 3:1 |
|
|
53
|
+
| Focus indicators | 3:1 | 3:1 |
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
/* ✅ GOOD - Sufficient contrast */
|
|
57
|
+
.text-primary {
|
|
58
|
+
color: #1a1a1a; /* Contrast: 16.1:1 on white */
|
|
59
|
+
background: #ffffff;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* ❌ BAD - Insufficient contrast */
|
|
63
|
+
.text-muted {
|
|
64
|
+
color: #999999; /* Contrast: 2.8:1 - FAILS */
|
|
65
|
+
background: #ffffff;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Color Independence
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<!-- ❌ BAD - Color only indicates error -->
|
|
73
|
+
<input class="error-red" />
|
|
74
|
+
|
|
75
|
+
<!-- ✅ GOOD - Multiple indicators -->
|
|
76
|
+
<input class="error" aria-invalid="true" />
|
|
77
|
+
<span class="error-icon">⚠️</span>
|
|
78
|
+
<span class="error-message">Email is required</span>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ⌨️ Keyboard Accessibility
|
|
84
|
+
|
|
85
|
+
### Focus Management
|
|
86
|
+
|
|
87
|
+
| Rule | Implementation |
|
|
88
|
+
| --------------------------- | --------------------------------- |
|
|
89
|
+
| All interactive elements | Must be focusable via Tab |
|
|
90
|
+
| Logical focus order | Match visual reading order |
|
|
91
|
+
| Visible focus indicators | Never `outline: none` without alt |
|
|
92
|
+
| Focus trapping in modals | Tab loops within modal |
|
|
93
|
+
| Return focus on modal close | Focus returns to trigger element |
|
|
94
|
+
|
|
95
|
+
### Focus Indicator Pattern
|
|
96
|
+
|
|
97
|
+
```css
|
|
98
|
+
/* ✅ GOOD - Visible, accessible focus */
|
|
99
|
+
:focus-visible {
|
|
100
|
+
outline: 2px solid var(--color-primary);
|
|
101
|
+
outline-offset: 2px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Remove default only if custom focus exists */
|
|
105
|
+
button:focus:not(:focus-visible) {
|
|
106
|
+
outline: none;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Skip Links
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<body>
|
|
114
|
+
<a href="#main-content" class="skip-link"> Skip to main content </a>
|
|
115
|
+
<!-- Navigation -->
|
|
116
|
+
<main id="main-content">
|
|
117
|
+
<!-- Content -->
|
|
118
|
+
</main>
|
|
119
|
+
</body>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```css
|
|
123
|
+
.skip-link {
|
|
124
|
+
position: absolute;
|
|
125
|
+
left: -9999px;
|
|
126
|
+
}
|
|
127
|
+
.skip-link:focus {
|
|
128
|
+
left: 10px;
|
|
129
|
+
top: 10px;
|
|
130
|
+
z-index: 9999;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🔊 Screen Reader Support
|
|
137
|
+
|
|
138
|
+
### Semantic HTML
|
|
139
|
+
|
|
140
|
+
| Use | Not |
|
|
141
|
+
| ------------------- | ----------------------- |
|
|
142
|
+
| `<button>` | `<div onclick>` |
|
|
143
|
+
| `<a href>` | `<span onclick>` |
|
|
144
|
+
| `<nav>` | `<div class="nav">` |
|
|
145
|
+
| `<main>` | `<div class="main">` |
|
|
146
|
+
| `<header>/<footer>` | `<div class="header">` |
|
|
147
|
+
| `<article>` | `<div class="article">` |
|
|
148
|
+
|
|
149
|
+
### ARIA Usage Guidelines
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<!-- Rule 1: Don't use ARIA if you can use HTML -->
|
|
153
|
+
<!-- ❌ BAD -->
|
|
154
|
+
<div role="button" tabindex="0">Click me</div>
|
|
155
|
+
|
|
156
|
+
<!-- ✅ GOOD -->
|
|
157
|
+
<button>Click me</button>
|
|
158
|
+
|
|
159
|
+
<!-- Rule 2: Use ARIA to enhance, not replace -->
|
|
160
|
+
<button aria-label="Close dialog" aria-describedby="dialog-desc">
|
|
161
|
+
<svg><!-- X icon --></svg>
|
|
162
|
+
</button>
|
|
163
|
+
<p id="dialog-desc">This will close the settings dialog</p>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Live Regions
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<!-- Announce dynamic content changes -->
|
|
170
|
+
<div role="status" aria-live="polite">3 search results found</div>
|
|
171
|
+
|
|
172
|
+
<div role="alert" aria-live="assertive">Error: Unable to save changes</div>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
| aria-live Value | Use Case |
|
|
176
|
+
| --------------- | ----------------------------------- |
|
|
177
|
+
| `polite` | Non-urgent updates (search results) |
|
|
178
|
+
| `assertive` | Urgent (errors, alerts) |
|
|
179
|
+
| `off` | Don't announce |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 📝 Forms Accessibility
|
|
184
|
+
|
|
185
|
+
### Labels and Descriptions
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<!-- ✅ GOOD - Properly labeled -->
|
|
189
|
+
<label for="email">Email Address</label>
|
|
190
|
+
<input
|
|
191
|
+
type="email"
|
|
192
|
+
id="email"
|
|
193
|
+
aria-describedby="email-hint email-error"
|
|
194
|
+
aria-invalid="false"
|
|
195
|
+
required
|
|
196
|
+
/>
|
|
197
|
+
<span id="email-hint">We'll never share your email</span>
|
|
198
|
+
<span id="email-error" role="alert"></span>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Error Handling
|
|
202
|
+
|
|
203
|
+
```html
|
|
204
|
+
<!-- Error state -->
|
|
205
|
+
<label for="password">Password</label>
|
|
206
|
+
<input
|
|
207
|
+
type="password"
|
|
208
|
+
id="password"
|
|
209
|
+
aria-invalid="true"
|
|
210
|
+
aria-describedby="password-error"
|
|
211
|
+
/>
|
|
212
|
+
<span id="password-error" role="alert">
|
|
213
|
+
Password must be at least 8 characters
|
|
214
|
+
</span>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Form Validation Pattern
|
|
218
|
+
|
|
219
|
+
| When | What |
|
|
220
|
+
| --------- | --------------------------------------- |
|
|
221
|
+
| On submit | Announce error count, focus first error |
|
|
222
|
+
| On blur | Validate individual field |
|
|
223
|
+
| On fix | Clear error, don't re-announce success |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 🖼️ Images and Media
|
|
228
|
+
|
|
229
|
+
### Alt Text Guidelines
|
|
230
|
+
|
|
231
|
+
| Image Type | Alt Text |
|
|
232
|
+
| ----------------- | ------------------------------ |
|
|
233
|
+
| Informative | Describe content and purpose |
|
|
234
|
+
| Decorative | `alt=""` (empty) |
|
|
235
|
+
| Functional (link) | Describe destination/action |
|
|
236
|
+
| Complex (chart) | Brief alt + longer description |
|
|
237
|
+
|
|
238
|
+
```html
|
|
239
|
+
<!-- Informative -->
|
|
240
|
+
<img src="chart.png" alt="Sales grew 25% from Q1 to Q2" />
|
|
241
|
+
|
|
242
|
+
<!-- Decorative -->
|
|
243
|
+
<img src="decoration.png" alt="" role="presentation" />
|
|
244
|
+
|
|
245
|
+
<!-- Complex -->
|
|
246
|
+
<figure>
|
|
247
|
+
<img src="complex-chart.png" alt="Revenue breakdown by region" />
|
|
248
|
+
<figcaption>North America leads with 45%, Europe at 30%...</figcaption>
|
|
249
|
+
</figure>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Video Accessibility
|
|
253
|
+
|
|
254
|
+
| Requirement | Solution |
|
|
255
|
+
| --------------- | ---------------------------- |
|
|
256
|
+
| Deaf users | Captions (synchronized text) |
|
|
257
|
+
| Blind users | Audio descriptions |
|
|
258
|
+
| Deafblind users | Transcript |
|
|
259
|
+
| Seizure safety | No flashing >3 times/second |
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 📱 Touch and Mobile
|
|
264
|
+
|
|
265
|
+
### Touch Target Size
|
|
266
|
+
|
|
267
|
+
| Standard | Minimum Size |
|
|
268
|
+
| --------------- | ------------ |
|
|
269
|
+
| WCAG 2.2 AA | 24x24px |
|
|
270
|
+
| WCAG 2.2 AAA | 44x44px |
|
|
271
|
+
| Apple HIG | 44x44pt |
|
|
272
|
+
| Material Design | 48x48dp |
|
|
273
|
+
|
|
274
|
+
### Spacing Between Targets
|
|
275
|
+
|
|
276
|
+
```css
|
|
277
|
+
.button-group button {
|
|
278
|
+
min-width: 44px;
|
|
279
|
+
min-height: 44px;
|
|
280
|
+
margin: 8px; /* Prevent accidental taps */
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 🧪 Testing Tools
|
|
287
|
+
|
|
288
|
+
### Automated Testing
|
|
289
|
+
|
|
290
|
+
| Tool | Use Case |
|
|
291
|
+
| ---------------- | ----------------------------------- |
|
|
292
|
+
| **axe DevTools** | Browser extension, CI integration |
|
|
293
|
+
| **Lighthouse** | Chrome DevTools, performance + a11y |
|
|
294
|
+
| **WAVE** | Browser extension, visual feedback |
|
|
295
|
+
| **pa11y** | CLI tool for CI/CD |
|
|
296
|
+
| **jest-axe** | Unit test accessibility assertions |
|
|
297
|
+
|
|
298
|
+
### Manual Testing
|
|
299
|
+
|
|
300
|
+
| Test | How |
|
|
301
|
+
| -------------- | ------------------------------------ |
|
|
302
|
+
| Keyboard only | Unplug mouse, navigate with Tab |
|
|
303
|
+
| Screen reader | VoiceOver (Mac), NVDA/JAWS (Windows) |
|
|
304
|
+
| Zoom 200% | Browser zoom, check layout |
|
|
305
|
+
| Color contrast | Use contrast checker tools |
|
|
306
|
+
| Motion reduced | Test `prefers-reduced-motion` |
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 🚨 Anti-Patterns
|
|
311
|
+
|
|
312
|
+
| ❌ Don't | ✅ Do |
|
|
313
|
+
| -------------------------------- | ----------------------------------- |
|
|
314
|
+
| `outline: none` without alt | Custom focus with adequate contrast |
|
|
315
|
+
| Color-only indicators | Multiple visual cues |
|
|
316
|
+
| Generic link text ("click here") | Descriptive link text |
|
|
317
|
+
| Auto-playing media | User-controlled playback |
|
|
318
|
+
| Time limits without extension | Allow time extension or removal |
|
|
319
|
+
| Mouse-only interactions | Keyboard equivalent for all actions |
|
|
320
|
+
| Missing form labels | Associated labels or aria-label |
|
|
321
|
+
| Small touch targets | Minimum 44x44 touch targets |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## ✅ Accessibility Checklist
|
|
326
|
+
|
|
327
|
+
### Perceivable
|
|
328
|
+
|
|
329
|
+
- [ ] All images have appropriate alt text
|
|
330
|
+
- [ ] Color contrast meets 4.5:1 for text
|
|
331
|
+
- [ ] Color is not the only way to convey info
|
|
332
|
+
- [ ] Captions for video content
|
|
333
|
+
- [ ] Text can be resized to 200% without loss
|
|
334
|
+
|
|
335
|
+
### Operable
|
|
336
|
+
|
|
337
|
+
- [ ] All functionality available via keyboard
|
|
338
|
+
- [ ] Visible focus indicators on all elements
|
|
339
|
+
- [ ] Skip links for main content
|
|
340
|
+
- [ ] No keyboard traps
|
|
341
|
+
- [ ] Adequate time for timed content
|
|
342
|
+
- [ ] Touch targets are 44x44 minimum
|
|
343
|
+
|
|
344
|
+
### Understandable
|
|
345
|
+
|
|
346
|
+
- [ ] Language attribute on `<html>`
|
|
347
|
+
- [ ] Consistent navigation pattern
|
|
348
|
+
- [ ] Form errors are clearly explained
|
|
349
|
+
- [ ] Labels on all form fields
|
|
350
|
+
- [ ] Instructions before complex forms
|
|
351
|
+
|
|
352
|
+
### Robust
|
|
353
|
+
|
|
354
|
+
- [ ] Valid HTML
|
|
355
|
+
- [ ] Semantic elements used correctly
|
|
356
|
+
- [ ] ARIA used only when necessary
|
|
357
|
+
- [ ] Works with screen readers
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## 🔗 Related Skills
|
|
362
|
+
|
|
363
|
+
| Need | Skill |
|
|
364
|
+
| ------------------ | ----------------------- |
|
|
365
|
+
| SEO implementation | `seo-patterns` |
|
|
366
|
+
| Frontend design | `frontend-design` |
|
|
367
|
+
| UX research | UX researcher agent |
|
|
368
|
+
| Performance | `performance-profiling` |
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
> **Remember:** Every accessibility barrier you remove opens your product to more people. 15-20% of the global population has some form of disability.
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Accessibility Checker - WCAG compliance audit for AGT-Kit
|
|
4
|
+
==========================================================
|
|
5
|
+
|
|
6
|
+
Checks HTML/JSX for common accessibility issues.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 .agent/skills/accessibility-patterns/scripts/a11y_checker.py <project_path>
|
|
10
|
+
|
|
11
|
+
Checks based on WCAG 2.2:
|
|
12
|
+
- Images with alt text
|
|
13
|
+
- Form labels
|
|
14
|
+
- Heading hierarchy
|
|
15
|
+
- Color contrast considerations
|
|
16
|
+
- ARIA attributes
|
|
17
|
+
- Keyboard navigation hints
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import sys
|
|
21
|
+
import re
|
|
22
|
+
import json
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from datetime import datetime
|
|
25
|
+
from typing import Dict, List, Any
|
|
26
|
+
|
|
27
|
+
# Fix console encoding
|
|
28
|
+
try:
|
|
29
|
+
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
30
|
+
except:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
SKIP_DIRS = {'node_modules', '.git', 'dist', 'build', '__pycache__', '.next', 'venv'}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def find_ui_files(project_path: Path) -> List[Path]:
|
|
37
|
+
"""Find UI component files."""
|
|
38
|
+
patterns = ['**/*.tsx', '**/*.jsx', '**/*.html', '**/*.vue']
|
|
39
|
+
|
|
40
|
+
files = []
|
|
41
|
+
for pattern in patterns:
|
|
42
|
+
for f in project_path.glob(pattern):
|
|
43
|
+
if not any(skip in f.parts for skip in SKIP_DIRS):
|
|
44
|
+
# Skip test files
|
|
45
|
+
if not any(x in f.name.lower() for x in ['test', 'spec', 'mock']):
|
|
46
|
+
files.append(f)
|
|
47
|
+
|
|
48
|
+
return files[:30] # Limit
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def check_file(file_path: Path) -> Dict[str, Any]:
|
|
52
|
+
"""Check a single file for accessibility issues."""
|
|
53
|
+
try:
|
|
54
|
+
content = file_path.read_text(encoding='utf-8', errors='ignore')
|
|
55
|
+
except:
|
|
56
|
+
return {'file': file_path.name, 'passed': [], 'issues': ['Read error']}
|
|
57
|
+
|
|
58
|
+
passed = []
|
|
59
|
+
issues = []
|
|
60
|
+
|
|
61
|
+
# 1. Images with alt text
|
|
62
|
+
img_tags = re.findall(r'<img[^>]*>', content, re.I)
|
|
63
|
+
img_without_alt = [img for img in img_tags if 'alt=' not in img.lower()]
|
|
64
|
+
|
|
65
|
+
if img_tags and not img_without_alt:
|
|
66
|
+
passed.append(f"All {len(img_tags)} images have alt text")
|
|
67
|
+
elif img_without_alt:
|
|
68
|
+
issues.append(f"{len(img_without_alt)} images missing alt text")
|
|
69
|
+
|
|
70
|
+
# 2. Form labels
|
|
71
|
+
inputs = re.findall(r'<input[^>]*>', content, re.I)
|
|
72
|
+
inputs_need_label = [i for i in inputs if 'type="hidden"' not in i.lower() and 'type="submit"' not in i.lower()]
|
|
73
|
+
|
|
74
|
+
has_labels = 'label' in content.lower() or 'aria-label' in content.lower()
|
|
75
|
+
if inputs_need_label and has_labels:
|
|
76
|
+
passed.append("Form labels/aria-labels found")
|
|
77
|
+
elif inputs_need_label and not has_labels:
|
|
78
|
+
issues.append("Form inputs may be missing labels")
|
|
79
|
+
|
|
80
|
+
# 3. Heading hierarchy
|
|
81
|
+
h1_count = len(re.findall(r'<h1[^>]*>', content, re.I))
|
|
82
|
+
h2_count = len(re.findall(r'<h2[^>]*>', content, re.I))
|
|
83
|
+
h3_count = len(re.findall(r'<h3[^>]*>', content, re.I))
|
|
84
|
+
|
|
85
|
+
if h1_count <= 1:
|
|
86
|
+
passed.append("Proper H1 usage (0-1)")
|
|
87
|
+
else:
|
|
88
|
+
issues.append(f"Multiple H1 tags ({h1_count}) - bad for a11y")
|
|
89
|
+
|
|
90
|
+
# Check for skipped heading levels (h1 -> h3 without h2)
|
|
91
|
+
if h3_count > 0 and h2_count == 0 and h1_count > 0:
|
|
92
|
+
issues.append("Skipped heading level (H1 -> H3)")
|
|
93
|
+
|
|
94
|
+
# 4. ARIA attributes
|
|
95
|
+
aria_patterns = ['aria-label', 'aria-labelledby', 'aria-describedby', 'role=']
|
|
96
|
+
has_aria = any(p in content for p in aria_patterns)
|
|
97
|
+
if has_aria:
|
|
98
|
+
passed.append("ARIA attributes used")
|
|
99
|
+
|
|
100
|
+
# 5. Focus indicators
|
|
101
|
+
focus_patterns = [':focus', 'onFocus', 'tabIndex', 'focus-visible']
|
|
102
|
+
has_focus = any(p in content for p in focus_patterns)
|
|
103
|
+
if has_focus:
|
|
104
|
+
passed.append("Focus handling present")
|
|
105
|
+
|
|
106
|
+
# 6. Buttons with text/aria-label
|
|
107
|
+
buttons = re.findall(r'<button[^>]*>([^<]*)</button>', content, re.I)
|
|
108
|
+
empty_buttons = [b for b in re.findall(r'<button[^>]*>', content, re.I)
|
|
109
|
+
if 'aria-label' not in b.lower() and '>' in b and '</' in content[content.find(b):content.find(b)+100]]
|
|
110
|
+
|
|
111
|
+
# Check for icon-only buttons
|
|
112
|
+
icon_buttons = re.findall(r'<button[^>]*>\s*<[^>]+/>\s*</button>', content, re.I)
|
|
113
|
+
if icon_buttons:
|
|
114
|
+
issues.append(f"{len(icon_buttons)} icon-only buttons may need aria-label")
|
|
115
|
+
|
|
116
|
+
# 7. Links with meaningful text
|
|
117
|
+
links = re.findall(r'<a[^>]*>([^<]*)</a>', content, re.I)
|
|
118
|
+
bad_link_text = ['click here', 'read more', 'here', 'more']
|
|
119
|
+
problematic_links = [l for l in links if l.lower().strip() in bad_link_text]
|
|
120
|
+
|
|
121
|
+
if problematic_links:
|
|
122
|
+
issues.append(f"{len(problematic_links)} links with non-descriptive text")
|
|
123
|
+
elif links:
|
|
124
|
+
passed.append("Link text appears descriptive")
|
|
125
|
+
|
|
126
|
+
# 8. Color contrast (basic check)
|
|
127
|
+
if 'color:' in content.lower() or 'backgroundColor' in content:
|
|
128
|
+
if 'contrast' in content.lower() or '--' in content: # CSS variables
|
|
129
|
+
passed.append("Color theming detected")
|
|
130
|
+
|
|
131
|
+
# 9. Skip links
|
|
132
|
+
if 'skip' in content.lower() and 'main' in content.lower():
|
|
133
|
+
passed.append("Skip link pattern detected")
|
|
134
|
+
|
|
135
|
+
return {'file': file_path.name, 'passed': passed, 'issues': issues}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def main():
|
|
139
|
+
project_path = Path(sys.argv[1] if len(sys.argv) > 1 else ".").resolve()
|
|
140
|
+
|
|
141
|
+
print(f"\n{'='*60}")
|
|
142
|
+
print(f"[AGT-KIT A11Y CHECKER] Accessibility Audit (WCAG 2.2)")
|
|
143
|
+
print(f"{'='*60}")
|
|
144
|
+
print(f"Project: {project_path}")
|
|
145
|
+
print(f"Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
146
|
+
print("-"*60)
|
|
147
|
+
|
|
148
|
+
files = find_ui_files(project_path)
|
|
149
|
+
|
|
150
|
+
if not files:
|
|
151
|
+
print("\nNo UI files found.")
|
|
152
|
+
output = {
|
|
153
|
+
"script": "a11y_checker",
|
|
154
|
+
"skill": "accessibility-patterns",
|
|
155
|
+
"project": str(project_path),
|
|
156
|
+
"files_checked": 0,
|
|
157
|
+
"passed": True
|
|
158
|
+
}
|
|
159
|
+
print(json.dumps(output, indent=2))
|
|
160
|
+
sys.exit(0)
|
|
161
|
+
|
|
162
|
+
print(f"Found {len(files)} UI files to analyze\n")
|
|
163
|
+
|
|
164
|
+
results = []
|
|
165
|
+
total_passed = 0
|
|
166
|
+
total_issues = 0
|
|
167
|
+
|
|
168
|
+
for file_path in files:
|
|
169
|
+
result = check_file(file_path)
|
|
170
|
+
|
|
171
|
+
if result['issues'] or result['passed']:
|
|
172
|
+
results.append(result)
|
|
173
|
+
total_passed += len(result['passed'])
|
|
174
|
+
total_issues += len(result['issues'])
|
|
175
|
+
|
|
176
|
+
if result['issues']:
|
|
177
|
+
print(f"⚠️ {result['file']}")
|
|
178
|
+
for issue in result['issues'][:2]:
|
|
179
|
+
print(f" - {issue}")
|
|
180
|
+
|
|
181
|
+
# Summary
|
|
182
|
+
print("\n" + "="*60)
|
|
183
|
+
print("SUMMARY")
|
|
184
|
+
print("="*60)
|
|
185
|
+
|
|
186
|
+
print(f"✅ {total_passed} accessibility patterns found")
|
|
187
|
+
print(f"⚠️ {total_issues} potential issues")
|
|
188
|
+
|
|
189
|
+
passed = total_issues < 10
|
|
190
|
+
|
|
191
|
+
if passed:
|
|
192
|
+
print("\n✅ Accessibility check passed")
|
|
193
|
+
else:
|
|
194
|
+
print("\n⚠️ Review accessibility issues")
|
|
195
|
+
|
|
196
|
+
output = {
|
|
197
|
+
"script": "a11y_checker",
|
|
198
|
+
"skill": "accessibility-patterns",
|
|
199
|
+
"project": str(project_path),
|
|
200
|
+
"files_checked": len(files),
|
|
201
|
+
"patterns_found": total_passed,
|
|
202
|
+
"issues_found": total_issues,
|
|
203
|
+
"passed": passed
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
print("\n" + json.dumps(output, indent=2))
|
|
207
|
+
sys.exit(0 if passed else 1)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
if __name__ == "__main__":
|
|
211
|
+
main()
|