@teseor/css 1.12.0 → 1.14.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.
@@ -2,7 +2,7 @@
2
2
  "id": "grid-primitive",
3
3
  "type": "primitive",
4
4
  "title": "Grid",
5
- "description": "CSS Grid with column variants.",
5
+ "description": "CSS Grid with column variants, subgrid support, and span utilities.",
6
6
  "api": "grid.api.json",
7
7
  "sections": [
8
8
  {
@@ -145,6 +145,349 @@
145
145
  ]
146
146
  }
147
147
  ]
148
+ },
149
+ {
150
+ "title": "Subgrid",
151
+ "description": "Children inherit parent grid tracks for cross-item alignment.",
152
+ "examples": [
153
+ {
154
+ "title": "Column subgrid",
155
+ "items": [
156
+ {
157
+ "tag": "div",
158
+ "class": "ui-grid ui-grid--3",
159
+ "children": [
160
+ {
161
+ "tag": "div",
162
+ "class": "ui-grid--subgrid",
163
+ "style": {
164
+ "grid-column": "span 3"
165
+ },
166
+ "children": [
167
+ {
168
+ "tag": "div",
169
+ "text": "Subgrid child 1",
170
+ "style": {
171
+ "background": "var(--ui-color-bg-muted)",
172
+ "padding": "var(--ui-space-2)"
173
+ }
174
+ },
175
+ {
176
+ "tag": "div",
177
+ "text": "Subgrid child 2",
178
+ "style": {
179
+ "background": "var(--ui-color-bg-muted)",
180
+ "padding": "var(--ui-space-2)"
181
+ }
182
+ },
183
+ {
184
+ "tag": "div",
185
+ "text": "Subgrid child 3",
186
+ "style": {
187
+ "background": "var(--ui-color-bg-muted)",
188
+ "padding": "var(--ui-space-2)"
189
+ }
190
+ }
191
+ ]
192
+ }
193
+ ]
194
+ }
195
+ ],
196
+ "code": "<div class=\"ui-grid ui-grid--3\">\n <div class=\"ui-grid--subgrid\" style=\"grid-column: span 3\">\n <div>Subgrid child 1</div>\n <div>Subgrid child 2</div>\n <div>Subgrid child 3</div>\n </div>\n</div>"
197
+ },
198
+ {
199
+ "title": "Row subgrid (aligned cards)",
200
+ "items": [
201
+ {
202
+ "tag": "div",
203
+ "class": "ui-grid ui-grid--3",
204
+ "style": {
205
+ "grid-template-rows": "auto 1fr auto"
206
+ },
207
+ "children": [
208
+ {
209
+ "tag": "div",
210
+ "class": "ui-grid--subgrid-rows",
211
+ "style": {
212
+ "grid-row": "span 3",
213
+ "border": "1px solid var(--ui-color-border)",
214
+ "padding": "var(--ui-space-2)"
215
+ },
216
+ "children": [
217
+ {
218
+ "tag": "strong",
219
+ "text": "Card A"
220
+ },
221
+ {
222
+ "tag": "p",
223
+ "text": "Short content."
224
+ },
225
+ {
226
+ "tag": "span",
227
+ "text": "Footer",
228
+ "style": {
229
+ "color": "var(--ui-color-text-muted)"
230
+ }
231
+ }
232
+ ]
233
+ },
234
+ {
235
+ "tag": "div",
236
+ "class": "ui-grid--subgrid-rows",
237
+ "style": {
238
+ "grid-row": "span 3",
239
+ "border": "1px solid var(--ui-color-border)",
240
+ "padding": "var(--ui-space-2)"
241
+ },
242
+ "children": [
243
+ {
244
+ "tag": "strong",
245
+ "text": "Card B"
246
+ },
247
+ {
248
+ "tag": "p",
249
+ "text": "Longer content that wraps to multiple lines to demonstrate row alignment."
250
+ },
251
+ {
252
+ "tag": "span",
253
+ "text": "Footer",
254
+ "style": {
255
+ "color": "var(--ui-color-text-muted)"
256
+ }
257
+ }
258
+ ]
259
+ },
260
+ {
261
+ "tag": "div",
262
+ "class": "ui-grid--subgrid-rows",
263
+ "style": {
264
+ "grid-row": "span 3",
265
+ "border": "1px solid var(--ui-color-border)",
266
+ "padding": "var(--ui-space-2)"
267
+ },
268
+ "children": [
269
+ {
270
+ "tag": "strong",
271
+ "text": "Card C"
272
+ },
273
+ {
274
+ "tag": "p",
275
+ "text": "Medium text."
276
+ },
277
+ {
278
+ "tag": "span",
279
+ "text": "Footer",
280
+ "style": {
281
+ "color": "var(--ui-color-text-muted)"
282
+ }
283
+ }
284
+ ]
285
+ }
286
+ ]
287
+ }
288
+ ],
289
+ "code": "<div class=\"ui-grid ui-grid--3\" style=\"grid-template-rows: auto 1fr auto\">\n <div class=\"ui-grid--subgrid-rows\" style=\"grid-row: span 3\">\n <strong>Title</strong>\n <p>Content</p>\n <span>Footer</span>\n </div>\n</div>"
290
+ },
291
+ {
292
+ "title": "Both axes subgrid",
293
+ "items": [
294
+ {
295
+ "tag": "div",
296
+ "class": "ui-grid ui-grid--3",
297
+ "style": {
298
+ "grid-template-rows": "auto auto"
299
+ },
300
+ "children": [
301
+ {
302
+ "tag": "div",
303
+ "class": "ui-grid--subgrid-both",
304
+ "style": {
305
+ "grid-column": "span 3",
306
+ "grid-row": "span 2"
307
+ },
308
+ "children": [
309
+ {
310
+ "tag": "div",
311
+ "text": "A1",
312
+ "style": {
313
+ "background": "var(--ui-color-bg-muted)",
314
+ "padding": "var(--ui-space-2)"
315
+ }
316
+ },
317
+ {
318
+ "tag": "div",
319
+ "text": "A2",
320
+ "style": {
321
+ "background": "var(--ui-color-bg-muted)",
322
+ "padding": "var(--ui-space-2)"
323
+ }
324
+ },
325
+ {
326
+ "tag": "div",
327
+ "text": "A3",
328
+ "style": {
329
+ "background": "var(--ui-color-bg-muted)",
330
+ "padding": "var(--ui-space-2)"
331
+ }
332
+ },
333
+ {
334
+ "tag": "div",
335
+ "text": "B1",
336
+ "style": {
337
+ "background": "var(--ui-color-bg-subtle)",
338
+ "padding": "var(--ui-space-2)"
339
+ }
340
+ },
341
+ {
342
+ "tag": "div",
343
+ "text": "B2",
344
+ "style": {
345
+ "background": "var(--ui-color-bg-subtle)",
346
+ "padding": "var(--ui-space-2)"
347
+ }
348
+ },
349
+ {
350
+ "tag": "div",
351
+ "text": "B3",
352
+ "style": {
353
+ "background": "var(--ui-color-bg-subtle)",
354
+ "padding": "var(--ui-space-2)"
355
+ }
356
+ }
357
+ ]
358
+ }
359
+ ]
360
+ }
361
+ ],
362
+ "code": "<div class=\"ui-grid ui-grid--3\" style=\"grid-template-rows: auto auto\">\n <div class=\"ui-grid--subgrid-both\" style=\"grid-column: span 3; grid-row: span 2\">\n <div>A1</div><div>A2</div><div>A3</div>\n <div>B1</div><div>B2</div><div>B3</div>\n </div>\n</div>"
363
+ }
364
+ ]
365
+ },
366
+ {
367
+ "title": "Column Span",
368
+ "description": "Span multiple columns with .ui-grid-col-span-{2,3,4,full} utilities.",
369
+ "examples": [
370
+ {
371
+ "items": [
372
+ {
373
+ "tag": "div",
374
+ "class": "ui-grid ui-grid--4",
375
+ "children": [
376
+ {
377
+ "tag": "div",
378
+ "text": "Span 2",
379
+ "style": {
380
+ "grid-column": "span 2",
381
+ "background": "var(--ui-color-bg-muted)",
382
+ "padding": "var(--ui-space-2)"
383
+ }
384
+ },
385
+ {
386
+ "tag": "div",
387
+ "text": "1",
388
+ "style": {
389
+ "background": "var(--ui-color-bg-subtle)",
390
+ "padding": "var(--ui-space-2)"
391
+ }
392
+ },
393
+ {
394
+ "tag": "div",
395
+ "text": "1",
396
+ "style": {
397
+ "background": "var(--ui-color-bg-subtle)",
398
+ "padding": "var(--ui-space-2)"
399
+ }
400
+ },
401
+ {
402
+ "tag": "div",
403
+ "text": "1",
404
+ "style": {
405
+ "background": "var(--ui-color-bg-subtle)",
406
+ "padding": "var(--ui-space-2)"
407
+ }
408
+ },
409
+ {
410
+ "tag": "div",
411
+ "text": "Span 3",
412
+ "style": {
413
+ "grid-column": "span 3",
414
+ "background": "var(--ui-color-bg-muted)",
415
+ "padding": "var(--ui-space-2)"
416
+ }
417
+ },
418
+ {
419
+ "tag": "div",
420
+ "text": "Span full",
421
+ "style": {
422
+ "grid-column": "1 / -1",
423
+ "background": "var(--ui-color-bg-muted)",
424
+ "padding": "var(--ui-space-2)"
425
+ }
426
+ }
427
+ ]
428
+ }
429
+ ],
430
+ "code": "{% set spans = ['2', '3', '4', 'full'] %}<div class=\"ui-grid ui-grid--4\">\n{% for s in spans %} <div class=\"ui-grid-col-span-{{ s }}\">Span {{ s }}</div>\n{% endfor %}</div>"
431
+ }
432
+ ]
433
+ },
434
+ {
435
+ "title": "Row Span",
436
+ "description": "Span multiple rows with .ui-grid-row-span-{2,3,full} utilities.",
437
+ "examples": [
438
+ {
439
+ "items": [
440
+ {
441
+ "tag": "div",
442
+ "class": "ui-grid ui-grid--3",
443
+ "children": [
444
+ {
445
+ "tag": "div",
446
+ "text": "Row span 2",
447
+ "style": {
448
+ "grid-row": "span 2",
449
+ "background": "var(--ui-color-bg-muted)",
450
+ "padding": "var(--ui-space-2)"
451
+ }
452
+ },
453
+ {
454
+ "tag": "div",
455
+ "text": "1",
456
+ "style": {
457
+ "background": "var(--ui-color-bg-subtle)",
458
+ "padding": "var(--ui-space-2)"
459
+ }
460
+ },
461
+ {
462
+ "tag": "div",
463
+ "text": "2",
464
+ "style": {
465
+ "background": "var(--ui-color-bg-subtle)",
466
+ "padding": "var(--ui-space-2)"
467
+ }
468
+ },
469
+ {
470
+ "tag": "div",
471
+ "text": "3",
472
+ "style": {
473
+ "background": "var(--ui-color-bg-subtle)",
474
+ "padding": "var(--ui-space-2)"
475
+ }
476
+ },
477
+ {
478
+ "tag": "div",
479
+ "text": "4",
480
+ "style": {
481
+ "background": "var(--ui-color-bg-subtle)",
482
+ "padding": "var(--ui-space-2)"
483
+ }
484
+ }
485
+ ]
486
+ }
487
+ ],
488
+ "code": "{% set spans = ['2', '3', 'full'] %}<div class=\"ui-grid ui-grid--3\">\n{% for s in spans %} <div class=\"ui-grid-row-span-{{ s }}\">Row span {{ s }}</div>\n{% endfor %}</div>"
489
+ }
490
+ ]
148
491
  }
149
492
  ]
150
493
  }
@@ -17,4 +17,34 @@
17
17
  .grid--auto {
18
18
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min, 16rem), 1fr));
19
19
  }
20
+
21
+ // @modifier boolean subgrid
22
+ .grid--subgrid {
23
+ display: grid;
24
+ grid-template-columns: subgrid;
25
+ }
26
+
27
+ // @modifier boolean subgrid-rows
28
+ .grid--subgrid-rows {
29
+ display: grid;
30
+ grid-template-rows: subgrid;
31
+ }
32
+
33
+ // @modifier boolean subgrid-both
34
+ .grid--subgrid-both {
35
+ display: grid;
36
+ grid-template-columns: subgrid;
37
+ grid-template-rows: subgrid;
38
+ }
39
+
40
+ // Column spanning
41
+ .grid-col-span-2 { grid-column: span 2; }
42
+ .grid-col-span-3 { grid-column: span 3; }
43
+ .grid-col-span-4 { grid-column: span 4; }
44
+ .grid-col-span-full { grid-column: 1 / -1; }
45
+
46
+ // Row spanning
47
+ .grid-row-span-2 { grid-row: span 2; }
48
+ .grid-row-span-3 { grid-row: span 3; }
49
+ .grid-row-span-full { grid-row: 1 / -1; }
20
50
  }
@@ -5,4 +5,5 @@
5
5
  @forward "./visually-hidden/index";
6
6
  @forward "./view-transition/index";
7
7
  @forward "./scroll-snap/index";
8
+ @forward "./scroll-animation/index";
8
9
  @forward "./container/index";
@@ -0,0 +1,136 @@
1
+ @use '../../config/tokens/variables' as t;
2
+ // Scroll-driven animation utilities
3
+ // Progressive enhancement: all rules wrapped in @supports
4
+
5
+ @layer utilities {
6
+ @supports (animation-timeline: scroll()) {
7
+ // ========================================================================
8
+ // SCROLL PROGRESS INDICATOR
9
+ // Fixed bar at top of viewport showing page scroll progress
10
+ // ========================================================================
11
+ .scroll-progress {
12
+ position: fixed;
13
+ inset-block-start: 0;
14
+ inset-inline-start: 0;
15
+ z-index: var(--ui-z-toast, #{t.$z-toast});
16
+
17
+ block-size: var(--ui-scroll-progress-height, var(--ui-space-half, #{t.$space-0}));
18
+ inline-size: 100%;
19
+
20
+ background: var(--ui-scroll-progress-bg, var(--ui-color-primary));
21
+ transform-origin: inline-start;
22
+ scale: 0 1;
23
+
24
+ animation: scroll-progress-fill auto linear;
25
+ animation-timeline: scroll();
26
+ }
27
+
28
+ @keyframes scroll-progress-fill {
29
+ to {
30
+ scale: 1 1;
31
+ }
32
+ }
33
+
34
+ // ========================================================================
35
+ // VIEW-DRIVEN FADE IN
36
+ // Fade in when element enters viewport
37
+ // ========================================================================
38
+ .view-fade {
39
+ animation: view-fade-in auto linear both;
40
+ animation-timeline: view();
41
+ animation-range: entry 0% entry 100%;
42
+ }
43
+
44
+ @keyframes view-fade-in {
45
+ from {
46
+ opacity: 0;
47
+ }
48
+
49
+ to {
50
+ opacity: 1;
51
+ }
52
+ }
53
+
54
+ // ========================================================================
55
+ // VIEW-DRIVEN SLIDE UP
56
+ // Slide up and fade in when element enters viewport
57
+ // ========================================================================
58
+ .view-slide-up {
59
+ animation: view-slide-up-in auto linear both;
60
+ animation-timeline: view();
61
+ animation-range: entry 0% entry 100%;
62
+ }
63
+
64
+ @keyframes view-slide-up-in {
65
+ from {
66
+ opacity: 0;
67
+ transform: translateY(var(--ui-space-4, #{t.$space-4}));
68
+ }
69
+
70
+ to {
71
+ opacity: 1;
72
+ transform: translateY(0);
73
+ }
74
+ }
75
+
76
+ // ========================================================================
77
+ // VIEW-DRIVEN SLIDE START (left in LTR)
78
+ // ========================================================================
79
+ .view-slide-start {
80
+ animation: view-slide-start-in auto linear both;
81
+ animation-timeline: view();
82
+ animation-range: entry 0% entry 100%;
83
+ }
84
+
85
+ @keyframes view-slide-start-in {
86
+ from {
87
+ opacity: 0;
88
+ transform: translateX(calc(var(--ui-space-4, #{t.$space-4}) * -1));
89
+ }
90
+
91
+ to {
92
+ opacity: 1;
93
+ transform: translateX(0);
94
+ }
95
+ }
96
+
97
+ // ========================================================================
98
+ // VIEW-DRIVEN SCALE
99
+ // Scale up and fade in on viewport entry
100
+ // ========================================================================
101
+ .view-scale {
102
+ animation: view-scale-in auto linear both;
103
+ animation-timeline: view();
104
+ animation-range: entry 0% entry 100%;
105
+ }
106
+
107
+ @keyframes view-scale-in {
108
+ from {
109
+ opacity: 0;
110
+ scale: 0.9;
111
+ }
112
+
113
+ to {
114
+ opacity: 1;
115
+ scale: 1;
116
+ }
117
+ }
118
+
119
+ // ========================================================================
120
+ // ACCESSIBILITY: disable all scroll-driven animations for reduced motion
121
+ // ========================================================================
122
+ @media (prefers-reduced-motion: reduce) {
123
+ .scroll-progress,
124
+ .view-fade,
125
+ .view-slide-up,
126
+ .view-slide-start,
127
+ .view-scale {
128
+ opacity: 1;
129
+ transform: none;
130
+ scale: 1 1;
131
+
132
+ animation: none;
133
+ }
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "scroll-animation",
3
+ "type": "utility",
4
+ "utilities": ["scroll-progress", "view-fade", "view-slide-up", "view-slide-start", "view-scale"],
5
+ "cssVars": [
6
+ {
7
+ "name": "--ui-scroll-progress-height",
8
+ "default": "var(--ui-space-half)",
9
+ "description": "Scroll progress indicator height"
10
+ },
11
+ {
12
+ "name": "--ui-scroll-progress-bg",
13
+ "default": "var(--ui-color-primary)",
14
+ "description": "Scroll progress indicator color"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,100 @@
1
+ {
2
+ "id": "scroll-animation-utils",
3
+ "type": "utility",
4
+ "title": "Scroll Animation",
5
+ "description": "Scroll-driven animation utilities for progress indicators and viewport-triggered effects. Wrapped in @supports — no impact on unsupported browsers.",
6
+ "api": "scroll-animation.api.json",
7
+ "sections": [
8
+ {
9
+ "title": "Scroll Progress Indicator",
10
+ "description": "Fixed bar at the top of the viewport that fills as the user scrolls down.",
11
+ "examples": [
12
+ {
13
+ "items": [
14
+ {
15
+ "tag": "div",
16
+ "attrs": { "style": "position: relative; block-size: 12rem; overflow-y: auto;" },
17
+ "children": [
18
+ {
19
+ "tag": "div",
20
+ "class": "ui-scroll-progress",
21
+ "attrs": { "style": "position: absolute;" }
22
+ },
23
+ {
24
+ "tag": "div",
25
+ "attrs": { "style": "block-size: 40rem; padding: var(--ui-space-2);" },
26
+ "children": [{ "tag": "p", "text": "Scroll down to see the progress bar fill." }]
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "code": "<div class=\"ui-scroll-progress\"></div>\n<!-- Fills as page scrolls -->"
32
+ }
33
+ ]
34
+ },
35
+ {
36
+ "title": "View Fade",
37
+ "description": "Elements fade in as they enter the viewport.",
38
+ "examples": [
39
+ {
40
+ "items": [
41
+ {
42
+ "tag": "div",
43
+ "class": "ui-view-fade ui-card ui-p-2",
44
+ "text": "I fade in on scroll"
45
+ }
46
+ ],
47
+ "code": "<div class=\"ui-view-fade\">I fade in on scroll</div>"
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "title": "View Slide Up",
53
+ "description": "Elements slide up and fade in on viewport entry.",
54
+ "examples": [
55
+ {
56
+ "items": [
57
+ {
58
+ "tag": "div",
59
+ "class": "ui-view-slide-up ui-card ui-p-2",
60
+ "text": "I slide up into view"
61
+ }
62
+ ],
63
+ "code": "<div class=\"ui-view-slide-up\">I slide up into view</div>"
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ "title": "View Slide Start",
69
+ "description": "Elements slide in from the start edge (left in LTR) on viewport entry.",
70
+ "examples": [
71
+ {
72
+ "items": [
73
+ {
74
+ "tag": "div",
75
+ "class": "ui-view-slide-start ui-card ui-p-2",
76
+ "text": "I slide from the start"
77
+ }
78
+ ],
79
+ "code": "<div class=\"ui-view-slide-start\">I slide from the start</div>"
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ "title": "View Scale",
85
+ "description": "Elements scale up and fade in on viewport entry.",
86
+ "examples": [
87
+ {
88
+ "items": [
89
+ {
90
+ "tag": "div",
91
+ "class": "ui-view-scale ui-card ui-p-2",
92
+ "text": "I scale into view"
93
+ }
94
+ ],
95
+ "code": "<div class=\"ui-view-scale\">I scale into view</div>"
96
+ }
97
+ ]
98
+ }
99
+ ]
100
+ }