@getvitops/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/css/animation.css +526 -0
- package/css/global.css +17 -0
- package/css/index.css +58 -0
- package/css/layout.css +723 -0
- package/css/patterns/anchor-link.css +66 -0
- package/css/patterns/banner.css +64 -0
- package/css/patterns/carousel.css +269 -0
- package/css/patterns/cluster.css +64 -0
- package/css/patterns/code.css +17 -0
- package/css/patterns/combobox.css +97 -0
- package/css/patterns/comment.css +88 -0
- package/css/patterns/copy.css +82 -0
- package/css/patterns/details.css +87 -0
- package/css/patterns/dialog.css +99 -0
- package/css/patterns/drawer.css +108 -0
- package/css/patterns/dropdown.css +45 -0
- package/css/patterns/forms.css +335 -0
- package/css/patterns/grouped.css +86 -0
- package/css/patterns/horizontal-scroll.css +40 -0
- package/css/patterns/icon.css +72 -0
- package/css/patterns/lightbox.css +156 -0
- package/css/patterns/list.css +272 -0
- package/css/patterns/marquee.css +68 -0
- package/css/patterns/masonry.css +40 -0
- package/css/patterns/media.css +70 -0
- package/css/patterns/nav.css +241 -0
- package/css/patterns/notification.css +114 -0
- package/css/patterns/overlay.css +28 -0
- package/css/patterns/popover.css +68 -0
- package/css/patterns/pull-quote.css +71 -0
- package/css/patterns/scroll-based.css +227 -0
- package/css/patterns/scroll-target.css +124 -0
- package/css/patterns/separator.css +130 -0
- package/css/patterns/sitenav.css +582 -0
- package/css/patterns/split-link.css +113 -0
- package/css/patterns/splitter.css +212 -0
- package/css/patterns/stack.css +67 -0
- package/css/patterns/sticky.css +127 -0
- package/css/patterns/subgrid.css +178 -0
- package/css/patterns/svg.css +166 -0
- package/css/patterns/table.css +106 -0
- package/css/patterns/tag.css +75 -0
- package/css/patterns/text-effects.css +317 -0
- package/css/patterns/tooltip.css +68 -0
- package/css/patterns/tree.css +126 -0
- package/css/utilities.css +351 -0
- package/dist/deferred.js +1 -0
- package/dist/elements.js +887 -0
- package/dist/polyfills/adoptedStyleSheets.js +1 -0
- package/dist/polyfills/css-anchor-positioning-fn.js +17 -0
- package/dist/polyfills/global.esm.js +1 -0
- package/dist/polyfills/popover.js +63 -0
- package/dist/polyfills/template-shadowroot.js +24 -0
- package/dist/polyfills/webcomponents-bundle.js +27 -0
- package/dist/polyfills.js +1 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @getvitops/core
|
|
2
|
+
|
|
3
|
+
The Vitops design-system **framework** — the platform-agnostic primitives that the generator
|
|
4
|
+
turns into platform output and that `@getvitops/bricks` / `@getvitops/astro` build on:
|
|
5
|
+
|
|
6
|
+
- **CSS partials** — the variable-driven framework (layout, utilities, component patterns).
|
|
7
|
+
Inert on their own; they resolve against the token layer emitted by
|
|
8
|
+
[`@getvitops/generator`](https://www.npmjs.com/package/@getvitops/generator).
|
|
9
|
+
- **Lit web components** — progressively-enhanced custom elements (`<wc-*>`), self-registering.
|
|
10
|
+
- **Browser polyfills** — a feature-detected loader (Anchor Positioning, Popover, Scroll
|
|
11
|
+
Timeline, …) used by both the CSS patterns and the web components.
|
|
12
|
+
|
|
13
|
+
## Subpath exports
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import '@getvitops/core/polyfills'; // feature-detected polyfill loader (load high in <head>)
|
|
17
|
+
import '@getvitops/core/elements'; // register the Lit web components
|
|
18
|
+
import '@getvitops/core/deferred'; // late progressive-enhancement behaviour
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
@import '@getvitops/core/css/index.css'; /* framework partials (needs generated tokens) */
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Most consumers don't import the CSS directly — they run
|
|
26
|
+
[`@getvitops/generator`](https://www.npmjs.com/package/@getvitops/generator) (via the
|
|
27
|
+
[CLI](https://www.npmjs.com/package/@getvitops/cli) or
|
|
28
|
+
[Vite plugin](https://www.npmjs.com/package/@getvitops/vite)) to emit a bundled stylesheet
|
|
29
|
+
from their `design-system.json`, and load these JS bundles for interactivity.
|
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation System — three orthogonal layers
|
|
3
|
+
*
|
|
4
|
+
* This file is the ENGINE (keyframes, drivers, floats, utilities), hand-written.
|
|
5
|
+
* The effect + journey classes are GENERATED from design-system.json `animations`
|
|
6
|
+
* into ./generated/animation-effects.css (imported right after this file).
|
|
7
|
+
*
|
|
8
|
+
* Effects (the WHAT): set only `--_anim` (which keyframe) +
|
|
9
|
+
* `--<prop>-from/-to` vars. Inert alone — a driver supplies the mechanism.
|
|
10
|
+
* Drivers (the HOW/WHEN): pair an effect with a mechanism —
|
|
11
|
+
* · animate-view / animate-scroll — keyframe linked to a scroll timeline
|
|
12
|
+
* · animate-trigger — keyframe, time-based; plays once when
|
|
13
|
+
* .is-active / [data-active] is set
|
|
14
|
+
* · transition-active / -hover — TRANSITION (not keyframe) over the same
|
|
15
|
+
* from/to vars, so it reverses on state flip
|
|
16
|
+
* Both driver families read the same `--<prop>-*` vars, so one effect
|
|
17
|
+
* (e.g. .fade-in) works in every mode with no redefinition.
|
|
18
|
+
*
|
|
19
|
+
* Effects by rendering stage (cheapest → most expensive):
|
|
20
|
+
* composite: fade-in/out, slide-up/down/left/right, scale-up/down, rotate-cw/ccw
|
|
21
|
+
* paint: blur-in/out, elevate-up/down, reveal-left/right/up/down
|
|
22
|
+
* layout: size-grow, size-shrink (keyframe-only — auto height)
|
|
23
|
+
* journey: fade-journey, slide-journey, … (multi-phase; view timeline)
|
|
24
|
+
* One keyframe per element: same-stage effects compose via vars (fade-in +
|
|
25
|
+
* scale-up); cross-stage (fade + blur) needs nested elements.
|
|
26
|
+
*
|
|
27
|
+
* Float (continuous, self-contained — no driver): add `.float` + a preset,
|
|
28
|
+
* e.g. <div class="float float-circular" style="--float-radius:15px">.
|
|
29
|
+
* Path variants use `.float-path` (offset-path).
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* <div class="fade-in slide-up animate-view"> <!-- scroll-into-view -->
|
|
33
|
+
* <div class="fade-in scale-up animate-trigger"> <!-- play once on enter -->
|
|
34
|
+
* <button class="scale-up transition-hover"> <!-- grow on hover -->
|
|
35
|
+
* <div class="fade-in slide-up transition-active"><!-- flip via .is-active -->
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/* ===========================================
|
|
39
|
+
* Configuration
|
|
40
|
+
* =========================================== */
|
|
41
|
+
|
|
42
|
+
:root {
|
|
43
|
+
--custom-ease-in: cubic-bezier(0.33, 1, 0.68, 1);
|
|
44
|
+
--custom-ease-out: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
45
|
+
--animation-duration-fast: 150ms;
|
|
46
|
+
--animation-duration-base: 250ms;
|
|
47
|
+
--animation-duration-slow: 500ms;
|
|
48
|
+
--animation-duration-xslow: 2s;
|
|
49
|
+
--animation-duration: var(--_animation-duration, var(--animation-duration-slow));
|
|
50
|
+
--trigger-animation-duration: var(--animation-duration-xslow);
|
|
51
|
+
|
|
52
|
+
/* Float easing presets */
|
|
53
|
+
/* Sinusoidal — smooth continuous speed, natural for 2D orbits */
|
|
54
|
+
--ease-float-sine: linear(0, 0.024, 0.095, 0.206, 0.354, 0.5, 0.646, 0.794, 0.905, 0.976, 1);
|
|
55
|
+
/* Soft bounce — decelerates at peaks, good for 1D oscillation */
|
|
56
|
+
--ease-float-bounce: linear(0, 0.11, 0.36, 0.64, 0.89, 1, 0.89, 0.64, 0.36, 0.11, 0);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ===========================================
|
|
60
|
+
* View Transitions (page navigation)
|
|
61
|
+
* =========================================== */
|
|
62
|
+
|
|
63
|
+
@view-transition {
|
|
64
|
+
navigation: auto;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
::view-transition-children(*) {
|
|
68
|
+
animation-duration: var(--animation-duration-xslow);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ===========================================
|
|
72
|
+
* Keyframes - Layout Stage (most expensive)
|
|
73
|
+
* =========================================== */
|
|
74
|
+
|
|
75
|
+
@keyframes layout {
|
|
76
|
+
from {
|
|
77
|
+
height: var(--height-from, auto);
|
|
78
|
+
}
|
|
79
|
+
to {
|
|
80
|
+
height: var(--height-to, auto);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ===========================================
|
|
85
|
+
* Keyframes - Compositor Stage (cheapest, GPU)
|
|
86
|
+
* opacity + individual transform properties
|
|
87
|
+
* =========================================== */
|
|
88
|
+
|
|
89
|
+
@keyframes composite {
|
|
90
|
+
from {
|
|
91
|
+
opacity: var(--opacity-from, 1);
|
|
92
|
+
translate: var(--translate-x-from, 0) var(--translate-y-from, 0);
|
|
93
|
+
scale: var(--scale-x-from, 1) var(--scale-y-from, 1);
|
|
94
|
+
rotate: var(--rotate-from, 0deg);
|
|
95
|
+
}
|
|
96
|
+
to {
|
|
97
|
+
opacity: var(--opacity-to, 1);
|
|
98
|
+
translate: var(--translate-x-to, 0) var(--translate-y-to, 0);
|
|
99
|
+
scale: var(--scale-x-to, 1) var(--scale-y-to, 1);
|
|
100
|
+
rotate: var(--rotate-to, 0deg);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* ===========================================
|
|
105
|
+
* Keyframes - Paint Stage
|
|
106
|
+
* filter functions + clip-path
|
|
107
|
+
* =========================================== */
|
|
108
|
+
|
|
109
|
+
@keyframes paint {
|
|
110
|
+
from {
|
|
111
|
+
filter: blur(var(--blur-from, 0px)) drop-shadow(var(--shadow-from, 0 0 0 transparent))
|
|
112
|
+
brightness(var(--brightness-from, 1)) grayscale(var(--grayscale-from, 0))
|
|
113
|
+
contrast(var(--contrast-from, 1)) saturate(var(--saturate-from, 1))
|
|
114
|
+
sepia(var(--sepia-from, 0)) hue-rotate(var(--hue-rotate-from, 0deg));
|
|
115
|
+
clip-path: var(--clip-from, none);
|
|
116
|
+
}
|
|
117
|
+
to {
|
|
118
|
+
filter: blur(var(--blur-to, 0px)) drop-shadow(var(--shadow-to, 0 0 0 transparent))
|
|
119
|
+
brightness(var(--brightness-to, 1)) grayscale(var(--grayscale-to, 0))
|
|
120
|
+
contrast(var(--contrast-to, 1)) saturate(var(--saturate-to, 1)) sepia(var(--sepia-to, 0))
|
|
121
|
+
hue-rotate(var(--hue-rotate-to, 0deg));
|
|
122
|
+
clip-path: var(--clip-to, none);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ===========================================
|
|
127
|
+
* Keyframes - Journey (Multi-Phase)
|
|
128
|
+
* Entry → Hold → Exit pattern
|
|
129
|
+
* =========================================== */
|
|
130
|
+
|
|
131
|
+
@keyframes fade-journey {
|
|
132
|
+
0%,
|
|
133
|
+
100% {
|
|
134
|
+
opacity: var(--opacity-from, 0);
|
|
135
|
+
}
|
|
136
|
+
25%,
|
|
137
|
+
75% {
|
|
138
|
+
opacity: var(--opacity-to, 1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@keyframes slide-journey {
|
|
143
|
+
0% {
|
|
144
|
+
translate: var(--translate-x-from, 0) var(--translate-y-from, 0);
|
|
145
|
+
}
|
|
146
|
+
25%,
|
|
147
|
+
75% {
|
|
148
|
+
translate: var(--translate-x-to, 0) var(--translate-y-to, 0);
|
|
149
|
+
}
|
|
150
|
+
100% {
|
|
151
|
+
translate: calc(var(--translate-x-from, 0) * -1) calc(var(--translate-y-from, 0) * -1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes scale-journey {
|
|
156
|
+
0%,
|
|
157
|
+
100% {
|
|
158
|
+
scale: var(--scale-x-from, 0.8) var(--scale-y-from, 0.8);
|
|
159
|
+
}
|
|
160
|
+
25%,
|
|
161
|
+
75% {
|
|
162
|
+
scale: var(--scale-x-to, 1) var(--scale-y-to, 1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@keyframes blur-journey {
|
|
167
|
+
0%,
|
|
168
|
+
100% {
|
|
169
|
+
filter: blur(var(--blur-from, 5px));
|
|
170
|
+
}
|
|
171
|
+
25%,
|
|
172
|
+
75% {
|
|
173
|
+
filter: blur(var(--blur-to, 0));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* ===========================================
|
|
178
|
+
* Keyframes - Float (Continuous Movement)
|
|
179
|
+
* 4 configurable waypoints, loops back to start
|
|
180
|
+
* =========================================== */
|
|
181
|
+
|
|
182
|
+
@keyframes float {
|
|
183
|
+
0%,
|
|
184
|
+
100% {
|
|
185
|
+
translate: var(--float-x-0, 0) var(--float-y-0, 0);
|
|
186
|
+
}
|
|
187
|
+
25% {
|
|
188
|
+
translate: var(--float-x-25, 0) var(--float-y-25, 0);
|
|
189
|
+
}
|
|
190
|
+
50% {
|
|
191
|
+
translate: var(--float-x-50, 0) var(--float-y-50, 0);
|
|
192
|
+
}
|
|
193
|
+
75% {
|
|
194
|
+
translate: var(--float-x-75, 0) var(--float-y-75, 0);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@keyframes float-path {
|
|
199
|
+
from {
|
|
200
|
+
offset-distance: 0%;
|
|
201
|
+
}
|
|
202
|
+
to {
|
|
203
|
+
offset-distance: 100%;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* ===========================================
|
|
208
|
+
* Keyframes - Utility
|
|
209
|
+
* =========================================== */
|
|
210
|
+
|
|
211
|
+
@keyframes bg-position-reveal {
|
|
212
|
+
from {
|
|
213
|
+
background-position: var(--bg-position-reveal-from);
|
|
214
|
+
}
|
|
215
|
+
to {
|
|
216
|
+
background-position: var(--bg-position-reveal-to);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* ===========================================
|
|
221
|
+
* Trigger Play-State
|
|
222
|
+
* Paused until activated. deferred.ts adds .is-active via IntersectionObserver,
|
|
223
|
+
* but [data-active] / .is-active can also be toggled by any state logic. Gated
|
|
224
|
+
* on JS (no-js → animation runs immediately, so content is never stuck hidden).
|
|
225
|
+
* =========================================== */
|
|
226
|
+
|
|
227
|
+
:where(:root:not(.no-js)) {
|
|
228
|
+
.animate-trigger {
|
|
229
|
+
animation-play-state: paused;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
:is(.is-active, [data-active]).animate-trigger,
|
|
233
|
+
:is(.is-active, [data-active]) > .animate-trigger {
|
|
234
|
+
animation-play-state: running;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* ===========================================
|
|
239
|
+
* Float Base — required alongside a preset: class="float float-circular"
|
|
240
|
+
* (A plain base class beats the old [class*='float-…'] list: extensible, and
|
|
241
|
+
* the float-slow/fast/linear modifiers can't accidentally match it.)
|
|
242
|
+
* =========================================== */
|
|
243
|
+
|
|
244
|
+
.float {
|
|
245
|
+
animation-name: float;
|
|
246
|
+
animation-duration: var(--float-duration, 4s);
|
|
247
|
+
animation-timing-function: var(--float-easing, ease-in-out);
|
|
248
|
+
animation-iteration-count: var(--float-iterations, infinite);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* animation-fill-mode: both — hoisted for every keyframe-driven animation. */
|
|
252
|
+
.animate-view,
|
|
253
|
+
.animate-scroll,
|
|
254
|
+
.animate-trigger,
|
|
255
|
+
.float,
|
|
256
|
+
.float-path {
|
|
257
|
+
animation-fill-mode: both;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* ===========================================
|
|
261
|
+
* Stagger Support
|
|
262
|
+
* =========================================== */
|
|
263
|
+
|
|
264
|
+
.stagger {
|
|
265
|
+
--_stagger-amount: var(--stagger-amount, 0.1s);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.stagger > * {
|
|
269
|
+
/* Default: no stagger (index 0). JS (applyRowStagger) sets a per-item
|
|
270
|
+
--_stagger-index inline, which wins. Where sibling-index() is supported
|
|
271
|
+
it provides a JS-free fallback via the @supports block below. */
|
|
272
|
+
--_stagger-index: 0;
|
|
273
|
+
animation-delay: calc(var(--_stagger-index) * var(--_stagger-amount));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* sibling-index() is near-baseline (lacking only Firefox as of 2026). Guarded so
|
|
277
|
+
that on unsupported engines the declaration is skipped and delay stays 0
|
|
278
|
+
(items animate together) rather than producing an invalid animation-delay. */
|
|
279
|
+
@supports (--x: sibling-index()) {
|
|
280
|
+
.stagger > * {
|
|
281
|
+
--_stagger-index: sibling-index();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* ===========================================
|
|
286
|
+
* Utility Classes
|
|
287
|
+
* =========================================== */
|
|
288
|
+
|
|
289
|
+
/* Scroll-based height adjustment (for sticky headers, etc.) */
|
|
290
|
+
.scroll-size {
|
|
291
|
+
animation: layout linear both;
|
|
292
|
+
animation-timeline: scroll();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Text reveal effect */
|
|
296
|
+
/* Text reveal — scroll-driven two-tone fill.
|
|
297
|
+
Text starts in --text-reveal-color-from and fills to --text-reveal-color-to
|
|
298
|
+
as the element scrolls through the viewport. Pure CSS (no JS dependency).
|
|
299
|
+
|
|
300
|
+
Robustness: background-clip:text + transparent color can hide text if the
|
|
301
|
+
technique is unsupported, so we (a) only apply the clip/transparent inside an
|
|
302
|
+
@supports guard, and (b) default the visible color to the "from" tone so any
|
|
303
|
+
failure leaves readable text rather than blank space. Scroll-timeline is also
|
|
304
|
+
guarded — without it the text simply shows the final (to) color, still legible. */
|
|
305
|
+
.text-reveal {
|
|
306
|
+
/* Fallback baseline: ordinary visible text in the start color. */
|
|
307
|
+
color: var(--text-reveal-color-from, currentColor);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
|
|
311
|
+
.text-reveal {
|
|
312
|
+
background: var(
|
|
313
|
+
--text-reveal-background,
|
|
314
|
+
linear-gradient(
|
|
315
|
+
var(--text-reveal-slant, 90deg),
|
|
316
|
+
var(--text-reveal-color-to) 50%,
|
|
317
|
+
var(--text-reveal-color-from) 50%
|
|
318
|
+
)
|
|
319
|
+
);
|
|
320
|
+
background-size: 200% 100%;
|
|
321
|
+
background-position: 100% 0; /* start: showing the "from" half */
|
|
322
|
+
background-clip: text;
|
|
323
|
+
-webkit-background-clip: text;
|
|
324
|
+
color: transparent;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* Drive the fill with the scroll timeline only where supported. Without this,
|
|
329
|
+
the @supports block above still renders the gradient at its start position
|
|
330
|
+
(readable in the "from" color), so nothing disappears. */
|
|
331
|
+
@supports (animation-timeline: view()) {
|
|
332
|
+
.text-reveal {
|
|
333
|
+
animation: bg-position-reveal linear both;
|
|
334
|
+
animation-timeline: view();
|
|
335
|
+
animation-range: entry 50% cover 50%;
|
|
336
|
+
--bg-position-reveal-from: 100% 0;
|
|
337
|
+
--bg-position-reveal-to: 0% 0;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* ===========================================
|
|
342
|
+
* Tier 1a: Keyframe drivers (animation-name from the effect's --_anim)
|
|
343
|
+
* =========================================== */
|
|
344
|
+
|
|
345
|
+
.animate-view {
|
|
346
|
+
animation-name: var(--_anim);
|
|
347
|
+
animation-timeline: view();
|
|
348
|
+
/* Finish the entrance early — by default within the first 20% of the element's
|
|
349
|
+
ENTRY into the viewport — so it's done just after it appears (fill: both
|
|
350
|
+
holds the end state). Override the stops via --anim-range; journey effects
|
|
351
|
+
set their own `entry exit` range and are unaffected. */
|
|
352
|
+
animation-range: var(--anim-range, entry 0% entry 20%);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.animate-scroll {
|
|
356
|
+
animation-name: var(--_anim);
|
|
357
|
+
animation-timeline: scroll();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.animate-trigger {
|
|
361
|
+
animation-name: var(--_anim);
|
|
362
|
+
animation-duration: var(--trigger-animation-duration);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/* Fallback: when scroll-driven timelines are unsupported, deferred.ts adds
|
|
366
|
+
.no-scroll-timeline to <html>. Without a timeline, view()/scroll() animations
|
|
367
|
+
never advance and elements would stick at their `from` keyframe (e.g.
|
|
368
|
+
opacity:0, clipped, blurred). Cancel the animation so they render in their
|
|
369
|
+
natural, fully-visible state. Trigger animations are unaffected (JS-driven). */
|
|
370
|
+
:root.no-scroll-timeline :where(.animate-view, .animate-scroll) {
|
|
371
|
+
animation: none;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* ===========================================
|
|
375
|
+
* Tier 1b: Transition base (state-flip — reversible, interruptible)
|
|
376
|
+
* `.transition` transitions every animatable property, applying each from a
|
|
377
|
+
* single current var (--t-<prop>). The generated state variants (hover-<fx> /
|
|
378
|
+
* active-<fx> in animation-effects.css) set those vars per state, so different
|
|
379
|
+
* effects bind to different states on one element:
|
|
380
|
+
* <div class="transition hover-slide-up active-elevate-up">
|
|
381
|
+
* Covers compositor + the full paint chain; layout (auto height) is keyframe-only.
|
|
382
|
+
* =========================================== */
|
|
383
|
+
|
|
384
|
+
.transition {
|
|
385
|
+
animation: none; /* state-driven, not keyframe-driven */
|
|
386
|
+
/* Each property reads the internal --t-<prop> (set per state by the variants),
|
|
387
|
+
falling back to the SAME --<prop>-from endpoint the keyframes read — so the
|
|
388
|
+
from/to vars are one shared convention across keyframe and transition modes. */
|
|
389
|
+
opacity: var(--t-opacity, var(--opacity-from, 1));
|
|
390
|
+
translate: var(--t-translate-x, var(--translate-x-from, 0))
|
|
391
|
+
var(--t-translate-y, var(--translate-y-from, 0));
|
|
392
|
+
scale: var(--t-scale-x, var(--scale-x-from, 1)) var(--t-scale-y, var(--scale-y-from, 1));
|
|
393
|
+
rotate: var(--t-rotate, var(--rotate-from, 0deg));
|
|
394
|
+
filter: blur(var(--t-blur, var(--blur-from, 0px)))
|
|
395
|
+
drop-shadow(var(--t-shadow, var(--shadow-from, 0 0 0 transparent)))
|
|
396
|
+
brightness(var(--t-brightness, var(--brightness-from, 1)))
|
|
397
|
+
grayscale(var(--t-grayscale, var(--grayscale-from, 0)))
|
|
398
|
+
contrast(var(--t-contrast, var(--contrast-from, 1)))
|
|
399
|
+
saturate(var(--t-saturate, var(--saturate-from, 1))) sepia(var(--t-sepia, var(--sepia-from, 0)))
|
|
400
|
+
hue-rotate(var(--t-hue-rotate, var(--hue-rotate-from, 0deg)));
|
|
401
|
+
clip-path: var(--t-clip, var(--clip-from, none));
|
|
402
|
+
transition:
|
|
403
|
+
opacity var(--animation-duration) var(--custom-ease-out),
|
|
404
|
+
translate var(--animation-duration) var(--custom-ease-out),
|
|
405
|
+
scale var(--animation-duration) var(--custom-ease-out),
|
|
406
|
+
rotate var(--animation-duration) var(--custom-ease-out),
|
|
407
|
+
filter var(--animation-duration) var(--custom-ease-out),
|
|
408
|
+
clip-path var(--animation-duration) var(--custom-ease-out);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* Respect reduced-motion: drop keyframes, transitions, and continuous floats so
|
|
412
|
+
elements settle at their natural resolved state. Plain selectors + !important
|
|
413
|
+
so this reliably overrides the driver/float rules (a legitimate a11y override). */
|
|
414
|
+
@media (prefers-reduced-motion: reduce) {
|
|
415
|
+
.animate-view,
|
|
416
|
+
.animate-scroll,
|
|
417
|
+
.animate-trigger,
|
|
418
|
+
.float,
|
|
419
|
+
.float-path {
|
|
420
|
+
animation: none !important;
|
|
421
|
+
}
|
|
422
|
+
.transition {
|
|
423
|
+
transition: none !important;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* ===========================================
|
|
428
|
+
* Float Presets — Waypoint-based
|
|
429
|
+
* Each sets float-x / float-y waypoint vars + easing
|
|
430
|
+
* =========================================== */
|
|
431
|
+
|
|
432
|
+
/* Circular orbit (clockwise) */
|
|
433
|
+
.float-circular {
|
|
434
|
+
--float-easing: var(--ease-float-sine);
|
|
435
|
+
--float-y-0: calc(-1 * var(--float-radius, 10px));
|
|
436
|
+
--float-x-25: var(--float-radius, 10px);
|
|
437
|
+
--float-y-50: var(--float-radius, 10px);
|
|
438
|
+
--float-x-75: calc(-1 * var(--float-radius, 10px));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* Circular orbit (counter-clockwise) */
|
|
442
|
+
.float-circular-ccw {
|
|
443
|
+
--float-easing: var(--ease-float-sine);
|
|
444
|
+
--float-y-0: calc(-1 * var(--float-radius, 10px));
|
|
445
|
+
--float-x-25: calc(-1 * var(--float-radius, 10px));
|
|
446
|
+
--float-y-50: var(--float-radius, 10px);
|
|
447
|
+
--float-x-75: var(--float-radius, 10px);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* Figure-8 (lemniscate approximation) */
|
|
451
|
+
.float-figure-8 {
|
|
452
|
+
--float-easing: var(--ease-float-sine);
|
|
453
|
+
--float-x-25: var(--float-radius, 15px);
|
|
454
|
+
--float-y-25: calc(-1 * var(--float-radius, 15px) * 0.5);
|
|
455
|
+
--float-x-75: calc(-1 * var(--float-radius, 15px));
|
|
456
|
+
--float-y-75: calc(var(--float-radius, 15px) * 0.5);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Vertical bounce (1D, y-axis only) */
|
|
460
|
+
.float-bounce-y {
|
|
461
|
+
--float-easing: var(--ease-float-bounce);
|
|
462
|
+
--float-y-0: calc(-1 * var(--float-distance, 8px));
|
|
463
|
+
--float-y-50: var(--float-distance, 8px);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/* Horizontal drift (1D, x-axis only) */
|
|
467
|
+
.float-drift-x {
|
|
468
|
+
--float-easing: var(--ease-float-bounce);
|
|
469
|
+
--float-x-0: calc(-1 * var(--float-distance, 10px));
|
|
470
|
+
--float-x-50: var(--float-distance, 10px);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/* Gentle drift (subtle organic movement) */
|
|
474
|
+
.float-gentle {
|
|
475
|
+
--float-easing: var(--ease-float-sine);
|
|
476
|
+
--float-x-0: calc(-1 * var(--float-radius, 5px));
|
|
477
|
+
--float-y-0: calc(-1 * var(--float-radius, 5px) * 0.7);
|
|
478
|
+
--float-x-25: calc(var(--float-radius, 5px) * 0.5);
|
|
479
|
+
--float-y-25: calc(-1 * var(--float-radius, 5px) * 0.3);
|
|
480
|
+
--float-x-50: calc(var(--float-radius, 5px) * 0.8);
|
|
481
|
+
--float-y-50: calc(var(--float-radius, 5px) * 0.6);
|
|
482
|
+
--float-x-75: calc(-1 * var(--float-radius, 5px) * 0.3);
|
|
483
|
+
--float-y-75: var(--float-radius, 5px);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/* ===========================================
|
|
487
|
+
* Float Presets — Path-based
|
|
488
|
+
* Uses offset-path + offset-distance
|
|
489
|
+
* =========================================== */
|
|
490
|
+
|
|
491
|
+
.float-path {
|
|
492
|
+
offset-path: var(--float-path, circle(30px));
|
|
493
|
+
offset-rotate: var(--float-rotate, 0deg);
|
|
494
|
+
animation-name: float-path;
|
|
495
|
+
animation-duration: var(--float-duration, 4s);
|
|
496
|
+
animation-timing-function: var(--float-easing, linear);
|
|
497
|
+
animation-iteration-count: var(--float-iterations, infinite);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.float-path-circle {
|
|
501
|
+
--float-path: circle(var(--float-radius, 30px));
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.float-path-ellipse {
|
|
505
|
+
--float-path: ellipse(var(--float-radius-x, 40px) var(--float-radius-y, 20px));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/* ===========================================
|
|
509
|
+
* Float Modifiers
|
|
510
|
+
* =========================================== */
|
|
511
|
+
|
|
512
|
+
.float-slow {
|
|
513
|
+
--float-duration: 8s;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.float-fast {
|
|
517
|
+
--float-duration: 2s;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.float-linear {
|
|
521
|
+
--float-easing: linear;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.float-organic {
|
|
525
|
+
--float-easing: ease-in-out;
|
|
526
|
+
}
|
package/css/global.css
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Assert a 16px root. The framework's rem-based tokens (type + space scales) are
|
|
2
|
+
generated on a 16px basis, so a host that resets the root — WordPress themes and
|
|
3
|
+
resets often ship `:root { font-size: 62.5% }` (1rem = 10px) — would silently
|
|
4
|
+
shrink the entire system to ~62.5%. `!important` keeps the design system portable
|
|
5
|
+
and predictable across hosts (Bricks, Astro/Tailwind); browser zoom still scales
|
|
6
|
+
the page. */
|
|
7
|
+
:root {
|
|
8
|
+
font-size: 100% !important;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
12
|
+
html {
|
|
13
|
+
scrollbar-gutter: stable;
|
|
14
|
+
scroll-behavior: smooth;
|
|
15
|
+
scroll-padding-block-start: var(--top-offset, 0);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/css/index.css
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
@import './global.css';
|
|
2
|
+
@import './animation.css';
|
|
3
|
+
@import './generated/animation-effects.css';
|
|
4
|
+
@import './generated/color.css';
|
|
5
|
+
@import './generated/shadows.css';
|
|
6
|
+
@import './generated/type-tokens.css';
|
|
7
|
+
@import './generated/tokens.css';
|
|
8
|
+
@import './generated/typography.css';
|
|
9
|
+
@import './layout.css';
|
|
10
|
+
/* was layout-extra.css */
|
|
11
|
+
@import './patterns/cluster.css';
|
|
12
|
+
@import './patterns/grouped.css';
|
|
13
|
+
@import './patterns/subgrid.css';
|
|
14
|
+
@import './patterns/masonry.css';
|
|
15
|
+
@import './patterns/media.css';
|
|
16
|
+
@import './patterns/separator.css';
|
|
17
|
+
@import './patterns/sticky.css';
|
|
18
|
+
@import './patterns/stack.css';
|
|
19
|
+
@import './patterns/splitter.css';
|
|
20
|
+
@import './utilities.css';
|
|
21
|
+
@import './generated/patterns.css';
|
|
22
|
+
/* was overlays.css */
|
|
23
|
+
@import './patterns/dialog.css';
|
|
24
|
+
@import './patterns/drawer.css';
|
|
25
|
+
@import './patterns/popover.css';
|
|
26
|
+
@import './patterns/tooltip.css';
|
|
27
|
+
@import './patterns/dropdown.css';
|
|
28
|
+
@import './patterns/split-link.css';
|
|
29
|
+
@import './patterns/sitenav.css';
|
|
30
|
+
@import './patterns/notification.css';
|
|
31
|
+
@import './patterns/lightbox.css';
|
|
32
|
+
@import './patterns/overlay.css';
|
|
33
|
+
/* was forms.css */
|
|
34
|
+
@import './patterns/forms.css';
|
|
35
|
+
@import './patterns/combobox.css';
|
|
36
|
+
/* was content.css */
|
|
37
|
+
@import './patterns/table.css';
|
|
38
|
+
@import './patterns/details.css';
|
|
39
|
+
@import './patterns/comment.css';
|
|
40
|
+
@import './patterns/banner.css';
|
|
41
|
+
@import './patterns/list.css';
|
|
42
|
+
@import './patterns/tree.css';
|
|
43
|
+
/* was typographic.css */
|
|
44
|
+
@import './patterns/pull-quote.css';
|
|
45
|
+
@import './patterns/tag.css';
|
|
46
|
+
@import './patterns/anchor-link.css';
|
|
47
|
+
@import './patterns/icon.css';
|
|
48
|
+
@import './patterns/code.css';
|
|
49
|
+
/* was scroll.css */
|
|
50
|
+
@import './patterns/scroll-based.css';
|
|
51
|
+
@import './patterns/horizontal-scroll.css';
|
|
52
|
+
@import './patterns/scroll-target.css';
|
|
53
|
+
@import './patterns/text-effects.css';
|
|
54
|
+
@import './patterns/svg.css';
|
|
55
|
+
@import './patterns/marquee.css';
|
|
56
|
+
@import './patterns/nav.css';
|
|
57
|
+
@import './patterns/carousel.css';
|
|
58
|
+
@import './patterns/copy.css';
|