@jaimevalasek/aioson 1.30.0 → 1.30.2
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 +18 -0
- package/docs/design-previews/cognitive-core-ui-auth.html +95 -0
- package/docs/design-previews/cognitive-core-ui-kanban.html +231 -0
- package/docs/design-previews/cognitive-core-ui-list-detail.html +174 -0
- package/docs/design-previews/cognitive-core-ui-preview.css +1315 -0
- package/docs/design-previews/cognitive-core-ui-settings.html +142 -0
- package/docs/design-previews/cognitive-core-ui-website.html +190 -1009
- package/docs/design-previews/cognitive-core-ui.html +281 -463
- package/docs/design-previews/index.html +83 -31
- package/package.json +1 -1
- package/src/constants.js +578 -514
- package/template/.aioson/docs/integrations/dashboard-app-form-publish-mapping.md +183 -0
- package/template/.aioson/docs/play/README.md +74 -0
- package/template/.aioson/docs/play/agent-usage-guide.md +112 -0
- package/template/.aioson/docs/play/app-compatibility-guide.md +117 -0
- package/template/.aioson/docs/play/auth-services-and-testing.md +235 -0
- package/template/.aioson/docs/play/llm-data-and-bindings.md +238 -0
- package/template/.aioson/docs/play/manifest-and-runtime.md +267 -0
- package/template/.aioson/docs/play/source-map.md +104 -0
- package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +266 -243
- package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -293
- package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -827
- package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -250
- package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -585
- package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -365
- package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +485 -482
- package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +386 -387
- package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +228 -205
- package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -338
- package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -977
- package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -218
- package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -326
- package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -461
- package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -293
- package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -352
- package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +233 -210
- package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -319
- package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -365
- package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -196
- package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -244
- package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -235
- package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -215
- package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -295
- package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +239 -203
- package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -339
- package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +417 -407
- package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +289 -272
- package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +525 -524
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +279 -279
- package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +355 -289
- package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +443 -437
- package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +245 -222
- package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -159
- package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -498
- package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -236
- package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -274
- package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -355
- package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -198
- package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -307
- package/template/.aioson/skills/design/interface-design/SKILL.md +68 -47
- package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -105
- package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -101
- package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +92 -71
- package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -74
- package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -173
- package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +236 -213
- package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -228
- package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -855
- package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -334
- package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -342
- package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -286
- package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -458
- package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -723
- package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +83 -62
- package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -74
- package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -116
- package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -47
- package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -215
- package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -31
- package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +94 -66
- package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +366 -366
- package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -150
- package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -270
- package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -189
- package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +161 -161
- package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +232 -209
- package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -324
- package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -508
- package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -223
- package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -374
- package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -356
- package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -288
- package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -289
|
@@ -1,356 +1,356 @@
|
|
|
1
|
-
# Motion — Warm Craft UI
|
|
2
|
-
|
|
3
|
-
Animation and transition specifications. Motion in Warm Craft is **gentle and purposeful** — every animation should feel like a natural, unhurried movement. Nothing aggressive, nothing flashy.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Motion Principles
|
|
8
|
-
|
|
9
|
-
1. **Gentle over dramatic.** Animations should feel like a slow exhale, not a punch. Ease-out curves, moderate durations, subtle distances.
|
|
10
|
-
2. **Purposeful only.** Every animation must communicate something: entrance, state change, feedback, hierarchy. Decorative motion is noise.
|
|
11
|
-
3. **Consistent timing.** Use the token-based durations. Never arbitrary millisecond values.
|
|
12
|
-
4. **Respect user preference.** Always implement `prefers-reduced-motion` — reduce all animations to near-instant.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Timing Tokens
|
|
17
|
-
|
|
18
|
-
```css
|
|
19
|
-
--transition-fast: 120ms ease; /* micro-interactions: hover, focus, toggle */
|
|
20
|
-
--transition-base: 200ms ease; /* state changes: active, expand, collapse */
|
|
21
|
-
--transition-slow: 320ms ease; /* page transitions, large reveals, modals */
|
|
22
|
-
--transition-theme: background 200ms ease, color 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Easing Curves
|
|
28
|
-
|
|
29
|
-
```css
|
|
30
|
-
/* Standard — most interactions */
|
|
31
|
-
--ease-default: cubic-bezier(0.25, 0.1, 0.25, 1.0); /* ease */
|
|
32
|
-
|
|
33
|
-
/* Entrance — elements appearing */
|
|
34
|
-
--ease-enter: cubic-bezier(0.0, 0.0, 0.2, 1.0); /* ease-out — decelerates in */
|
|
35
|
-
|
|
36
|
-
/* Exit — elements leaving */
|
|
37
|
-
--ease-exit: cubic-bezier(0.4, 0.0, 1.0, 1.0); /* ease-in — accelerates out */
|
|
38
|
-
|
|
39
|
-
/* Gentle spring — for playful moments (onboarding, celebrations) */
|
|
40
|
-
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1.0); /* slight overshoot */
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Entrance Animations
|
|
46
|
-
|
|
47
|
-
### Fade In (default entrance)
|
|
48
|
-
```css
|
|
49
|
-
@keyframes warm-fade-in {
|
|
50
|
-
from { opacity: 0; }
|
|
51
|
-
to { opacity: 1; }
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.fade-in {
|
|
55
|
-
animation: warm-fade-in 300ms var(--ease-enter) both;
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Fade Up (cards, sections)
|
|
60
|
-
```css
|
|
61
|
-
@keyframes warm-fade-up {
|
|
62
|
-
from {
|
|
63
|
-
opacity: 0;
|
|
64
|
-
transform: translateY(12px);
|
|
65
|
-
}
|
|
66
|
-
to {
|
|
67
|
-
opacity: 1;
|
|
68
|
-
transform: translateY(0);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.fade-up {
|
|
73
|
-
animation: warm-fade-up 400ms var(--ease-enter) both;
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Scale In (modals, popovers)
|
|
78
|
-
```css
|
|
79
|
-
@keyframes warm-scale-in {
|
|
80
|
-
from {
|
|
81
|
-
opacity: 0;
|
|
82
|
-
transform: scale(0.95);
|
|
83
|
-
}
|
|
84
|
-
to {
|
|
85
|
-
opacity: 1;
|
|
86
|
-
transform: scale(1);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.scale-in {
|
|
91
|
-
animation: warm-scale-in 250ms var(--ease-enter) both;
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Slide In (drawers, side panels)
|
|
96
|
-
```css
|
|
97
|
-
@keyframes warm-slide-in-right {
|
|
98
|
-
from {
|
|
99
|
-
opacity: 0;
|
|
100
|
-
transform: translateX(20px);
|
|
101
|
-
}
|
|
102
|
-
to {
|
|
103
|
-
opacity: 1;
|
|
104
|
-
transform: translateX(0);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.slide-in-right {
|
|
109
|
-
animation: warm-slide-in-right 300ms var(--ease-enter) both;
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## Stagger Sequences
|
|
116
|
-
|
|
117
|
-
For lists, grids, and card groups appearing together:
|
|
118
|
-
|
|
119
|
-
```css
|
|
120
|
-
.stagger-group > * {
|
|
121
|
-
animation: warm-fade-up 400ms var(--ease-enter) both;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.stagger-group > *:nth-child(1) { animation-delay: 0ms; }
|
|
125
|
-
.stagger-group > *:nth-child(2) { animation-delay: 60ms; }
|
|
126
|
-
.stagger-group > *:nth-child(3) { animation-delay: 120ms; }
|
|
127
|
-
.stagger-group > *:nth-child(4) { animation-delay: 180ms; }
|
|
128
|
-
.stagger-group > *:nth-child(5) { animation-delay: 240ms; }
|
|
129
|
-
.stagger-group > *:nth-child(6) { animation-delay: 300ms; }
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Rules:
|
|
133
|
-
- Stagger delay: 60ms per item (warm, unhurried).
|
|
134
|
-
- Max 6 items staggered. After 6, start the rest together.
|
|
135
|
-
- Only stagger on first load or page transition. Never on scroll.
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## Micro-Interactions
|
|
140
|
-
|
|
141
|
-
### Button Press
|
|
142
|
-
```css
|
|
143
|
-
button:active {
|
|
144
|
-
transform: scale(0.98);
|
|
145
|
-
transition: transform 80ms ease;
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Card Hover Lift
|
|
150
|
-
```css
|
|
151
|
-
.card-interactive {
|
|
152
|
-
transition: transform var(--transition-base), box-shadow var(--transition-base);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.card-interactive:hover {
|
|
156
|
-
transform: translateY(-2px);
|
|
157
|
-
box-shadow: var(--shadow-md);
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Toggle Switch
|
|
162
|
-
```css
|
|
163
|
-
.toggle-thumb {
|
|
164
|
-
transition: transform 200ms var(--ease-spring);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.toggle-checked .toggle-thumb {
|
|
168
|
-
transform: translateX(20px);
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### Checkbox Check
|
|
173
|
-
```css
|
|
174
|
-
@keyframes warm-check {
|
|
175
|
-
0% { stroke-dashoffset: 20; }
|
|
176
|
-
100% { stroke-dashoffset: 0; }
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
.checkbox-checked svg path {
|
|
180
|
-
animation: warm-check 200ms var(--ease-enter) both;
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### Input Focus Ring
|
|
185
|
-
```css
|
|
186
|
-
input {
|
|
187
|
-
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
input:focus {
|
|
191
|
-
border-color: var(--accent);
|
|
192
|
-
box-shadow: 0 0 0 3px var(--accent-dim);
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Page Transitions
|
|
199
|
-
|
|
200
|
-
### Content Area Change (tab switch, route change)
|
|
201
|
-
```css
|
|
202
|
-
.page-content-enter {
|
|
203
|
-
animation: warm-fade-up 300ms var(--ease-enter) both;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.page-content-exit {
|
|
207
|
-
animation: warm-fade-in 150ms var(--ease-exit) reverse both;
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Rule: exit is faster than enter (150ms vs 300ms). Content should leave quickly and arrive gently.
|
|
212
|
-
|
|
213
|
-
### Modal Enter/Exit
|
|
214
|
-
```css
|
|
215
|
-
/* Backdrop */
|
|
216
|
-
.modal-backdrop-enter {
|
|
217
|
-
animation: warm-fade-in 200ms ease both;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/* Modal */
|
|
221
|
-
.modal-enter {
|
|
222
|
-
animation: warm-scale-in 280ms var(--ease-enter) both;
|
|
223
|
-
animation-delay: 60ms; /* slight delay after backdrop */
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
.modal-exit {
|
|
227
|
-
animation: warm-scale-in 180ms var(--ease-exit) reverse both;
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Drawer Enter/Exit
|
|
232
|
-
```css
|
|
233
|
-
.drawer-enter {
|
|
234
|
-
animation: warm-slide-in-right 300ms var(--ease-enter) both;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.drawer-exit {
|
|
238
|
-
animation: warm-slide-in-right 200ms var(--ease-exit) reverse both;
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## Scroll Reveal (websites only)
|
|
245
|
-
|
|
246
|
-
Use for landing pages and marketing sections. Never for app pages.
|
|
247
|
-
|
|
248
|
-
```css
|
|
249
|
-
.scroll-reveal {
|
|
250
|
-
opacity: 0;
|
|
251
|
-
transform: translateY(20px);
|
|
252
|
-
transition: opacity 500ms var(--ease-enter), transform 500ms var(--ease-enter);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.scroll-reveal.visible {
|
|
256
|
-
opacity: 1;
|
|
257
|
-
transform: translateY(0);
|
|
258
|
-
}
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Implementation:
|
|
262
|
-
```javascript
|
|
263
|
-
const observer = new IntersectionObserver((entries) => {
|
|
264
|
-
entries.forEach(entry => {
|
|
265
|
-
if (entry.isIntersecting) {
|
|
266
|
-
entry.target.classList.add('visible');
|
|
267
|
-
observer.unobserve(entry.target); // trigger once
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
}, { threshold: 0.15 });
|
|
271
|
-
|
|
272
|
-
document.querySelectorAll('.scroll-reveal').forEach(el => observer.observe(el));
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
Rules:
|
|
276
|
-
- Threshold: 0.15 (trigger when 15% visible — feels natural).
|
|
277
|
-
- Trigger once, never re-animate on scroll back.
|
|
278
|
-
- Translate distance: 20px max. More feels dramatic, less feels invisible.
|
|
279
|
-
- Duration: 500ms. Scroll reveals are slower than UI transitions — they are narrative.
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
## Loading States
|
|
284
|
-
|
|
285
|
-
### Skeleton Pulse
|
|
286
|
-
```css
|
|
287
|
-
@keyframes warm-pulse {
|
|
288
|
-
0%, 100% { opacity: 1; }
|
|
289
|
-
50% { opacity: 0.5; }
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
.skeleton {
|
|
293
|
-
background: var(--bg-elevated);
|
|
294
|
-
border-radius: var(--radius-md);
|
|
295
|
-
animation: warm-pulse 1.8s ease-in-out infinite;
|
|
296
|
-
}
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Spinner (for buttons, small areas)
|
|
300
|
-
```css
|
|
301
|
-
@keyframes warm-spin {
|
|
302
|
-
to { transform: rotate(360deg); }
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.spinner {
|
|
306
|
-
width: 20px;
|
|
307
|
-
height: 20px;
|
|
308
|
-
border: 2px solid var(--border-medium);
|
|
309
|
-
border-top-color: var(--accent);
|
|
310
|
-
border-radius: var(--radius-full);
|
|
311
|
-
animation: warm-spin 800ms linear infinite;
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### Progress Bar Fill
|
|
316
|
-
```css
|
|
317
|
-
.progress-fill {
|
|
318
|
-
transition: width 600ms var(--ease-enter);
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
|
|
324
|
-
## Celebration Moments
|
|
325
|
-
|
|
326
|
-
For onboarding completion, achievement unlocked, milestone reached.
|
|
327
|
-
|
|
328
|
-
```css
|
|
329
|
-
@keyframes warm-celebrate {
|
|
330
|
-
0% { transform: scale(0.8); opacity: 0; }
|
|
331
|
-
50% { transform: scale(1.05); }
|
|
332
|
-
100% { transform: scale(1); opacity: 1; }
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.celebration {
|
|
336
|
-
animation: warm-celebrate 500ms var(--ease-spring) both;
|
|
337
|
-
}
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
Use sparingly. One celebration per flow, not per step.
|
|
341
|
-
|
|
342
|
-
---
|
|
343
|
-
|
|
344
|
-
## Reduced Motion
|
|
345
|
-
|
|
346
|
-
```css
|
|
347
|
-
@media (prefers-reduced-motion: reduce) {
|
|
348
|
-
*, *::before, *::after {
|
|
349
|
-
animation-duration: 0.01ms !important;
|
|
350
|
-
animation-iteration-count: 1 !important;
|
|
351
|
-
transition-duration: 0.01ms !important;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Non-negotiable. Always include this in the global stylesheet.
|
|
1
|
+
# Motion — Warm Craft UI
|
|
2
|
+
|
|
3
|
+
Animation and transition specifications. Motion in Warm Craft is **gentle and purposeful** — every animation should feel like a natural, unhurried movement. Nothing aggressive, nothing flashy.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Motion Principles
|
|
8
|
+
|
|
9
|
+
1. **Gentle over dramatic.** Animations should feel like a slow exhale, not a punch. Ease-out curves, moderate durations, subtle distances.
|
|
10
|
+
2. **Purposeful only.** Every animation must communicate something: entrance, state change, feedback, hierarchy. Decorative motion is noise.
|
|
11
|
+
3. **Consistent timing.** Use the token-based durations. Never arbitrary millisecond values.
|
|
12
|
+
4. **Respect user preference.** Always implement `prefers-reduced-motion` — reduce all animations to near-instant.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Timing Tokens
|
|
17
|
+
|
|
18
|
+
```css
|
|
19
|
+
--transition-fast: 120ms ease; /* micro-interactions: hover, focus, toggle */
|
|
20
|
+
--transition-base: 200ms ease; /* state changes: active, expand, collapse */
|
|
21
|
+
--transition-slow: 320ms ease; /* page transitions, large reveals, modals */
|
|
22
|
+
--transition-theme: background 200ms ease, color 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Easing Curves
|
|
28
|
+
|
|
29
|
+
```css
|
|
30
|
+
/* Standard — most interactions */
|
|
31
|
+
--ease-default: cubic-bezier(0.25, 0.1, 0.25, 1.0); /* ease */
|
|
32
|
+
|
|
33
|
+
/* Entrance — elements appearing */
|
|
34
|
+
--ease-enter: cubic-bezier(0.0, 0.0, 0.2, 1.0); /* ease-out — decelerates in */
|
|
35
|
+
|
|
36
|
+
/* Exit — elements leaving */
|
|
37
|
+
--ease-exit: cubic-bezier(0.4, 0.0, 1.0, 1.0); /* ease-in — accelerates out */
|
|
38
|
+
|
|
39
|
+
/* Gentle spring — for playful moments (onboarding, celebrations) */
|
|
40
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1.0); /* slight overshoot */
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Entrance Animations
|
|
46
|
+
|
|
47
|
+
### Fade In (default entrance)
|
|
48
|
+
```css
|
|
49
|
+
@keyframes warm-fade-in {
|
|
50
|
+
from { opacity: 0; }
|
|
51
|
+
to { opacity: 1; }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.fade-in {
|
|
55
|
+
animation: warm-fade-in 300ms var(--ease-enter) both;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Fade Up (cards, sections)
|
|
60
|
+
```css
|
|
61
|
+
@keyframes warm-fade-up {
|
|
62
|
+
from {
|
|
63
|
+
opacity: 0;
|
|
64
|
+
transform: translateY(12px);
|
|
65
|
+
}
|
|
66
|
+
to {
|
|
67
|
+
opacity: 1;
|
|
68
|
+
transform: translateY(0);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.fade-up {
|
|
73
|
+
animation: warm-fade-up 400ms var(--ease-enter) both;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Scale In (modals, popovers)
|
|
78
|
+
```css
|
|
79
|
+
@keyframes warm-scale-in {
|
|
80
|
+
from {
|
|
81
|
+
opacity: 0;
|
|
82
|
+
transform: scale(0.95);
|
|
83
|
+
}
|
|
84
|
+
to {
|
|
85
|
+
opacity: 1;
|
|
86
|
+
transform: scale(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.scale-in {
|
|
91
|
+
animation: warm-scale-in 250ms var(--ease-enter) both;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Slide In (drawers, side panels)
|
|
96
|
+
```css
|
|
97
|
+
@keyframes warm-slide-in-right {
|
|
98
|
+
from {
|
|
99
|
+
opacity: 0;
|
|
100
|
+
transform: translateX(20px);
|
|
101
|
+
}
|
|
102
|
+
to {
|
|
103
|
+
opacity: 1;
|
|
104
|
+
transform: translateX(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.slide-in-right {
|
|
109
|
+
animation: warm-slide-in-right 300ms var(--ease-enter) both;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Stagger Sequences
|
|
116
|
+
|
|
117
|
+
For lists, grids, and card groups appearing together:
|
|
118
|
+
|
|
119
|
+
```css
|
|
120
|
+
.stagger-group > * {
|
|
121
|
+
animation: warm-fade-up 400ms var(--ease-enter) both;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.stagger-group > *:nth-child(1) { animation-delay: 0ms; }
|
|
125
|
+
.stagger-group > *:nth-child(2) { animation-delay: 60ms; }
|
|
126
|
+
.stagger-group > *:nth-child(3) { animation-delay: 120ms; }
|
|
127
|
+
.stagger-group > *:nth-child(4) { animation-delay: 180ms; }
|
|
128
|
+
.stagger-group > *:nth-child(5) { animation-delay: 240ms; }
|
|
129
|
+
.stagger-group > *:nth-child(6) { animation-delay: 300ms; }
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Rules:
|
|
133
|
+
- Stagger delay: 60ms per item (warm, unhurried).
|
|
134
|
+
- Max 6 items staggered. After 6, start the rest together.
|
|
135
|
+
- Only stagger on first load or page transition. Never on scroll.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Micro-Interactions
|
|
140
|
+
|
|
141
|
+
### Button Press
|
|
142
|
+
```css
|
|
143
|
+
button:active {
|
|
144
|
+
transform: scale(0.98);
|
|
145
|
+
transition: transform 80ms ease;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Card Hover Lift
|
|
150
|
+
```css
|
|
151
|
+
.card-interactive {
|
|
152
|
+
transition: transform var(--transition-base), box-shadow var(--transition-base);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.card-interactive:hover {
|
|
156
|
+
transform: translateY(-2px);
|
|
157
|
+
box-shadow: var(--shadow-md);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Toggle Switch
|
|
162
|
+
```css
|
|
163
|
+
.toggle-thumb {
|
|
164
|
+
transition: transform 200ms var(--ease-spring);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.toggle-checked .toggle-thumb {
|
|
168
|
+
transform: translateX(20px);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Checkbox Check
|
|
173
|
+
```css
|
|
174
|
+
@keyframes warm-check {
|
|
175
|
+
0% { stroke-dashoffset: 20; }
|
|
176
|
+
100% { stroke-dashoffset: 0; }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.checkbox-checked svg path {
|
|
180
|
+
animation: warm-check 200ms var(--ease-enter) both;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Input Focus Ring
|
|
185
|
+
```css
|
|
186
|
+
input {
|
|
187
|
+
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
input:focus {
|
|
191
|
+
border-color: var(--accent);
|
|
192
|
+
box-shadow: 0 0 0 3px var(--accent-dim);
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Page Transitions
|
|
199
|
+
|
|
200
|
+
### Content Area Change (tab switch, route change)
|
|
201
|
+
```css
|
|
202
|
+
.page-content-enter {
|
|
203
|
+
animation: warm-fade-up 300ms var(--ease-enter) both;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.page-content-exit {
|
|
207
|
+
animation: warm-fade-in 150ms var(--ease-exit) reverse both;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Rule: exit is faster than enter (150ms vs 300ms). Content should leave quickly and arrive gently.
|
|
212
|
+
|
|
213
|
+
### Modal Enter/Exit
|
|
214
|
+
```css
|
|
215
|
+
/* Backdrop */
|
|
216
|
+
.modal-backdrop-enter {
|
|
217
|
+
animation: warm-fade-in 200ms ease both;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* Modal */
|
|
221
|
+
.modal-enter {
|
|
222
|
+
animation: warm-scale-in 280ms var(--ease-enter) both;
|
|
223
|
+
animation-delay: 60ms; /* slight delay after backdrop */
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.modal-exit {
|
|
227
|
+
animation: warm-scale-in 180ms var(--ease-exit) reverse both;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Drawer Enter/Exit
|
|
232
|
+
```css
|
|
233
|
+
.drawer-enter {
|
|
234
|
+
animation: warm-slide-in-right 300ms var(--ease-enter) both;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.drawer-exit {
|
|
238
|
+
animation: warm-slide-in-right 200ms var(--ease-exit) reverse both;
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Scroll Reveal (websites only)
|
|
245
|
+
|
|
246
|
+
Use for landing pages and marketing sections. Never for app pages.
|
|
247
|
+
|
|
248
|
+
```css
|
|
249
|
+
.scroll-reveal {
|
|
250
|
+
opacity: 0;
|
|
251
|
+
transform: translateY(20px);
|
|
252
|
+
transition: opacity 500ms var(--ease-enter), transform 500ms var(--ease-enter);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.scroll-reveal.visible {
|
|
256
|
+
opacity: 1;
|
|
257
|
+
transform: translateY(0);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Implementation:
|
|
262
|
+
```javascript
|
|
263
|
+
const observer = new IntersectionObserver((entries) => {
|
|
264
|
+
entries.forEach(entry => {
|
|
265
|
+
if (entry.isIntersecting) {
|
|
266
|
+
entry.target.classList.add('visible');
|
|
267
|
+
observer.unobserve(entry.target); // trigger once
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}, { threshold: 0.15 });
|
|
271
|
+
|
|
272
|
+
document.querySelectorAll('.scroll-reveal').forEach(el => observer.observe(el));
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Rules:
|
|
276
|
+
- Threshold: 0.15 (trigger when 15% visible — feels natural).
|
|
277
|
+
- Trigger once, never re-animate on scroll back.
|
|
278
|
+
- Translate distance: 20px max. More feels dramatic, less feels invisible.
|
|
279
|
+
- Duration: 500ms. Scroll reveals are slower than UI transitions — they are narrative.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Loading States
|
|
284
|
+
|
|
285
|
+
### Skeleton Pulse
|
|
286
|
+
```css
|
|
287
|
+
@keyframes warm-pulse {
|
|
288
|
+
0%, 100% { opacity: 1; }
|
|
289
|
+
50% { opacity: 0.5; }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.skeleton {
|
|
293
|
+
background: var(--bg-elevated);
|
|
294
|
+
border-radius: var(--radius-md);
|
|
295
|
+
animation: warm-pulse 1.8s ease-in-out infinite;
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Spinner (for buttons, small areas)
|
|
300
|
+
```css
|
|
301
|
+
@keyframes warm-spin {
|
|
302
|
+
to { transform: rotate(360deg); }
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.spinner {
|
|
306
|
+
width: 20px;
|
|
307
|
+
height: 20px;
|
|
308
|
+
border: 2px solid var(--border-medium);
|
|
309
|
+
border-top-color: var(--accent);
|
|
310
|
+
border-radius: var(--radius-full);
|
|
311
|
+
animation: warm-spin 800ms linear infinite;
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Progress Bar Fill
|
|
316
|
+
```css
|
|
317
|
+
.progress-fill {
|
|
318
|
+
transition: width 600ms var(--ease-enter);
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Celebration Moments
|
|
325
|
+
|
|
326
|
+
For onboarding completion, achievement unlocked, milestone reached.
|
|
327
|
+
|
|
328
|
+
```css
|
|
329
|
+
@keyframes warm-celebrate {
|
|
330
|
+
0% { transform: scale(0.8); opacity: 0; }
|
|
331
|
+
50% { transform: scale(1.05); }
|
|
332
|
+
100% { transform: scale(1); opacity: 1; }
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.celebration {
|
|
336
|
+
animation: warm-celebrate 500ms var(--ease-spring) both;
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Use sparingly. One celebration per flow, not per step.
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Reduced Motion
|
|
345
|
+
|
|
346
|
+
```css
|
|
347
|
+
@media (prefers-reduced-motion: reduce) {
|
|
348
|
+
*, *::before, *::after {
|
|
349
|
+
animation-duration: 0.01ms !important;
|
|
350
|
+
animation-iteration-count: 1 !important;
|
|
351
|
+
transition-duration: 0.01ms !important;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Non-negotiable. Always include this in the global stylesheet.
|