@ericrisco/rsc 3.3.1 → 3.5.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/README.md +3 -3
- package/manifest.json +43 -22
- package/package.json +1 -1
- package/scripts/lib/default-skill-floor.js +5 -1
- package/scripts/lib/domains.js +2 -2
- package/scripts/lib/retired-skills.js +4 -0
- package/scripts/rsc.js +1 -1
- package/skills/design/SKILL.md +4 -3
- package/skills/design/evals/cases.yaml +2 -2
- package/skills/ftd/SKILL.md +1 -1
- package/skills/react/SKILL.md +2 -1
- package/skills/ux/SKILL.md +149 -0
- package/skills/ux/THIRD_PARTY.md +32 -0
- package/skills/ux/evals/cases.yaml +40 -0
- package/skills/ux/references/flows.md +124 -0
- package/skills/ux/upstream/UPSTREAM.json +59 -0
- package/skills/ux/upstream/ux-designer/GUIDE.md +180 -0
- package/skills/ux/upstream/ux-designer/LICENSE +21 -0
- package/skills/ux/upstream/ux-designer/references/01-core-principles.md +251 -0
- package/skills/ux/upstream/ux-designer/references/02-laws-of-ux.md +330 -0
- package/skills/ux/upstream/ux-designer/references/03-accessibility.md +411 -0
- package/skills/ux/upstream/ux-designer/references/04-visual-design.md +433 -0
- package/skills/ux/upstream/ux-designer/references/05-information-architecture.md +432 -0
- package/skills/ux/upstream/ux-designer/references/06-interaction-design.md +495 -0
- package/skills/ux/upstream/ux-designer/references/07-forms-and-inputs.md +491 -0
- package/skills/ux/upstream/ux-designer/references/08-mobile-ux.md +539 -0
- package/skills/ux/upstream/ux-designer/references/09-ux-writing.md +493 -0
- package/skills/ux/upstream/ux-designer/references/10-user-research.md +533 -0
- package/skills/ux/upstream/ux-designer/references/11-design-systems.md +618 -0
- package/skills/ux/upstream/ux-designer/references/12a-presence-awareness.md +395 -0
- package/skills/ux/upstream/ux-designer/references/12b-conflict-resolution-sync.md +420 -0
- package/skills/ux/upstream/ux-designer/references/13a-canvas-navigation.md +388 -0
- package/skills/ux/upstream/ux-designer/references/13b-canvas-objects-performance.md +559 -0
- package/skills/ux/upstream/ux-designer/references/14-ai-ux-patterns.md +511 -0
- package/skills/ux/upstream/ux-designer/references/15-ethical-design.md +419 -0
- package/skills/ux/upstream/ux-designer/references/16-onboarding.md +430 -0
- package/skills/ux/upstream/ux-designer/references/17-notifications.md +461 -0
- package/skills/ux/upstream/ux-designer/references/18-data-visualization.md +453 -0
- package/skills/ux/upstream/ux-designer/references/19-search-ux.md +479 -0
- package/skills/ux/upstream/ux-designer/references/20-emotional-design.md +382 -0
- package/skills/ux/upstream/ux-designer/references/21-data-tables.md +629 -0
- package/skills/ux/upstream/ux-designer/references/22-performance-ux.md +626 -0
- package/skills/ux/upstream/ux-designer/references/23-internationalization.md +347 -0
- package/skills/ux/upstream/ux-designer/references/24-voice-and-multimodal.md +308 -0
- package/skills/ux/upstream/ux-designer/references/25a-barcode-camera-scanning.md +342 -0
- package/skills/ux/upstream/ux-designer/references/25b-barcode-scanner-workflows.md +412 -0
- package/skills/ux/upstream/ux-designer/references/25c-barcode-display.md +277 -0
- package/skills/ux/upstream/ux-usability-foundations/GUIDE.md +285 -0
- package/skills/ux/upstream/ux-usability-foundations/LICENSE +21 -0
- package/skills/ux/upstream/ux-usability-foundations/references/anti-patterns.md +267 -0
- package/skills/ux/upstream/ux-usability-foundations/references/checklists.md +130 -0
- package/skills/ux/upstream/ux-usability-foundations/references/decision-prompts.md +340 -0
- package/skills/ux/upstream/ux-usability-foundations/references/principle-cards.md +449 -0
- package/skills/worktrees/SKILL.md +19 -5
- package/targets/branch-guard.mjs +59 -4
- package/targets/clone-bootstrap.mjs +1 -1
- package/targets/session-memory-adapter.mjs +2 -2
- package/targets/team-safe-start.mjs +1 -0
- package/targets/worktree-reaper.mjs +14 -1
- package/skills/ui-engineering/SKILL.md +0 -113
- package/skills/ui-engineering/evals/cases.yaml +0 -38
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
# Interaction Design
|
|
2
|
+
|
|
3
|
+
Interaction design (IxD) focuses on creating engaging interfaces with well-thought-out behaviors—how the system responds to user actions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- Micro-interactions
|
|
10
|
+
- Feedback States
|
|
11
|
+
- Animation Principles
|
|
12
|
+
- Loading States
|
|
13
|
+
- Gesture Design
|
|
14
|
+
- Transitions
|
|
15
|
+
- Reduced Motion
|
|
16
|
+
- Haptic Feedback
|
|
17
|
+
- 2026 Trends
|
|
18
|
+
- Common Mistakes
|
|
19
|
+
- Sources
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Micro-interactions
|
|
24
|
+
|
|
25
|
+
Small, contained moments that accomplish a single task while enhancing the user experience.
|
|
26
|
+
|
|
27
|
+
### Dan Saffer's Four Components
|
|
28
|
+
|
|
29
|
+
#### 1. Trigger
|
|
30
|
+
What initiates the micro-interaction.
|
|
31
|
+
|
|
32
|
+
**User Triggers:**
|
|
33
|
+
- Click/tap
|
|
34
|
+
- Swipe
|
|
35
|
+
- Hover
|
|
36
|
+
- Scroll
|
|
37
|
+
- Voice command
|
|
38
|
+
- Keyboard input
|
|
39
|
+
|
|
40
|
+
**System Triggers:**
|
|
41
|
+
- Time-based (notification)
|
|
42
|
+
- Location-based
|
|
43
|
+
- Data changes
|
|
44
|
+
- Error conditions
|
|
45
|
+
|
|
46
|
+
#### 2. Rules
|
|
47
|
+
What happens once triggered.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Example: Like button
|
|
51
|
+
1. User taps heart icon
|
|
52
|
+
2. Icon changes to filled state
|
|
53
|
+
3. Color changes to red
|
|
54
|
+
4. Counter increments
|
|
55
|
+
5. Animation plays
|
|
56
|
+
6. Haptic feedback (mobile)
|
|
57
|
+
7. Data sent to server
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### 3. Feedback
|
|
61
|
+
How the system communicates what's happening.
|
|
62
|
+
|
|
63
|
+
**Visual:** Color, shape, position changes
|
|
64
|
+
**Auditory:** Sounds, voice
|
|
65
|
+
**Haptic:** Vibration, force feedback
|
|
66
|
+
**Motion:** Animation
|
|
67
|
+
|
|
68
|
+
#### 4. Loops and Modes
|
|
69
|
+
How the interaction changes over time or in different states.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Loops:
|
|
73
|
+
- First use vs. repeated use
|
|
74
|
+
- Decay over time
|
|
75
|
+
- Escalation
|
|
76
|
+
|
|
77
|
+
Modes:
|
|
78
|
+
- Light/dark mode
|
|
79
|
+
- Editing mode
|
|
80
|
+
- Offline mode
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Feedback States
|
|
86
|
+
|
|
87
|
+
### Button States
|
|
88
|
+
|
|
89
|
+
```css
|
|
90
|
+
/* Default state */
|
|
91
|
+
.button {
|
|
92
|
+
background: #0066cc;
|
|
93
|
+
color: white;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Hover state (desktop) */
|
|
97
|
+
.button:hover {
|
|
98
|
+
background: #0052a3;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Focus state (keyboard navigation) */
|
|
102
|
+
.button:focus-visible {
|
|
103
|
+
outline: 2px solid #0066cc;
|
|
104
|
+
outline-offset: 2px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Active/pressed state */
|
|
108
|
+
.button:active {
|
|
109
|
+
background: #004080;
|
|
110
|
+
transform: scale(0.98);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Disabled state */
|
|
114
|
+
.button:disabled {
|
|
115
|
+
background: #cccccc;
|
|
116
|
+
cursor: not-allowed;
|
|
117
|
+
opacity: 0.7;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Loading state */
|
|
121
|
+
.button.loading {
|
|
122
|
+
pointer-events: none;
|
|
123
|
+
/* Show spinner */
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Form Field States
|
|
128
|
+
|
|
129
|
+
```css
|
|
130
|
+
/* Default */
|
|
131
|
+
.input { border: 1px solid #ccc; }
|
|
132
|
+
|
|
133
|
+
/* Focus */
|
|
134
|
+
.input:focus { border-color: #0066cc; box-shadow: 0 0 0 3px rgba(0,102,204,0.2); }
|
|
135
|
+
|
|
136
|
+
/* Valid */
|
|
137
|
+
.input:valid { border-color: #28a745; }
|
|
138
|
+
|
|
139
|
+
/* Invalid */
|
|
140
|
+
.input:invalid { border-color: #dc3545; }
|
|
141
|
+
|
|
142
|
+
/* Disabled */
|
|
143
|
+
.input:disabled { background: #f5f5f5; cursor: not-allowed; }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### System States
|
|
147
|
+
|
|
148
|
+
| State | Visual Indicator | User Action |
|
|
149
|
+
|-------|-----------------|-------------|
|
|
150
|
+
| Loading | Spinner, skeleton, progress bar | Wait |
|
|
151
|
+
| Success | Green check, confirmation message | Continue |
|
|
152
|
+
| Error | Red alert, error message | Correct and retry |
|
|
153
|
+
| Warning | Yellow/orange alert | Proceed with caution |
|
|
154
|
+
| Empty | Illustration, helpful message | Add content |
|
|
155
|
+
| Offline | Banner, cached indicator | Limited functionality |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Animation Principles
|
|
160
|
+
|
|
161
|
+
### Timing
|
|
162
|
+
|
|
163
|
+
```css
|
|
164
|
+
/* Natural feeling durations */
|
|
165
|
+
.quick { transition-duration: 100ms; } /* Hovers, immediate feedback */
|
|
166
|
+
.normal { transition-duration: 200ms; } /* Standard transitions */
|
|
167
|
+
.smooth { transition-duration: 300ms; } /* Panel transitions */
|
|
168
|
+
.slow { transition-duration: 500ms; } /* Large/complex animations */
|
|
169
|
+
|
|
170
|
+
/* Maximum for focused attention */
|
|
171
|
+
.complex { animation-duration: 500ms; } /* Don't exceed 500ms typically */
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Easing Functions
|
|
175
|
+
|
|
176
|
+
```css
|
|
177
|
+
/* Standard easing curves */
|
|
178
|
+
.ease-out { transition-timing-function: ease-out; }
|
|
179
|
+
/* Fast start, slow end - entering elements */
|
|
180
|
+
|
|
181
|
+
.ease-in { transition-timing-function: ease-in; }
|
|
182
|
+
/* Slow start, fast end - exiting elements */
|
|
183
|
+
|
|
184
|
+
.ease-in-out { transition-timing-function: ease-in-out; }
|
|
185
|
+
/* Smooth start and end - moving elements */
|
|
186
|
+
|
|
187
|
+
/* Custom bezier curves */
|
|
188
|
+
.bounce { transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### The 12 Principles of Animation (Disney)
|
|
192
|
+
|
|
193
|
+
Applied to UI:
|
|
194
|
+
|
|
195
|
+
1. **Squash and Stretch** - Subtle scaling on press
|
|
196
|
+
2. **Anticipation** - Brief pause before action
|
|
197
|
+
3. **Staging** - Direct attention to important elements
|
|
198
|
+
4. **Straight Ahead/Pose to Pose** - Keyframe animations
|
|
199
|
+
5. **Follow Through/Overlapping** - Elements don't stop all at once
|
|
200
|
+
6. **Slow In/Slow Out** - Easing functions
|
|
201
|
+
7. **Arc** - Natural curved motion paths
|
|
202
|
+
8. **Secondary Action** - Supporting animations
|
|
203
|
+
9. **Timing** - Speed conveys weight and emotion
|
|
204
|
+
10. **Exaggeration** - Subtle emphasis (don't overdo)
|
|
205
|
+
11. **Solid Drawing** - 3D consistency
|
|
206
|
+
12. **Appeal** - Pleasing, polished animations
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Loading States
|
|
211
|
+
|
|
212
|
+
### Skeleton Screens
|
|
213
|
+
|
|
214
|
+
```html
|
|
215
|
+
<div class="card skeleton">
|
|
216
|
+
<div class="skeleton-image"></div>
|
|
217
|
+
<div class="skeleton-title"></div>
|
|
218
|
+
<div class="skeleton-text"></div>
|
|
219
|
+
<div class="skeleton-text short"></div>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<style>
|
|
223
|
+
.skeleton * {
|
|
224
|
+
background: linear-gradient(
|
|
225
|
+
90deg,
|
|
226
|
+
#f0f0f0 25%,
|
|
227
|
+
#e0e0e0 50%,
|
|
228
|
+
#f0f0f0 75%
|
|
229
|
+
);
|
|
230
|
+
background-size: 200% 100%;
|
|
231
|
+
animation: shimmer 1.5s infinite;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@keyframes shimmer {
|
|
235
|
+
0% { background-position: 200% 0; }
|
|
236
|
+
100% { background-position: -200% 0; }
|
|
237
|
+
}
|
|
238
|
+
</style>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Progress Indicators
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
Determinate (known duration):
|
|
245
|
+
┌──────────────────────────────────────┐
|
|
246
|
+
│████████████░░░░░░░░░░░░░░░ 45% │
|
|
247
|
+
└──────────────────────────────────────┘
|
|
248
|
+
|
|
249
|
+
Indeterminate (unknown duration):
|
|
250
|
+
┌──────────────────────────────────────┐
|
|
251
|
+
│ ████████░░░░░░ │ (moving)
|
|
252
|
+
└──────────────────────────────────────┘
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Spinner Guidelines
|
|
256
|
+
|
|
257
|
+
- Show after 300ms delay (avoid flash for fast operations)
|
|
258
|
+
- Use on buttons during submission
|
|
259
|
+
- Disable interaction during loading
|
|
260
|
+
- Provide cancel option for long operations
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Gesture Design
|
|
265
|
+
|
|
266
|
+
### Standard Touch Gestures
|
|
267
|
+
|
|
268
|
+
| Gesture | Action | Example |
|
|
269
|
+
|---------|--------|---------|
|
|
270
|
+
| Tap | Select, activate | Button press |
|
|
271
|
+
| Double tap | Zoom, like | Photo zoom |
|
|
272
|
+
| Long press | Context menu | Delete options |
|
|
273
|
+
| Swipe | Navigate, dismiss | Page turn, delete |
|
|
274
|
+
| Pinch | Zoom | Map, photo |
|
|
275
|
+
| Rotate | Rotate object | Image editing |
|
|
276
|
+
| Drag | Move, reorder | List sorting |
|
|
277
|
+
|
|
278
|
+
### Gesture Best Practices
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
1. Provide visual affordances
|
|
282
|
+
- Swipe indicators
|
|
283
|
+
- Drag handles
|
|
284
|
+
- Touch hints
|
|
285
|
+
|
|
286
|
+
2. Offer alternatives (WCAG 2.5.7)
|
|
287
|
+
- Buttons for swipe actions
|
|
288
|
+
- Menus for gestures
|
|
289
|
+
- Keyboard equivalents
|
|
290
|
+
|
|
291
|
+
3. Give feedback
|
|
292
|
+
- Haptic response
|
|
293
|
+
- Visual confirmation
|
|
294
|
+
- Sound (optional)
|
|
295
|
+
|
|
296
|
+
4. Allow undo
|
|
297
|
+
- Swipe to delete → Undo button
|
|
298
|
+
- Accidental gestures happen
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Transitions
|
|
304
|
+
|
|
305
|
+
### Page Transitions
|
|
306
|
+
|
|
307
|
+
```css
|
|
308
|
+
/* Fade transition */
|
|
309
|
+
.page-enter {
|
|
310
|
+
opacity: 0;
|
|
311
|
+
}
|
|
312
|
+
.page-enter-active {
|
|
313
|
+
opacity: 1;
|
|
314
|
+
transition: opacity 200ms ease-out;
|
|
315
|
+
}
|
|
316
|
+
.page-exit {
|
|
317
|
+
opacity: 1;
|
|
318
|
+
}
|
|
319
|
+
.page-exit-active {
|
|
320
|
+
opacity: 0;
|
|
321
|
+
transition: opacity 200ms ease-in;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* Slide transition */
|
|
325
|
+
.page-enter {
|
|
326
|
+
transform: translateX(100%);
|
|
327
|
+
}
|
|
328
|
+
.page-enter-active {
|
|
329
|
+
transform: translateX(0);
|
|
330
|
+
transition: transform 300ms ease-out;
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Modal Transitions
|
|
335
|
+
|
|
336
|
+
```css
|
|
337
|
+
/* Backdrop */
|
|
338
|
+
.backdrop {
|
|
339
|
+
opacity: 0;
|
|
340
|
+
transition: opacity 200ms ease;
|
|
341
|
+
}
|
|
342
|
+
.backdrop.open {
|
|
343
|
+
opacity: 1;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Modal */
|
|
347
|
+
.modal {
|
|
348
|
+
transform: scale(0.95);
|
|
349
|
+
opacity: 0;
|
|
350
|
+
transition: transform 200ms ease, opacity 200ms ease;
|
|
351
|
+
}
|
|
352
|
+
.modal.open {
|
|
353
|
+
transform: scale(1);
|
|
354
|
+
opacity: 1;
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Accordion/Collapse
|
|
359
|
+
|
|
360
|
+
```css
|
|
361
|
+
.accordion-content {
|
|
362
|
+
max-height: 0;
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
transition: max-height 300ms ease-out;
|
|
365
|
+
}
|
|
366
|
+
.accordion-content.open {
|
|
367
|
+
max-height: 500px; /* Use calculated height for best results */
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Reduced Motion
|
|
374
|
+
|
|
375
|
+
### Respecting User Preferences
|
|
376
|
+
|
|
377
|
+
```css
|
|
378
|
+
/* Check user preference */
|
|
379
|
+
@media (prefers-reduced-motion: reduce) {
|
|
380
|
+
*,
|
|
381
|
+
*::before,
|
|
382
|
+
*::after {
|
|
383
|
+
animation-duration: 0.01ms !important;
|
|
384
|
+
animation-iteration-count: 1 !important;
|
|
385
|
+
transition-duration: 0.01ms !important;
|
|
386
|
+
scroll-behavior: auto !important;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Alternative: provide reduced but not eliminated motion */
|
|
391
|
+
@media (prefers-reduced-motion: reduce) {
|
|
392
|
+
.animated {
|
|
393
|
+
animation: none;
|
|
394
|
+
transition: opacity 0.01ms;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### When to Reduce Motion
|
|
400
|
+
|
|
401
|
+
- Vestibular disorders
|
|
402
|
+
- Motion sickness
|
|
403
|
+
- Cognitive load reduction
|
|
404
|
+
- Battery/performance concerns
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Haptic Feedback
|
|
409
|
+
|
|
410
|
+
### Mobile Haptics
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// Web Vibration API
|
|
414
|
+
if ('vibrate' in navigator) {
|
|
415
|
+
// Single vibration (ms)
|
|
416
|
+
navigator.vibrate(50);
|
|
417
|
+
|
|
418
|
+
// Pattern: vibrate, pause, vibrate
|
|
419
|
+
navigator.vibrate([50, 100, 50]);
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Haptic Patterns
|
|
424
|
+
|
|
425
|
+
| Action | Pattern | Feel |
|
|
426
|
+
|--------|---------|------|
|
|
427
|
+
| Success | Short, light | Confirmation |
|
|
428
|
+
| Error | Two quick pulses | Alert |
|
|
429
|
+
| Selection | Very short | Tactile |
|
|
430
|
+
| Warning | Medium, strong | Attention |
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 2026 Trends
|
|
435
|
+
|
|
436
|
+
### Functional Motion (motion earns its keep)
|
|
437
|
+
The dominant 2026 framing: motion should **guide, not flash**. Every animation must
|
|
438
|
+
do a job—orient the user, show cause and effect, or maintain spatial continuity—
|
|
439
|
+
otherwise it's decoration that adds cognitive load. Reserve flourish for moments
|
|
440
|
+
that matter (success, first-run delight); keep everyday transitions calm and quick.
|
|
441
|
+
|
|
442
|
+
- Use motion to **explain state change** (where did this come from / go to?)
|
|
443
|
+
- Use motion to **direct attention** to what just changed
|
|
444
|
+
- Use motion to **preserve context** across views (shared-element transitions)
|
|
445
|
+
- Cut motion that exists only to look impressive—calm interfaces win in 2026
|
|
446
|
+
|
|
447
|
+
### Giving Users Control Over Motion
|
|
448
|
+
`prefers-reduced-motion` (see [Reduced Motion](#reduced-motion) above) is the
|
|
449
|
+
baseline, but it's an OS-level all-or-nothing switch many users never set. Mature
|
|
450
|
+
products add an **explicit in-product "Reduce motion" toggle** in settings so users
|
|
451
|
+
can dial motion down without touching system preferences.
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
Settings → Accessibility → Motion
|
|
455
|
+
○ Full motion (default)
|
|
456
|
+
● Reduced motion ← respects this even if OS pref is unset
|
|
457
|
+
○ Off
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
- Default to the OS preference, then let the in-app setting override it
|
|
461
|
+
- Persist the choice per user/device; apply it everywhere, not just key screens
|
|
462
|
+
- Treat "reduced" as *reduced* (instant fades) not *broken* (no feedback at all)
|
|
463
|
+
|
|
464
|
+
### AI-Driven Interactions
|
|
465
|
+
- Predictive UI that anticipates needs (offered, never forced)
|
|
466
|
+
- Personalized micro-interactions
|
|
467
|
+
- Adaptive animation complexity tuned to device performance
|
|
468
|
+
|
|
469
|
+
### Voice + Multimodal
|
|
470
|
+
- Multimodal feedback (voice confirms visual action)
|
|
471
|
+
- Combining voice, touch, pointer, and keyboard input
|
|
472
|
+
- See [24-voice-and-multimodal.md](24-voice-and-multimodal.md) for depth
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Common Mistakes
|
|
477
|
+
|
|
478
|
+
1. **Too much animation** - Distracting, performance issues
|
|
479
|
+
2. **Too fast/slow** - Feels broken or sluggish
|
|
480
|
+
3. **No feedback** - Users unsure if action worked
|
|
481
|
+
4. **Inconsistent timing** - Jarring experience
|
|
482
|
+
5. **Ignoring reduced motion** - Accessibility failure
|
|
483
|
+
6. **Blocking content** - Loading spinners over everything
|
|
484
|
+
7. **No cancel option** - Trapped in loading state
|
|
485
|
+
8. **Overusing haptics** - Annoying, drains battery
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Sources
|
|
490
|
+
|
|
491
|
+
- Saffer, D. (2013). "Microinteractions: Designing with Details"
|
|
492
|
+
- Material Design Motion Guidelines
|
|
493
|
+
- Apple Human Interface Guidelines - Motion
|
|
494
|
+
- [UXDesign.cc - Motion Design](https://uxdesign.cc/)
|
|
495
|
+
- [CSS Tricks - Animation](https://css-tricks.com/tag/animation/)
|