devflow-kit 1.1.0 → 1.2.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/CHANGELOG.md +39 -0
- package/README.md +23 -6
- package/dist/plugins.js +67 -3
- package/package.json +2 -1
- package/plugins/devflow-accessibility/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +1 -1
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +4 -0
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -4
- package/plugins/devflow-code-review/agents/reviewer.md +8 -0
- package/plugins/devflow-code-review/commands/code-review-teams.md +11 -1
- package/plugins/devflow-code-review/commands/code-review.md +12 -2
- package/plugins/devflow-core-skills/.claude-plugin/plugin.json +2 -6
- package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-go/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-go/skills/go/SKILL.md +187 -0
- package/plugins/devflow-go/skills/go/references/concurrency.md +312 -0
- package/plugins/devflow-go/skills/go/references/detection.md +129 -0
- package/plugins/devflow-go/skills/go/references/patterns.md +232 -0
- package/plugins/devflow-go/skills/go/references/violations.md +205 -0
- package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -3
- package/plugins/devflow-implement/agents/coder.md +11 -6
- package/plugins/devflow-java/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-java/skills/java/SKILL.md +183 -0
- package/plugins/devflow-java/skills/java/references/detection.md +120 -0
- package/plugins/devflow-java/skills/java/references/modern-java.md +270 -0
- package/plugins/devflow-java/skills/java/references/patterns.md +235 -0
- package/plugins/devflow-java/skills/java/references/violations.md +213 -0
- package/plugins/devflow-python/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-python/skills/python/SKILL.md +188 -0
- package/plugins/devflow-python/skills/python/references/async.md +220 -0
- package/plugins/devflow-python/skills/python/references/detection.md +128 -0
- package/plugins/devflow-python/skills/python/references/patterns.md +226 -0
- package/plugins/devflow-python/skills/python/references/violations.md +204 -0
- package/plugins/devflow-react/.claude-plugin/plugin.json +15 -0
- package/plugins/{devflow-core-skills → devflow-react}/skills/react/SKILL.md +1 -1
- package/plugins/{devflow-core-skills → devflow-react}/skills/react/references/patterns.md +3 -3
- package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-rust/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-rust/skills/rust/SKILL.md +193 -0
- package/plugins/devflow-rust/skills/rust/references/detection.md +131 -0
- package/plugins/devflow-rust/skills/rust/references/ownership.md +242 -0
- package/plugins/devflow-rust/skills/rust/references/patterns.md +210 -0
- package/plugins/devflow-rust/skills/rust/references/violations.md +191 -0
- package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-typescript/.claude-plugin/plugin.json +15 -0
- package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/patterns.md +3 -3
- package/shared/agents/coder.md +11 -6
- package/shared/agents/reviewer.md +8 -0
- package/shared/skills/ambient-router/SKILL.md +1 -1
- package/shared/skills/ambient-router/references/skill-catalog.md +4 -0
- package/shared/skills/go/SKILL.md +187 -0
- package/shared/skills/go/references/concurrency.md +312 -0
- package/shared/skills/go/references/detection.md +129 -0
- package/shared/skills/go/references/patterns.md +232 -0
- package/shared/skills/go/references/violations.md +205 -0
- package/shared/skills/java/SKILL.md +183 -0
- package/shared/skills/java/references/detection.md +120 -0
- package/shared/skills/java/references/modern-java.md +270 -0
- package/shared/skills/java/references/patterns.md +235 -0
- package/shared/skills/java/references/violations.md +213 -0
- package/shared/skills/python/SKILL.md +188 -0
- package/shared/skills/python/references/async.md +220 -0
- package/shared/skills/python/references/detection.md +128 -0
- package/shared/skills/python/references/patterns.md +226 -0
- package/shared/skills/python/references/violations.md +204 -0
- package/shared/skills/react/SKILL.md +1 -1
- package/shared/skills/react/references/patterns.md +3 -3
- package/shared/skills/rust/SKILL.md +193 -0
- package/shared/skills/rust/references/detection.md +131 -0
- package/shared/skills/rust/references/ownership.md +242 -0
- package/shared/skills/rust/references/patterns.md +210 -0
- package/shared/skills/rust/references/violations.md +191 -0
- package/shared/skills/typescript/references/patterns.md +3 -3
- package/plugins/devflow-code-review/skills/react/SKILL.md +0 -276
- package/plugins/devflow-code-review/skills/react/references/patterns.md +0 -1331
- package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +0 -229
- package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +0 -171
- package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +0 -670
- package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +0 -419
- package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +0 -254
- package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +0 -184
- package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +0 -511
- package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +0 -453
- package/plugins/devflow-core-skills/skills/react/references/violations.md +0 -565
- package/plugins/devflow-implement/skills/accessibility/SKILL.md +0 -229
- package/plugins/devflow-implement/skills/accessibility/references/detection.md +0 -171
- package/plugins/devflow-implement/skills/accessibility/references/patterns.md +0 -670
- package/plugins/devflow-implement/skills/accessibility/references/violations.md +0 -419
- package/plugins/devflow-implement/skills/frontend-design/SKILL.md +0 -254
- package/plugins/devflow-implement/skills/frontend-design/references/detection.md +0 -184
- package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +0 -511
- package/plugins/devflow-implement/skills/frontend-design/references/violations.md +0 -453
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/SKILL.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/detection.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/patterns.md +0 -0
- /package/plugins/{devflow-code-review → devflow-accessibility}/skills/accessibility/references/violations.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/SKILL.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/detection.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/patterns.md +0 -0
- /package/plugins/{devflow-code-review → devflow-frontend-design}/skills/frontend-design/references/violations.md +0 -0
- /package/plugins/{devflow-code-review → devflow-react}/skills/react/references/violations.md +0 -0
- /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/SKILL.md +0 -0
- /package/plugins/{devflow-core-skills → devflow-typescript}/skills/typescript/references/violations.md +0 -0
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
# Accessibility Violations
|
|
2
|
-
|
|
3
|
-
Extended violation patterns for accessibility reviews. Reference from main SKILL.md.
|
|
4
|
-
|
|
5
|
-
## Keyboard Navigation Violations
|
|
6
|
-
|
|
7
|
-
### No Keyboard Access
|
|
8
|
-
|
|
9
|
-
```tsx
|
|
10
|
-
// VIOLATION: onClick without keyboard equivalent
|
|
11
|
-
<div onClick={handleClick} className="card">
|
|
12
|
-
Click me
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
// VIOLATION: Custom element not focusable
|
|
16
|
-
<span className="link" onClick={() => navigate('/page')}>
|
|
17
|
-
Go to page
|
|
18
|
-
</span>
|
|
19
|
-
|
|
20
|
-
// VIOLATION: Drag-only interaction
|
|
21
|
-
<div
|
|
22
|
-
draggable
|
|
23
|
-
onDragStart={handleDrag}
|
|
24
|
-
onDragEnd={handleDrop}
|
|
25
|
-
>
|
|
26
|
-
Drag me (no keyboard alternative)
|
|
27
|
-
</div>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Missing Focus Management
|
|
31
|
-
|
|
32
|
-
```tsx
|
|
33
|
-
// VIOLATION: Modal doesn't trap focus
|
|
34
|
-
function Modal({ isOpen, children }) {
|
|
35
|
-
return isOpen ? (
|
|
36
|
-
<div className="modal-overlay">
|
|
37
|
-
<div className="modal-content">
|
|
38
|
-
{children}
|
|
39
|
-
<button onClick={onClose}>Close</button>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
) : null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// VIOLATION: Dropdown doesn't return focus on close
|
|
46
|
-
function Dropdown() {
|
|
47
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div>
|
|
51
|
-
<button onClick={() => setIsOpen(true)}>Open</button>
|
|
52
|
-
{isOpen && (
|
|
53
|
-
<ul>
|
|
54
|
-
<li onClick={() => setIsOpen(false)}>Option 1</li>
|
|
55
|
-
{/* Focus lost when dropdown closes */}
|
|
56
|
-
</ul>
|
|
57
|
-
)}
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Poor Focus Visibility
|
|
64
|
-
|
|
65
|
-
```css
|
|
66
|
-
/* VIOLATION: Focus removed entirely */
|
|
67
|
-
*:focus {
|
|
68
|
-
outline: none;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/* VIOLATION: Focus invisible on dark backgrounds */
|
|
72
|
-
button:focus {
|
|
73
|
-
outline: 1px solid #333;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/* VIOLATION: Focus style same as hover */
|
|
77
|
-
button:hover,
|
|
78
|
-
button:focus {
|
|
79
|
-
background: #eee;
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Illogical Tab Order
|
|
84
|
-
|
|
85
|
-
```tsx
|
|
86
|
-
// VIOLATION: tabIndex breaks natural order
|
|
87
|
-
<div>
|
|
88
|
-
<input tabIndex={3} placeholder="Third" />
|
|
89
|
-
<input tabIndex={1} placeholder="First" />
|
|
90
|
-
<input tabIndex={2} placeholder="Second" />
|
|
91
|
-
</div>
|
|
92
|
-
|
|
93
|
-
// VIOLATION: Positive tabIndex on many elements
|
|
94
|
-
<nav>
|
|
95
|
-
<a href="/" tabIndex={1}>Home</a>
|
|
96
|
-
<a href="/about" tabIndex={2}>About</a>
|
|
97
|
-
<a href="/contact" tabIndex={3}>Contact</a>
|
|
98
|
-
</nav>
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## ARIA Violations
|
|
104
|
-
|
|
105
|
-
### Missing Labels
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
// VIOLATION: Icon button without accessible name
|
|
109
|
-
<button onClick={handleClose}>
|
|
110
|
-
<CloseIcon />
|
|
111
|
-
</button>
|
|
112
|
-
|
|
113
|
-
// VIOLATION: Input without label
|
|
114
|
-
<input type="text" placeholder="Search" />
|
|
115
|
-
|
|
116
|
-
// VIOLATION: Image without alt
|
|
117
|
-
<img src="/logo.png" />
|
|
118
|
-
|
|
119
|
-
// VIOLATION: Link without text
|
|
120
|
-
<a href="/profile">
|
|
121
|
-
<Avatar src={user.avatar} />
|
|
122
|
-
</a>
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Incorrect ARIA Usage
|
|
126
|
-
|
|
127
|
-
```tsx
|
|
128
|
-
// VIOLATION: role="button" on already-button element
|
|
129
|
-
<button role="button" onClick={handleClick}>Submit</button>
|
|
130
|
-
|
|
131
|
-
// VIOLATION: aria-hidden on focusable element
|
|
132
|
-
<button aria-hidden="true" onClick={handleClick}>
|
|
133
|
-
Hidden but focusable
|
|
134
|
-
</button>
|
|
135
|
-
|
|
136
|
-
// VIOLATION: Missing required ARIA attributes
|
|
137
|
-
<div role="slider">
|
|
138
|
-
{/* Missing aria-valuenow, aria-valuemin, aria-valuemax */}
|
|
139
|
-
</div>
|
|
140
|
-
|
|
141
|
-
// VIOLATION: aria-label duplicating visible text
|
|
142
|
-
<button aria-label="Submit form">Submit form</button>
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Overuse of ARIA
|
|
146
|
-
|
|
147
|
-
```tsx
|
|
148
|
-
// VIOLATION: ARIA where semantic HTML suffices
|
|
149
|
-
<div role="navigation" aria-label="Main navigation">
|
|
150
|
-
<div role="list">
|
|
151
|
-
<div role="listitem">
|
|
152
|
-
<div role="link" onClick={() => navigate('/')}>Home</div>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
|
|
157
|
-
// Should be:
|
|
158
|
-
<nav aria-label="Main">
|
|
159
|
-
<ul>
|
|
160
|
-
<li><a href="/">Home</a></li>
|
|
161
|
-
</ul>
|
|
162
|
-
</nav>
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## Color and Contrast Violations
|
|
168
|
-
|
|
169
|
-
### Insufficient Contrast
|
|
170
|
-
|
|
171
|
-
```css
|
|
172
|
-
/* VIOLATION: Light gray on white (1.5:1 ratio) */
|
|
173
|
-
.muted-text {
|
|
174
|
-
color: #aaa;
|
|
175
|
-
background: #fff;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/* VIOLATION: Placeholder text too light */
|
|
179
|
-
input::placeholder {
|
|
180
|
-
color: #ccc;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/* VIOLATION: Disabled state invisible */
|
|
184
|
-
button:disabled {
|
|
185
|
-
color: #eee;
|
|
186
|
-
background: #f5f5f5;
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Color-Only Information
|
|
191
|
-
|
|
192
|
-
```tsx
|
|
193
|
-
// VIOLATION: Status only indicated by color
|
|
194
|
-
<span style={{ color: status === 'error' ? 'red' : 'green' }}>
|
|
195
|
-
{status}
|
|
196
|
-
</span>
|
|
197
|
-
|
|
198
|
-
// VIOLATION: Required fields only marked red
|
|
199
|
-
<label style={{ color: required ? 'red' : 'inherit' }}>
|
|
200
|
-
{label}
|
|
201
|
-
</label>
|
|
202
|
-
|
|
203
|
-
// VIOLATION: Chart using only color to differentiate data
|
|
204
|
-
<LineChart>
|
|
205
|
-
<Line stroke="red" data={series1} />
|
|
206
|
-
<Line stroke="blue" data={series2} />
|
|
207
|
-
{/* No pattern, icon, or label differentiation */}
|
|
208
|
-
</LineChart>
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Form Violations
|
|
214
|
-
|
|
215
|
-
### Missing Error Association
|
|
216
|
-
|
|
217
|
-
```tsx
|
|
218
|
-
// VIOLATION: Error not associated with input
|
|
219
|
-
<div>
|
|
220
|
-
<input id="email" type="email" />
|
|
221
|
-
{error && <span className="error">{error}</span>}
|
|
222
|
-
</div>
|
|
223
|
-
|
|
224
|
-
// VIOLATION: Error not announced to screen readers
|
|
225
|
-
<div>
|
|
226
|
-
<input aria-invalid={!!error} />
|
|
227
|
-
{error && <div className="error-message">{error}</div>}
|
|
228
|
-
</div>
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Placeholder as Label
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
// VIOLATION: Placeholder disappears, no persistent label
|
|
235
|
-
<input placeholder="Email address" />
|
|
236
|
-
|
|
237
|
-
// VIOLATION: Floating label without visible label initially
|
|
238
|
-
function FloatingInput({ label }) {
|
|
239
|
-
const [value, setValue] = useState('');
|
|
240
|
-
return (
|
|
241
|
-
<div>
|
|
242
|
-
<input
|
|
243
|
-
value={value}
|
|
244
|
-
onChange={(e) => setValue(e.target.value)}
|
|
245
|
-
/>
|
|
246
|
-
<label className={value ? 'floating' : 'hidden'}>{label}</label>
|
|
247
|
-
</div>
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Form Not Keyboard Navigable
|
|
253
|
-
|
|
254
|
-
```tsx
|
|
255
|
-
// VIOLATION: Custom select not keyboard accessible
|
|
256
|
-
function CustomSelect({ options, value, onChange }) {
|
|
257
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
258
|
-
|
|
259
|
-
return (
|
|
260
|
-
<div className="select" onClick={() => setIsOpen(!isOpen)}>
|
|
261
|
-
<span>{value}</span>
|
|
262
|
-
{isOpen && (
|
|
263
|
-
<ul className="options">
|
|
264
|
-
{options.map(opt => (
|
|
265
|
-
<li onClick={() => onChange(opt)}>{opt}</li>
|
|
266
|
-
))}
|
|
267
|
-
</ul>
|
|
268
|
-
)}
|
|
269
|
-
</div>
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## Motion and Animation Violations
|
|
277
|
-
|
|
278
|
-
### No Reduced Motion Support
|
|
279
|
-
|
|
280
|
-
```css
|
|
281
|
-
/* VIOLATION: Animation ignores user preference */
|
|
282
|
-
.hero {
|
|
283
|
-
animation: slideIn 1s ease-in-out;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
@keyframes slideIn {
|
|
287
|
-
from { transform: translateY(100%); }
|
|
288
|
-
to { transform: translateY(0); }
|
|
289
|
-
}
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Autoplay Without Pause
|
|
293
|
-
|
|
294
|
-
```tsx
|
|
295
|
-
// VIOLATION: Video autoplays without pause control
|
|
296
|
-
<video autoPlay loop muted>
|
|
297
|
-
<source src="/background.mp4" />
|
|
298
|
-
</video>
|
|
299
|
-
|
|
300
|
-
// VIOLATION: Carousel auto-advances without pause
|
|
301
|
-
function Carousel({ slides }) {
|
|
302
|
-
useEffect(() => {
|
|
303
|
-
const interval = setInterval(nextSlide, 3000);
|
|
304
|
-
return () => clearInterval(interval);
|
|
305
|
-
}, []);
|
|
306
|
-
// No pause on hover or focus
|
|
307
|
-
}
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### Flashing Content
|
|
311
|
-
|
|
312
|
-
```css
|
|
313
|
-
/* VIOLATION: Flash rate > 3 per second */
|
|
314
|
-
@keyframes flash {
|
|
315
|
-
0%, 100% { opacity: 1; }
|
|
316
|
-
50% { opacity: 0; }
|
|
317
|
-
}
|
|
318
|
-
.alert {
|
|
319
|
-
animation: flash 0.2s infinite;
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
325
|
-
## Touch Target Violations
|
|
326
|
-
|
|
327
|
-
### Small Touch Targets
|
|
328
|
-
|
|
329
|
-
```css
|
|
330
|
-
/* VIOLATION: Icon buttons too small */
|
|
331
|
-
.icon-btn {
|
|
332
|
-
width: 24px;
|
|
333
|
-
height: 24px;
|
|
334
|
-
padding: 4px;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/* VIOLATION: Inline links with no padding */
|
|
338
|
-
.inline-link {
|
|
339
|
-
/* Natural text height only */
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/* VIOLATION: Close button in corner */
|
|
343
|
-
.modal-close {
|
|
344
|
-
position: absolute;
|
|
345
|
-
top: 4px;
|
|
346
|
-
right: 4px;
|
|
347
|
-
width: 16px;
|
|
348
|
-
height: 16px;
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Targets Too Close Together
|
|
353
|
-
|
|
354
|
-
```tsx
|
|
355
|
-
// VIOLATION: Adjacent small targets
|
|
356
|
-
<div className="button-group">
|
|
357
|
-
<button className="icon-btn">A</button>
|
|
358
|
-
<button className="icon-btn">B</button>
|
|
359
|
-
<button className="icon-btn">C</button>
|
|
360
|
-
{/* No spacing between 24px buttons */}
|
|
361
|
-
</div>
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## Screen Reader Violations
|
|
367
|
-
|
|
368
|
-
### Hidden Important Content
|
|
369
|
-
|
|
370
|
-
```tsx
|
|
371
|
-
// VIOLATION: Visually hidden but important content
|
|
372
|
-
<span className="sr-only">
|
|
373
|
-
Loading... {/* Never announced because sr-only wrong implementation */}
|
|
374
|
-
</span>
|
|
375
|
-
|
|
376
|
-
// VIOLATION: aria-hidden on important element
|
|
377
|
-
<main aria-hidden="true">
|
|
378
|
-
{/* Page content hidden from AT */}
|
|
379
|
-
</main>
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
### Meaningless Link Text
|
|
383
|
-
|
|
384
|
-
```tsx
|
|
385
|
-
// VIOLATION: Generic link text
|
|
386
|
-
<p>
|
|
387
|
-
To learn more about our services, <a href="/services">click here</a>.
|
|
388
|
-
</p>
|
|
389
|
-
|
|
390
|
-
// VIOLATION: Repeated "Read more" links
|
|
391
|
-
{posts.map(post => (
|
|
392
|
-
<article>
|
|
393
|
-
<h2>{post.title}</h2>
|
|
394
|
-
<p>{post.excerpt}</p>
|
|
395
|
-
<a href={post.url}>Read more</a>
|
|
396
|
-
</article>
|
|
397
|
-
))}
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
### Missing Page Structure
|
|
401
|
-
|
|
402
|
-
```tsx
|
|
403
|
-
// VIOLATION: No landmark regions
|
|
404
|
-
function App() {
|
|
405
|
-
return (
|
|
406
|
-
<div>
|
|
407
|
-
<div className="header">...</div>
|
|
408
|
-
<div className="sidebar">...</div>
|
|
409
|
-
<div className="content">...</div>
|
|
410
|
-
<div className="footer">...</div>
|
|
411
|
-
</div>
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// VIOLATION: Skipped heading levels
|
|
416
|
-
<h1>Page Title</h1>
|
|
417
|
-
<h3>Section</h3> {/* h2 skipped */}
|
|
418
|
-
<h5>Subsection</h5> {/* h4 skipped */}
|
|
419
|
-
```
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: frontend-design
|
|
3
|
-
description: This skill should be used when the user asks to "design a component", "pick colors", "improve typography", "fix spacing", "choose a layout", or discusses visual design, CSS, styling decisions, or responsive interfaces. Provides patterns for typography scales, color systems, spacing, and production-grade UI design.
|
|
4
|
-
user-invocable: false
|
|
5
|
-
allowed-tools: Read, Grep, Glob
|
|
6
|
-
activation:
|
|
7
|
-
file-patterns:
|
|
8
|
-
- "**/*.tsx"
|
|
9
|
-
- "**/*.jsx"
|
|
10
|
-
- "**/*.css"
|
|
11
|
-
- "**/*.scss"
|
|
12
|
-
- "**/tailwind.config.*"
|
|
13
|
-
exclude:
|
|
14
|
-
- "node_modules/**"
|
|
15
|
-
- "**/*.test.*"
|
|
16
|
-
- "**/*.spec.*"
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
# Frontend Design Patterns
|
|
20
|
-
|
|
21
|
-
Reference for intentional visual design, following Anthropic's 4 Dimensions framework. Focus on deliberate aesthetic choices over default slop.
|
|
22
|
-
|
|
23
|
-
## Iron Law
|
|
24
|
-
|
|
25
|
-
> **AESTHETICS MUST HAVE INTENT**
|
|
26
|
-
>
|
|
27
|
-
> Every visual choice must be justified. Default styles, copied gradients, and
|
|
28
|
-
> "looks modern" are not justifications. If you cannot explain why a specific
|
|
29
|
-
> font, color, or animation exists, it's design debt. Good design is invisible
|
|
30
|
-
> because it serves purpose, not because it copies trends.
|
|
31
|
-
|
|
32
|
-
## When This Skill Activates
|
|
33
|
-
|
|
34
|
-
- Creating or styling UI components
|
|
35
|
-
- Reviewing CSS, Tailwind, or styled-components
|
|
36
|
-
- Discussing typography, color schemes, or layouts
|
|
37
|
-
- Building design systems or component libraries
|
|
38
|
-
- Evaluating visual consistency
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 1. Typography Intent
|
|
43
|
-
|
|
44
|
-
### Font Personality Must Match Product
|
|
45
|
-
|
|
46
|
-
```css
|
|
47
|
-
/* CORRECT: Deliberate choice with rationale */
|
|
48
|
-
/* Product: Developer documentation - needs readability */
|
|
49
|
-
font-family: 'IBM Plex Mono', 'JetBrains Mono', monospace;
|
|
50
|
-
|
|
51
|
-
/* VIOLATION: Inter because "everyone uses it" */
|
|
52
|
-
font-family: 'Inter', sans-serif; /* Why? What does it communicate? */
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Clear Hierarchy
|
|
56
|
-
|
|
57
|
-
```css
|
|
58
|
-
/* CORRECT: Distinct visual hierarchy */
|
|
59
|
-
.heading-1 { font-size: 2.5rem; font-weight: 700; letter-spacing: -0.02em; }
|
|
60
|
-
.heading-2 { font-size: 1.75rem; font-weight: 600; letter-spacing: -0.01em; }
|
|
61
|
-
.body { font-size: 1rem; font-weight: 400; line-height: 1.6; }
|
|
62
|
-
.caption { font-size: 0.875rem; font-weight: 400; color: var(--text-muted); }
|
|
63
|
-
|
|
64
|
-
/* VIOLATION: No hierarchy - everything similar */
|
|
65
|
-
.text { font-size: 1rem; }
|
|
66
|
-
.text-big { font-size: 1.1rem; }
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Line Height Tuning
|
|
70
|
-
|
|
71
|
-
```css
|
|
72
|
-
/* CORRECT: Context-appropriate line height */
|
|
73
|
-
.heading { line-height: 1.2; } /* Tight for short headings */
|
|
74
|
-
.body { line-height: 1.6; } /* Comfortable for reading */
|
|
75
|
-
.code { line-height: 1.4; } /* Balanced for code */
|
|
76
|
-
|
|
77
|
-
/* VIOLATION: Universal line height */
|
|
78
|
-
* { line-height: 1.5; }
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## 2. Color and Theme
|
|
84
|
-
|
|
85
|
-
### Deliberate Palette
|
|
86
|
-
|
|
87
|
-
```css
|
|
88
|
-
/* CORRECT: Semantic color system with clear purpose */
|
|
89
|
-
:root {
|
|
90
|
-
--color-primary: #0066cc; /* Actions, links - trust/stability */
|
|
91
|
-
--color-success: #0a6640; /* Positive outcomes */
|
|
92
|
-
--color-warning: #b35900; /* Attention needed */
|
|
93
|
-
--color-error: #c41e3a; /* Errors, destructive */
|
|
94
|
-
--color-neutral-900: #1a1a1a; /* Primary text */
|
|
95
|
-
--color-neutral-500: #6b7280; /* Secondary text */
|
|
96
|
-
--color-neutral-100: #f5f5f5; /* Backgrounds */
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* VIOLATION: Random hex values without system */
|
|
100
|
-
.button { background: #4f46e5; }
|
|
101
|
-
.link { color: #3b82f6; }
|
|
102
|
-
.alert { background: #ef4444; }
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Light/Dark as First-Class
|
|
106
|
-
|
|
107
|
-
```css
|
|
108
|
-
/* CORRECT: Design for both modes intentionally */
|
|
109
|
-
:root {
|
|
110
|
-
--bg-primary: #ffffff;
|
|
111
|
-
--text-primary: #1a1a1a;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@media (prefers-color-scheme: dark) {
|
|
115
|
-
:root {
|
|
116
|
-
--bg-primary: #0f0f0f;
|
|
117
|
-
--text-primary: #f5f5f5;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/* VIOLATION: Dark mode as afterthought */
|
|
122
|
-
.dark-mode { filter: invert(1); }
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## 3. Motion and Animation
|
|
128
|
-
|
|
129
|
-
### State Communication
|
|
130
|
-
|
|
131
|
-
```css
|
|
132
|
-
/* CORRECT: Animation communicates state change */
|
|
133
|
-
.button {
|
|
134
|
-
transition: transform 0.1s ease-out, background 0.15s ease;
|
|
135
|
-
}
|
|
136
|
-
.button:active {
|
|
137
|
-
transform: scale(0.98); /* Feedback: "I received your click" */
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/* VIOLATION: Animation for decoration */
|
|
141
|
-
.button {
|
|
142
|
-
animation: pulse 2s infinite; /* Why is it pulsing? */
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Consistent Timing
|
|
147
|
-
|
|
148
|
-
```css
|
|
149
|
-
/* CORRECT: Timing scale for consistency */
|
|
150
|
-
:root {
|
|
151
|
-
--duration-fast: 100ms; /* Micro-interactions */
|
|
152
|
-
--duration-normal: 200ms; /* Standard transitions */
|
|
153
|
-
--duration-slow: 300ms; /* Complex animations */
|
|
154
|
-
--easing-default: cubic-bezier(0.4, 0, 0.2, 1);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/* VIOLATION: Random durations */
|
|
158
|
-
.modal { transition: 0.35s; }
|
|
159
|
-
.dropdown { transition: 0.2s; }
|
|
160
|
-
.tooltip { transition: 0.15s; }
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
### Appropriate Duration
|
|
164
|
-
|
|
165
|
-
| Element | Duration | Rationale |
|
|
166
|
-
|---------|----------|-----------|
|
|
167
|
-
| Hover states | 100-150ms | Immediate feedback |
|
|
168
|
-
| Dropdowns | 150-200ms | Quick but perceptible |
|
|
169
|
-
| Modals | 200-300ms | Significant context change |
|
|
170
|
-
| Page transitions | 300-500ms | Major navigation |
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
## 4. Spatial Composition
|
|
175
|
-
|
|
176
|
-
### Consistent Spacing Scale
|
|
177
|
-
|
|
178
|
-
```css
|
|
179
|
-
/* CORRECT: Mathematical spacing system */
|
|
180
|
-
:root {
|
|
181
|
-
--space-1: 0.25rem; /* 4px */
|
|
182
|
-
--space-2: 0.5rem; /* 8px */
|
|
183
|
-
--space-3: 0.75rem; /* 12px */
|
|
184
|
-
--space-4: 1rem; /* 16px */
|
|
185
|
-
--space-6: 1.5rem; /* 24px */
|
|
186
|
-
--space-8: 2rem; /* 32px */
|
|
187
|
-
--space-12: 3rem; /* 48px */
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/* VIOLATION: Magic numbers */
|
|
191
|
-
.card { padding: 18px 22px; margin-bottom: 13px; }
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Whitespace With Purpose
|
|
195
|
-
|
|
196
|
-
```css
|
|
197
|
-
/* CORRECT: Whitespace creates visual grouping */
|
|
198
|
-
.section { margin-bottom: var(--space-12); }
|
|
199
|
-
.section-header { margin-bottom: var(--space-6); }
|
|
200
|
-
.paragraph { margin-bottom: var(--space-4); }
|
|
201
|
-
|
|
202
|
-
/* VIOLATION: Uniform spacing (no hierarchy) */
|
|
203
|
-
* + * { margin-top: 1rem; }
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## AI Slop Detection
|
|
209
|
-
|
|
210
|
-
Flag these patterns - they indicate thoughtless defaults:
|
|
211
|
-
|
|
212
|
-
| Pattern | Problem |
|
|
213
|
-
|---------|---------|
|
|
214
|
-
| Purple-to-pink gradient | Copied from templates without brand justification |
|
|
215
|
-
| `font-family: Inter` without rationale | Default choice, not intentional |
|
|
216
|
-
| Everything centered | No visual hierarchy or flow |
|
|
217
|
-
| `rounded-xl` on everything | Border radius should vary by context |
|
|
218
|
-
| Shadows on everything | Elevation should be meaningful |
|
|
219
|
-
| Generic "hero section" with gradient | Template copy, not designed |
|
|
220
|
-
| `animate-pulse` on buttons | Meaningless attention grab |
|
|
221
|
-
| Glassmorphism everywhere | Trend following, not purpose |
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## Extended References
|
|
226
|
-
|
|
227
|
-
For additional patterns and examples:
|
|
228
|
-
- `references/violations.md` - Extended design anti-patterns
|
|
229
|
-
- `references/patterns.md` - Extended correct patterns
|
|
230
|
-
- `references/detection.md` - Grep patterns for finding issues
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
## Severity Guidelines
|
|
235
|
-
|
|
236
|
-
| Severity | Criteria |
|
|
237
|
-
|----------|----------|
|
|
238
|
-
| CRITICAL | No design system (random values everywhere) |
|
|
239
|
-
| HIGH | Inconsistent spacing/typography, broken dark mode |
|
|
240
|
-
| MEDIUM | Missing hover states, poor visual hierarchy |
|
|
241
|
-
| LOW | Could improve animation timing, minor inconsistencies |
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## Checklist
|
|
246
|
-
|
|
247
|
-
- [ ] Typography choices have documented rationale
|
|
248
|
-
- [ ] Color palette is semantic (not arbitrary hex)
|
|
249
|
-
- [ ] Dark/light modes both intentionally designed
|
|
250
|
-
- [ ] Spacing follows consistent scale
|
|
251
|
-
- [ ] Animations communicate state (not decoration)
|
|
252
|
-
- [ ] No "AI slop" patterns present
|
|
253
|
-
- [ ] Visual hierarchy is clear
|
|
254
|
-
- [ ] Responsive behavior is intentional
|