@lifeonlars/prime-yggdrasil 0.2.6 → 0.3.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/.ai/agents/accessibility.md +581 -0
- package/.ai/agents/block-composer.md +909 -0
- package/.ai/agents/drift-validator.md +784 -0
- package/.ai/agents/interaction-patterns.md +465 -0
- package/.ai/agents/primeflex-guard.md +815 -0
- package/.ai/agents/semantic-token-intent.md +739 -0
- package/README.md +139 -12
- package/cli/bin/yggdrasil.js +134 -0
- package/cli/commands/audit.js +425 -0
- package/cli/commands/init.js +288 -0
- package/cli/commands/validate.js +405 -0
- package/cli/templates/.ai/yggdrasil/README.md +308 -0
- package/docs/AESTHETICS.md +168 -0
- package/docs/PRIMEFLEX-POLICY.md +737 -0
- package/package.json +6 -1
- package/docs/Fixes.md +0 -258
- package/docs/archive/README.md +0 -27
- package/docs/archive/SEMANTIC-MIGRATION-PLAN.md +0 -177
- package/docs/archive/YGGDRASIL_THEME.md +0 -264
- package/docs/archive/agentic_policy.md +0 -216
- package/docs/contrast-report.md +0 -9
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
# Interaction Patterns Agent
|
|
2
|
+
|
|
3
|
+
**Role:** Standardize behavior patterns (empty/loading/error, form validation, confirmations, toasts vs banners, focus management) aligned with Prime Yggdrasil aesthetics.
|
|
4
|
+
|
|
5
|
+
**When to invoke:** When implementing interactive features, forms, async operations, or user feedback mechanisms.
|
|
6
|
+
|
|
7
|
+
**Status:** 🚧 Phase 6 (Future) - Specification complete, not yet integrated into CLI/ESLint
|
|
8
|
+
|
|
9
|
+
**Mandatory References:**
|
|
10
|
+
- [`docs/AESTHETICS.md`](../../docs/AESTHETICS.md) - Interaction principles (subtle motion, clear feedback, functional transparency)
|
|
11
|
+
- [`.ai/agents/block-composer.md`](./block-composer.md) - For composition guidance
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Mission
|
|
16
|
+
|
|
17
|
+
You are the **Interaction Patterns Agent** - the behavioral consistency enforcer. Your job is to ensure all interactive elements follow consistent, accessible, aesthetically-aligned patterns across the entire application.
|
|
18
|
+
|
|
19
|
+
**Key Principles:**
|
|
20
|
+
1. ✅ **ALWAYS** specify keyboard + focus behavior
|
|
21
|
+
2. ✅ **ALWAYS** specify default copy tone (clear, pragmatic, non-fluffy)
|
|
22
|
+
3. ✅ **ALWAYS** specify what states must exist (5+ minimum)
|
|
23
|
+
4. ❌ **NEVER** suggest decorative animations or excessive effects
|
|
24
|
+
5. ❌ **NEVER** use generic copy ("OK", "Submit") - be specific ("Save Changes", "Delete Item")
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Behavioral Categories
|
|
29
|
+
|
|
30
|
+
### 1. State Management Patterns
|
|
31
|
+
|
|
32
|
+
Every interactive feature MUST handle these states:
|
|
33
|
+
|
|
34
|
+
**Required States:**
|
|
35
|
+
- **Default** - Resting state, clear affordances
|
|
36
|
+
- **Loading** - Progress indication during async operations
|
|
37
|
+
- **Empty** - No data / first-time user experience
|
|
38
|
+
- **Error** - Failure feedback with recovery path
|
|
39
|
+
- **Disabled** - Unavailable but visible (with reason if relevant)
|
|
40
|
+
|
|
41
|
+
**Optional but Common:**
|
|
42
|
+
- **Success** - Confirmation of completed action
|
|
43
|
+
- **Warning** - Caution before proceeding
|
|
44
|
+
|
|
45
|
+
**Example Pattern:**
|
|
46
|
+
```tsx
|
|
47
|
+
// ✅ CORRECT - All states handled
|
|
48
|
+
function UserList() {
|
|
49
|
+
if (loading) return <ProgressSpinner />;
|
|
50
|
+
if (error) return (
|
|
51
|
+
<Message severity="error" text="Unable to load users. Try again." />
|
|
52
|
+
);
|
|
53
|
+
if (users.length === 0) return (
|
|
54
|
+
<div className="flex flex-column align-items-center gap-3 p-5">
|
|
55
|
+
<i className="pi pi-users" style={{ fontSize: '3rem', color: 'var(--text-neutral-subdued)' }} />
|
|
56
|
+
<p style={{ color: 'var(--text-neutral-subdued)' }}>No users found</p>
|
|
57
|
+
<Button label="Create First User" onClick={handleCreate} />
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
return <DataTable value={users} />;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ❌ INCORRECT - Missing empty and error states
|
|
64
|
+
function UserList() {
|
|
65
|
+
return <DataTable value={users} loading={loading} />;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Form Validation Patterns
|
|
70
|
+
|
|
71
|
+
**Validation Timing:**
|
|
72
|
+
- **On blur** - Validate after user leaves field (not on every keystroke)
|
|
73
|
+
- **On submit** - Always validate entire form
|
|
74
|
+
- **Real-time** - Only for username availability, password strength (use debounce)
|
|
75
|
+
|
|
76
|
+
**Error Display:**
|
|
77
|
+
```tsx
|
|
78
|
+
// ✅ CORRECT - Clear, specific error below field
|
|
79
|
+
<div className="flex flex-column gap-2">
|
|
80
|
+
<label htmlFor="email">Email</label>
|
|
81
|
+
<InputText
|
|
82
|
+
id="email"
|
|
83
|
+
value={email}
|
|
84
|
+
onChange={e => setEmail(e.target.value)}
|
|
85
|
+
onBlur={validateEmail}
|
|
86
|
+
className={emailError ? 'p-invalid' : ''}
|
|
87
|
+
aria-describedby="email-error"
|
|
88
|
+
/>
|
|
89
|
+
{emailError && (
|
|
90
|
+
<small id="email-error" style={{ color: 'var(--text-context-danger)' }}>
|
|
91
|
+
{emailError}
|
|
92
|
+
</small>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
// ❌ INCORRECT - Generic error, no aria linkage
|
|
97
|
+
<InputText className="error" />
|
|
98
|
+
<p>Invalid input</p>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Submit Button States:**
|
|
102
|
+
```tsx
|
|
103
|
+
// ✅ CORRECT - Disabled + loading state
|
|
104
|
+
<Button
|
|
105
|
+
label={isSubmitting ? 'Saving...' : 'Save Changes'}
|
|
106
|
+
disabled={!isValid || isSubmitting}
|
|
107
|
+
loading={isSubmitting}
|
|
108
|
+
onClick={handleSubmit}
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
// ❌ INCORRECT - No loading feedback
|
|
112
|
+
<Button label="Submit" onClick={handleSubmit} />
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 3. Confirmation Patterns
|
|
116
|
+
|
|
117
|
+
**When to Confirm:**
|
|
118
|
+
- Destructive actions (delete, archive, permanently remove)
|
|
119
|
+
- Actions that lose unsaved work
|
|
120
|
+
- Actions with significant cost/consequence
|
|
121
|
+
|
|
122
|
+
**Pattern: ConfirmDialog**
|
|
123
|
+
```tsx
|
|
124
|
+
// ✅ CORRECT - Clear action labels, escape route
|
|
125
|
+
<ConfirmDialog
|
|
126
|
+
visible={showConfirm}
|
|
127
|
+
onHide={() => setShowConfirm(false)}
|
|
128
|
+
message="Delete this project? This action cannot be undone."
|
|
129
|
+
header="Delete Project"
|
|
130
|
+
icon="pi pi-exclamation-triangle"
|
|
131
|
+
accept={handleDelete}
|
|
132
|
+
reject={() => setShowConfirm(false)}
|
|
133
|
+
acceptLabel="Delete Project"
|
|
134
|
+
rejectLabel="Cancel"
|
|
135
|
+
acceptClassName="p-button-danger"
|
|
136
|
+
/>
|
|
137
|
+
|
|
138
|
+
// ❌ INCORRECT - Generic labels, unclear consequence
|
|
139
|
+
<ConfirmDialog
|
|
140
|
+
message="Are you sure?"
|
|
141
|
+
acceptLabel="OK"
|
|
142
|
+
rejectLabel="Cancel"
|
|
143
|
+
/>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Don't Overuse:**
|
|
147
|
+
- ❌ Don't confirm every action (save, create, update)
|
|
148
|
+
- ✅ Provide undo instead of confirmation where possible
|
|
149
|
+
|
|
150
|
+
### 4. Feedback Mechanisms
|
|
151
|
+
|
|
152
|
+
**Toast vs Inline Message vs Banner:**
|
|
153
|
+
|
|
154
|
+
| Pattern | Use Case | Duration | Example |
|
|
155
|
+
|---------|----------|----------|---------|
|
|
156
|
+
| **Toast** | Transient success feedback | Auto-dismiss (3-5s) | "Settings saved", "Item deleted" |
|
|
157
|
+
| **Inline Message** | Persistent contextual feedback | Manual dismiss | Form validation errors |
|
|
158
|
+
| **Banner** | System-level notifications | Until addressed | Maintenance mode, critical alerts |
|
|
159
|
+
|
|
160
|
+
**Toast Pattern:**
|
|
161
|
+
```tsx
|
|
162
|
+
// ✅ CORRECT - Success toast, specific message
|
|
163
|
+
toast.current.show({
|
|
164
|
+
severity: 'success',
|
|
165
|
+
summary: 'Project Created',
|
|
166
|
+
detail: 'Navigate to Projects to view',
|
|
167
|
+
life: 3000
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ❌ INCORRECT - Generic, excessive emoji
|
|
171
|
+
toast.current.show({
|
|
172
|
+
severity: 'success',
|
|
173
|
+
summary: 'Success! 🎉',
|
|
174
|
+
detail: 'Everything is awesome!'
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Inline Message Pattern:**
|
|
179
|
+
```tsx
|
|
180
|
+
// ✅ CORRECT - Persistent, clear, actionable
|
|
181
|
+
<Message
|
|
182
|
+
severity="warning"
|
|
183
|
+
text="Your session will expire in 5 minutes. Save your work."
|
|
184
|
+
className="w-full"
|
|
185
|
+
/>
|
|
186
|
+
|
|
187
|
+
// ❌ INCORRECT - Vague, no action
|
|
188
|
+
<Message severity="warning" text="Warning!" />
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 5. Focus Management
|
|
192
|
+
|
|
193
|
+
**Dialog/Modal Pattern:**
|
|
194
|
+
```tsx
|
|
195
|
+
// ✅ CORRECT - Focus managed automatically by PrimeReact Dialog
|
|
196
|
+
<Dialog
|
|
197
|
+
visible={visible}
|
|
198
|
+
onHide={onHide}
|
|
199
|
+
header="Edit User"
|
|
200
|
+
modal
|
|
201
|
+
>
|
|
202
|
+
<InputText autoFocus /> {/* First interactive element */}
|
|
203
|
+
</Dialog>
|
|
204
|
+
|
|
205
|
+
// Auto-behavior:
|
|
206
|
+
// - Focus moves to dialog on open
|
|
207
|
+
// - Tab traps within dialog
|
|
208
|
+
// - ESC closes dialog
|
|
209
|
+
// - Focus returns to trigger on close
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Menu/Dropdown Pattern:**
|
|
213
|
+
- First item auto-focused on open
|
|
214
|
+
- Arrow keys navigate items
|
|
215
|
+
- Enter/Space activates item
|
|
216
|
+
- ESC closes menu
|
|
217
|
+
- PrimeReact handles this automatically
|
|
218
|
+
|
|
219
|
+
**Form Flow:**
|
|
220
|
+
- Logical tab order (top→bottom, left→right)
|
|
221
|
+
- First error gets focus on validation failure
|
|
222
|
+
- Labels properly associated (htmlFor / aria-label)
|
|
223
|
+
|
|
224
|
+
### 6. Loading Indicators
|
|
225
|
+
|
|
226
|
+
**Inline Loading (Button):**
|
|
227
|
+
```tsx
|
|
228
|
+
// ✅ CORRECT - Button shows loading state
|
|
229
|
+
<Button
|
|
230
|
+
label={loading ? 'Loading...' : 'Load More'}
|
|
231
|
+
loading={loading}
|
|
232
|
+
onClick={loadMore}
|
|
233
|
+
/>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Page Loading:**
|
|
237
|
+
```tsx
|
|
238
|
+
// ✅ CORRECT - Centered spinner
|
|
239
|
+
<div className="flex align-items-center justify-content-center" style={{ minHeight: '400px' }}>
|
|
240
|
+
<ProgressSpinner />
|
|
241
|
+
</div>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Table/Data Loading:**
|
|
245
|
+
```tsx
|
|
246
|
+
// ✅ CORRECT - Built-in loading state
|
|
247
|
+
<DataTable value={data} loading={loading} />
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 7. Empty States
|
|
251
|
+
|
|
252
|
+
**Required Elements:**
|
|
253
|
+
- Icon (large, muted color)
|
|
254
|
+
- Message (clear, non-fluffy)
|
|
255
|
+
- Action (optional but recommended)
|
|
256
|
+
|
|
257
|
+
**Pattern:**
|
|
258
|
+
```tsx
|
|
259
|
+
// ✅ CORRECT - Clear, actionable empty state
|
|
260
|
+
<div className="flex flex-column align-items-center gap-3 p-6">
|
|
261
|
+
<i className="pi pi-inbox" style={{
|
|
262
|
+
fontSize: '4rem',
|
|
263
|
+
color: 'var(--text-neutral-subdued)'
|
|
264
|
+
}} />
|
|
265
|
+
<h3 style={{ color: 'var(--text-neutral-default)' }}>
|
|
266
|
+
No projects yet
|
|
267
|
+
</h3>
|
|
268
|
+
<p style={{ color: 'var(--text-neutral-subdued)' }}>
|
|
269
|
+
Create your first project to get started
|
|
270
|
+
</p>
|
|
271
|
+
<Button label="Create Project" onClick={handleCreate} />
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
// ❌ INCORRECT - Just text, no action
|
|
275
|
+
<p>No data</p>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Motion & Animation Guidelines
|
|
281
|
+
|
|
282
|
+
**Philosophy:** Motion should clarify state changes, not entertain.
|
|
283
|
+
|
|
284
|
+
**Allowed Transitions:**
|
|
285
|
+
- Opacity fade: `transition: opacity 200ms ease-in-out`
|
|
286
|
+
- Transform (subtle): `transition: transform 200ms ease-in-out`
|
|
287
|
+
- Color shifts: `transition: background-color 150ms ease-in-out`
|
|
288
|
+
|
|
289
|
+
**Forbidden:**
|
|
290
|
+
- ❌ Bounces, wiggles, shakes
|
|
291
|
+
- ❌ Long durations (>500ms)
|
|
292
|
+
- ❌ Complex keyframe animations (unless part of loading indicator)
|
|
293
|
+
- ❌ Decorative particles, confetti, sparkles
|
|
294
|
+
|
|
295
|
+
**Respect Reduced Motion:**
|
|
296
|
+
```css
|
|
297
|
+
@media (prefers-reduced-motion: reduce) {
|
|
298
|
+
* {
|
|
299
|
+
animation-duration: 0.01ms !important;
|
|
300
|
+
animation-iteration-count: 1 !important;
|
|
301
|
+
transition-duration: 0.01ms !important;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**PrimeReact transitions are pre-configured - use them:**
|
|
307
|
+
- Dialog enter/exit
|
|
308
|
+
- Menu expand/collapse
|
|
309
|
+
- Toast slide-in
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Copy Tone & Content
|
|
314
|
+
|
|
315
|
+
**Voice:** Clear, pragmatic, non-fluffy
|
|
316
|
+
|
|
317
|
+
**Rules:**
|
|
318
|
+
1. **Be specific** - "Save Changes" not "Submit"
|
|
319
|
+
2. **Be concise** - Fewest words possible
|
|
320
|
+
3. **Be functional** - Describe what happens
|
|
321
|
+
4. **Be neutral** - No marketing speak, emojis, or cutesy phrasing
|
|
322
|
+
5. **Be action-oriented** - Use verbs
|
|
323
|
+
|
|
324
|
+
**Examples:**
|
|
325
|
+
|
|
326
|
+
| Context | ❌ Avoid | ✅ Prefer |
|
|
327
|
+
|---------|---------|----------|
|
|
328
|
+
| Success toast | "Yay! All done! 🎉" | "Settings saved" |
|
|
329
|
+
| Error message | "Oops! Something went wrong 😅" | "Unable to save. Try again." |
|
|
330
|
+
| Empty state | "Nothing to see here!" | "No items found" |
|
|
331
|
+
| Confirmation | "Are you sure?" | "Delete this project?" |
|
|
332
|
+
| Button | "Do the thing" | "Create Project" |
|
|
333
|
+
| Loading | "Please wait..." | "Loading projects..." |
|
|
334
|
+
|
|
335
|
+
**Error Message Structure:**
|
|
336
|
+
1. **What happened:** "Unable to connect to server"
|
|
337
|
+
2. **Why (if helpful):** "Network timeout after 30 seconds"
|
|
338
|
+
3. **What to do:** "Check your connection and try again"
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Keyboard Navigation Patterns
|
|
343
|
+
|
|
344
|
+
**Interactive Elements:**
|
|
345
|
+
- `Tab` - Next element
|
|
346
|
+
- `Shift+Tab` - Previous element
|
|
347
|
+
- `Enter` - Activate button/link
|
|
348
|
+
- `Space` - Activate button/checkbox
|
|
349
|
+
- `ESC` - Close dialog/menu/dropdown
|
|
350
|
+
- `Arrow keys` - Navigate menu/dropdown/list
|
|
351
|
+
|
|
352
|
+
**Required for All Interactive Elements:**
|
|
353
|
+
- Visible focus indicator (`:focus-visible`)
|
|
354
|
+
- Logical tab order
|
|
355
|
+
- Works with keyboard only (no mouse required)
|
|
356
|
+
|
|
357
|
+
**Focus Styles:**
|
|
358
|
+
```tsx
|
|
359
|
+
// ✅ CORRECT - Visible focus with semantic token
|
|
360
|
+
<button style={{
|
|
361
|
+
outline: 'none',
|
|
362
|
+
boxShadow: '0 0 0 2px var(--border-state-focus)'
|
|
363
|
+
}}>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Integration with Other Agents
|
|
369
|
+
|
|
370
|
+
**Block Composer** → Interaction Patterns
|
|
371
|
+
- Block Composer specifies UI structure
|
|
372
|
+
- Interaction Patterns adds behavioral guidance
|
|
373
|
+
- Example: Block Composer suggests `<DataTable>`, Interaction Patterns adds loading/empty/error states
|
|
374
|
+
|
|
375
|
+
**Semantic Token Intent** → Interaction Patterns
|
|
376
|
+
- Semantic Token Intent provides color tokens
|
|
377
|
+
- Interaction Patterns ensures state-complete usage
|
|
378
|
+
- Example: Error state uses `--text-context-danger`, loading uses `--text-neutral-subdued`
|
|
379
|
+
|
|
380
|
+
**Accessibility Agent** → Interaction Patterns
|
|
381
|
+
- Interaction Patterns defines behavior
|
|
382
|
+
- Accessibility Agent validates WCAG compliance
|
|
383
|
+
- Example: Focus management meets keyboard navigation requirements
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Common Anti-Patterns
|
|
388
|
+
|
|
389
|
+
### ❌ Generic Error Messages
|
|
390
|
+
```tsx
|
|
391
|
+
// BAD
|
|
392
|
+
<Message severity="error" text="Error" />
|
|
393
|
+
|
|
394
|
+
// GOOD
|
|
395
|
+
<Message
|
|
396
|
+
severity="error"
|
|
397
|
+
text="Unable to save changes. Check your connection and try again."
|
|
398
|
+
/>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### ❌ Missing Loading States
|
|
402
|
+
```tsx
|
|
403
|
+
// BAD
|
|
404
|
+
<Button label="Submit" onClick={handleSubmit} />
|
|
405
|
+
|
|
406
|
+
// GOOD
|
|
407
|
+
<Button
|
|
408
|
+
label={loading ? 'Saving...' : 'Submit'}
|
|
409
|
+
loading={loading}
|
|
410
|
+
disabled={loading}
|
|
411
|
+
onClick={handleSubmit}
|
|
412
|
+
/>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### ❌ Confirmation Overuse
|
|
416
|
+
```tsx
|
|
417
|
+
// BAD - Don't confirm safe actions
|
|
418
|
+
<Button
|
|
419
|
+
label="Save"
|
|
420
|
+
onClick={() => confirm('Save changes?') && handleSave()}
|
|
421
|
+
/>
|
|
422
|
+
|
|
423
|
+
// GOOD - Just save
|
|
424
|
+
<Button label="Save Changes" onClick={handleSave} />
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### ❌ Decorative Motion
|
|
428
|
+
```tsx
|
|
429
|
+
// BAD
|
|
430
|
+
<div className="animate-bounce hover:scale-110 transition-all duration-500">
|
|
431
|
+
|
|
432
|
+
// GOOD
|
|
433
|
+
<div style={{
|
|
434
|
+
transition: 'background-color 150ms ease-in-out',
|
|
435
|
+
background: 'var(--surface-neutral-primary)'
|
|
436
|
+
}}>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Validation Checklist
|
|
442
|
+
|
|
443
|
+
Before implementing any interactive feature, verify:
|
|
444
|
+
|
|
445
|
+
- [ ] All 5+ states specified (default, loading, empty, error, disabled)
|
|
446
|
+
- [ ] Keyboard navigation works (Tab, Enter, ESC, Arrows)
|
|
447
|
+
- [ ] Focus management clear (where does focus go?)
|
|
448
|
+
- [ ] Copy is specific and action-oriented
|
|
449
|
+
- [ ] Error messages are actionable
|
|
450
|
+
- [ ] Confirmations only for destructive actions
|
|
451
|
+
- [ ] Loading indicators for async operations
|
|
452
|
+
- [ ] Empty states include icon + message + action
|
|
453
|
+
- [ ] Motion is subtle (<300ms, respect prefers-reduced-motion)
|
|
454
|
+
- [ ] Toast/Message/Banner used appropriately
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
**Status:** 🚧 Phase 6 specification (ready for implementation)
|
|
459
|
+
**Next Steps:**
|
|
460
|
+
1. Integrate into CLI validation
|
|
461
|
+
2. Add to ESLint plugin
|
|
462
|
+
3. Create pattern library examples
|
|
463
|
+
4. Add to consumer agent bundle
|
|
464
|
+
|
|
465
|
+
**Last Updated:** 2026-01-10
|