@contentrain/astro-kit 0.31.0 → 0.33.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/catalog.json +4600 -1584
- package/components/_shared/Button.astro +2 -1
- package/components/_shared/KitImage.astro +9 -4
- package/components/_shared/Section.astro +3 -1
- package/components/_shared/SectionHeader.astro +27 -0
- package/components/_shared/measured.ts +23 -0
- package/components/_shared/safe-url.ts +67 -0
- package/components/_shared/social.ts +73 -0
- package/components/announcement/Announcement.astro +2 -1
- package/components/announcement/meta.json +1 -1
- package/components/band/Band.astro +3 -2
- package/components/band/meta.json +1 -0
- package/components/breadcrumb/Breadcrumb.astro +2 -1
- package/components/breadcrumb/meta.json +1 -1
- package/components/card-grid/CardGrid.astro +2 -1
- package/components/card-grid/meta.json +1 -0
- package/components/consent/Consent.astro +2 -1
- package/components/consent/meta.json +1 -1
- package/components/contact-details/ContactDetails.astro +3 -2
- package/components/contact-details/meta.json +1 -0
- package/components/contact-form/ContactForm.astro +51 -14
- package/components/contact-form/fixtures.json +169 -9
- package/components/contact-form/meta.json +284 -15
- package/components/cta/Cta.astro +52 -12
- package/components/cta/fixtures.json +5 -1
- package/components/cta/meta.json +11 -2
- package/components/dialog/Dialog.astro +113 -0
- package/components/dialog/fixtures.json +84 -0
- package/components/dialog/meta.json +252 -0
- package/components/embed/meta.json +1 -1
- package/components/faq/Faq.astro +60 -17
- package/components/faq/fixtures.json +79 -0
- package/components/faq/meta.json +9 -3
- package/components/feature-list/FeatureList.astro +28 -4
- package/components/feature-list/meta.json +16 -3
- package/components/footer/Footer.astro +5 -4
- package/components/footer/meta.json +1 -0
- package/components/gallery/Gallery.astro +49 -14
- package/components/gallery/fixtures.json +275 -0
- package/components/gallery/meta.json +267 -14
- package/components/header/Header.astro +17 -5
- package/components/header/fixtures.json +90 -1
- package/components/header/meta.json +5 -3
- package/components/hero/meta.json +1 -0
- package/components/language-switcher/LanguageSwitcher.astro +68 -0
- package/components/language-switcher/fixtures.json +51 -0
- package/components/language-switcher/meta.json +73 -0
- package/components/logo-cloud/LogoCloud.astro +86 -21
- package/components/logo-cloud/fixtures.json +239 -0
- package/components/logo-cloud/meta.json +145 -5
- package/components/nav/Nav.astro +77 -24
- package/components/nav/NavTree.astro +40 -0
- package/components/nav/fixtures.json +165 -0
- package/components/nav/meta.json +11 -2
- package/components/newsletter/Newsletter.astro +2 -1
- package/components/newsletter/meta.json +1 -0
- package/components/pagination/Pagination.astro +4 -3
- package/components/pagination/meta.json +1 -1
- package/components/post-card/PostCard.astro +8 -5
- package/components/post-card/meta.json +3 -2
- package/components/post-list/PostList.astro +115 -0
- package/components/post-list/fixtures.json +387 -0
- package/components/post-list/meta.json +309 -0
- package/components/pricing/Pricing.astro +128 -24
- package/components/pricing/fixtures.json +288 -4
- package/components/pricing/meta.json +188 -1
- package/components/search-box/SearchBox.astro +51 -0
- package/components/search-box/fixtures.json +31 -0
- package/components/search-box/meta.json +75 -0
- package/components/slider/Slider.astro +19 -115
- package/components/slider/SliderTrack.astro +178 -0
- package/components/slider/fixtures.json +2 -1
- package/components/slider/meta.json +11 -5
- package/components/social-links/SocialLinks.astro +74 -0
- package/components/social-links/fixtures.json +67 -0
- package/components/social-links/meta.json +94 -0
- package/components/split/Split.astro +76 -14
- package/components/split/fixtures.json +8 -1
- package/components/split/meta.json +226 -4
- package/components/stats/Stats.astro +54 -11
- package/components/stats/fixtures.json +260 -0
- package/components/stats/meta.json +151 -4
- package/components/steps/Steps.astro +36 -8
- package/components/steps/fixtures.json +217 -5
- package/components/steps/meta.json +157 -3
- package/components/tabs/Tabs.astro +10 -3
- package/components/tabs/fixtures.json +4 -0
- package/components/tabs/meta.json +5 -2
- package/components/team/Team.astro +54 -9
- package/components/team/fixtures.json +217 -4
- package/components/team/meta.json +169 -3
- package/components/team/team.ts +4 -0
- package/components/testimonial/Testimonial.astro +71 -21
- package/components/testimonial/fixtures.json +73 -0
- package/components/testimonial/meta.json +168 -6
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/mapping/classic.json +124 -3
- package/mapping/divi.json +26 -8
- package/mapping/elementor.json +133 -14
- package/mapping/gutenberg.json +38 -10
- package/package.json +2 -2
|
@@ -156,5 +156,265 @@
|
|
|
156
156
|
}
|
|
157
157
|
]
|
|
158
158
|
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"name": "divided-center-md",
|
|
162
|
+
"props": {
|
|
163
|
+
"items": [
|
|
164
|
+
{
|
|
165
|
+
"value": "12",
|
|
166
|
+
"label": "Years in business",
|
|
167
|
+
"suffix": "+"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"value": "480",
|
|
171
|
+
"label": "Clients served"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"value": "99.9",
|
|
175
|
+
"label": "Uptime",
|
|
176
|
+
"suffix": "%"
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"style": "divided",
|
|
180
|
+
"align": "center",
|
|
181
|
+
"valueSize": "md"
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"name": "inline-xl",
|
|
186
|
+
"props": {
|
|
187
|
+
"items": [
|
|
188
|
+
{
|
|
189
|
+
"value": "12",
|
|
190
|
+
"label": "Years in business",
|
|
191
|
+
"suffix": "+"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"value": "480",
|
|
195
|
+
"label": "Clients served"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"value": "99.9",
|
|
199
|
+
"label": "Uptime",
|
|
200
|
+
"suffix": "%"
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"layout": "inline",
|
|
204
|
+
"valueSize": "xl",
|
|
205
|
+
"heading": "In numbers"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "display-icons",
|
|
210
|
+
"props": {
|
|
211
|
+
"items": [
|
|
212
|
+
{
|
|
213
|
+
"value": "12",
|
|
214
|
+
"label": "Years in business",
|
|
215
|
+
"suffix": "+",
|
|
216
|
+
"icon": "/kit-fixtures/logo.svg"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"value": "480",
|
|
220
|
+
"label": "Clients served",
|
|
221
|
+
"icon": "/kit-fixtures/logo.svg"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"value": "99.9",
|
|
225
|
+
"label": "Uptime",
|
|
226
|
+
"suffix": "%",
|
|
227
|
+
"icon": "/kit-fixtures/logo.svg"
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
"valueSize": "display"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "five-columns",
|
|
235
|
+
"props": {
|
|
236
|
+
"items": [
|
|
237
|
+
{
|
|
238
|
+
"value": "12",
|
|
239
|
+
"label": "Years in business",
|
|
240
|
+
"suffix": "+"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"value": "480",
|
|
244
|
+
"label": "Clients served"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"value": "99.9",
|
|
248
|
+
"label": "Uptime",
|
|
249
|
+
"suffix": "%"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"value": "7",
|
|
253
|
+
"label": "Offices"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"value": "24/7",
|
|
257
|
+
"label": "Support"
|
|
258
|
+
}
|
|
259
|
+
],
|
|
260
|
+
"columns": "5"
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"name": "six-columns",
|
|
265
|
+
"props": {
|
|
266
|
+
"items": [
|
|
267
|
+
{
|
|
268
|
+
"value": "12",
|
|
269
|
+
"label": "Years in business",
|
|
270
|
+
"suffix": "+"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"value": "480",
|
|
274
|
+
"label": "Clients served"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"value": "99.9",
|
|
278
|
+
"label": "Uptime",
|
|
279
|
+
"suffix": "%"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"value": "7",
|
|
283
|
+
"label": "Offices"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"value": "24/7",
|
|
287
|
+
"label": "Support"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"value": "3",
|
|
291
|
+
"label": "Awards"
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
"columns": "6"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "measured-columns",
|
|
299
|
+
"props": {
|
|
300
|
+
"heading": "By the numbers",
|
|
301
|
+
"intro": "A decade of shipping sites for small teams.",
|
|
302
|
+
"items": [
|
|
303
|
+
{
|
|
304
|
+
"value": "12",
|
|
305
|
+
"label": "Years in business",
|
|
306
|
+
"suffix": "+"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"value": "480",
|
|
310
|
+
"label": "Clients served"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"value": "99.9",
|
|
314
|
+
"label": "Uptime",
|
|
315
|
+
"suffix": "%"
|
|
316
|
+
}
|
|
317
|
+
],
|
|
318
|
+
"measured": {
|
|
319
|
+
"columns": {
|
|
320
|
+
"390": 1,
|
|
321
|
+
"768": 2,
|
|
322
|
+
"1280": 4
|
|
323
|
+
},
|
|
324
|
+
"gap": 40,
|
|
325
|
+
"padY": 96,
|
|
326
|
+
"bg": {
|
|
327
|
+
"color": "#0f172a"
|
|
328
|
+
},
|
|
329
|
+
"tone": "dark"
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"name": "long-values-four",
|
|
335
|
+
"props": {
|
|
336
|
+
"items": [
|
|
337
|
+
{
|
|
338
|
+
"value": "99.9",
|
|
339
|
+
"label": "Uptime",
|
|
340
|
+
"suffix": "%"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"value": "1.250",
|
|
344
|
+
"label": "Projects shipped",
|
|
345
|
+
"suffix": "+"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"value": "12.5",
|
|
349
|
+
"label": "Revenue handled",
|
|
350
|
+
"prefix": "€",
|
|
351
|
+
"suffix": "M"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"value": "480",
|
|
355
|
+
"label": "Clients served"
|
|
356
|
+
}
|
|
357
|
+
],
|
|
358
|
+
"columns": "4",
|
|
359
|
+
"style": "card",
|
|
360
|
+
"tone": "muted"
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"name": "long-values-two-xl",
|
|
365
|
+
"props": {
|
|
366
|
+
"items": [
|
|
367
|
+
{
|
|
368
|
+
"value": "99.9",
|
|
369
|
+
"label": "Uptime",
|
|
370
|
+
"suffix": "%"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"value": "1.250",
|
|
374
|
+
"label": "Projects shipped",
|
|
375
|
+
"suffix": "+"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"value": "12.5",
|
|
379
|
+
"label": "Revenue handled",
|
|
380
|
+
"prefix": "€",
|
|
381
|
+
"suffix": "M"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
"value": "480",
|
|
385
|
+
"label": "Clients served"
|
|
386
|
+
}
|
|
387
|
+
],
|
|
388
|
+
"columns": "2",
|
|
389
|
+
"style": "card",
|
|
390
|
+
"valueSize": "xl"
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": "long-values-three-display",
|
|
395
|
+
"props": {
|
|
396
|
+
"items": [
|
|
397
|
+
{
|
|
398
|
+
"value": "99.9",
|
|
399
|
+
"label": "Uptime",
|
|
400
|
+
"suffix": "%"
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"value": "1.250",
|
|
404
|
+
"label": "Projects shipped",
|
|
405
|
+
"suffix": "+"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"value": "12.5",
|
|
409
|
+
"label": "Revenue handled",
|
|
410
|
+
"prefix": "€",
|
|
411
|
+
"suffix": "M"
|
|
412
|
+
}
|
|
413
|
+
],
|
|
414
|
+
"columns": "3",
|
|
415
|
+
"style": "card",
|
|
416
|
+
"valueSize": "display",
|
|
417
|
+
"align": "center"
|
|
418
|
+
}
|
|
159
419
|
}
|
|
160
420
|
]
|
|
@@ -5,27 +5,59 @@
|
|
|
5
5
|
"category": "section",
|
|
6
6
|
"uses": [],
|
|
7
7
|
"shared": [
|
|
8
|
+
"KitImage.astro",
|
|
8
9
|
"Section.astro",
|
|
10
|
+
"image.ts",
|
|
9
11
|
"measured.ts",
|
|
12
|
+
"safe-url.ts",
|
|
10
13
|
"types.ts"
|
|
11
14
|
],
|
|
12
15
|
"variants": {
|
|
16
|
+
"layout": {
|
|
17
|
+
"options": [
|
|
18
|
+
"grid",
|
|
19
|
+
"inline"
|
|
20
|
+
],
|
|
21
|
+
"default": "grid",
|
|
22
|
+
"description": "grid: figures in columns. inline: one line that wraps, for two to four short figures."
|
|
23
|
+
},
|
|
13
24
|
"columns": {
|
|
14
25
|
"options": [
|
|
15
26
|
"2",
|
|
16
27
|
"3",
|
|
17
|
-
"4"
|
|
28
|
+
"4",
|
|
29
|
+
"5",
|
|
30
|
+
"6"
|
|
18
31
|
],
|
|
19
32
|
"default": "3",
|
|
20
|
-
"description": "Figures per row on wide screens; two on phones."
|
|
33
|
+
"description": "Figures per row on wide screens (grid layout); two on phones."
|
|
21
34
|
},
|
|
22
35
|
"style": {
|
|
23
36
|
"options": [
|
|
24
37
|
"plain",
|
|
25
|
-
"card"
|
|
38
|
+
"card",
|
|
39
|
+
"divided"
|
|
26
40
|
],
|
|
27
41
|
"default": "plain",
|
|
28
|
-
"description": "plain: figures on the section background. card: each figure in its own box."
|
|
42
|
+
"description": "plain: figures on the section background. card: each figure in its own box. divided: hairlines between the figures (across on a wide screen, above each on a phone), no box; for a single row."
|
|
43
|
+
},
|
|
44
|
+
"align": {
|
|
45
|
+
"options": [
|
|
46
|
+
"start",
|
|
47
|
+
"center"
|
|
48
|
+
],
|
|
49
|
+
"default": "start",
|
|
50
|
+
"description": "Alignment of each figure and its label."
|
|
51
|
+
},
|
|
52
|
+
"valueSize": {
|
|
53
|
+
"options": [
|
|
54
|
+
"md",
|
|
55
|
+
"lg",
|
|
56
|
+
"xl",
|
|
57
|
+
"display"
|
|
58
|
+
],
|
|
59
|
+
"default": "lg",
|
|
60
|
+
"description": "The figure's size: md, lg, xl or a display-size number."
|
|
29
61
|
},
|
|
30
62
|
"tone": {
|
|
31
63
|
"options": [
|
|
@@ -94,11 +126,126 @@
|
|
|
94
126
|
"type": "string",
|
|
95
127
|
"label": "Suffix",
|
|
96
128
|
"description": "Printed after the figure (`+`, `%`, `k`)."
|
|
129
|
+
},
|
|
130
|
+
"icon": {
|
|
131
|
+
"type": "image",
|
|
132
|
+
"label": "Icon",
|
|
133
|
+
"description": "A small picture above the figure; decorative."
|
|
97
134
|
}
|
|
98
135
|
}
|
|
99
136
|
},
|
|
100
137
|
"description": "The figures, in order (Elementor counter, Divi number counter, a Gutenberg columns row of big numbers)."
|
|
101
138
|
},
|
|
139
|
+
"measured": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"content": false,
|
|
142
|
+
"description": "The source section's measured style (MeasuredStyle): frame width, padding, fill, image, columns per width, gap, text tone, radius, minimum height — all in pixels. Absent, the site's tokens; present, it wins over tone and columns. Values that are not a number, a colour or a known keyword are dropped.",
|
|
143
|
+
"fields": {
|
|
144
|
+
"containerPx": {
|
|
145
|
+
"type": "integer",
|
|
146
|
+
"min": 0,
|
|
147
|
+
"max": 2560,
|
|
148
|
+
"description": "The frame's content width."
|
|
149
|
+
},
|
|
150
|
+
"padY": {
|
|
151
|
+
"type": "integer",
|
|
152
|
+
"min": 0,
|
|
153
|
+
"max": 400,
|
|
154
|
+
"description": "Top and bottom padding."
|
|
155
|
+
},
|
|
156
|
+
"padX": {
|
|
157
|
+
"type": "integer",
|
|
158
|
+
"min": 0,
|
|
159
|
+
"max": 200,
|
|
160
|
+
"description": "The frame's side padding (gutter)."
|
|
161
|
+
},
|
|
162
|
+
"bg": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"description": "The section's background.",
|
|
165
|
+
"fields": {
|
|
166
|
+
"color": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"description": "Fill colour: hex, rgb(a) or hsl(a)."
|
|
169
|
+
},
|
|
170
|
+
"image": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"description": "Background image address (http(s) or root-relative), drawn behind the content."
|
|
173
|
+
},
|
|
174
|
+
"overlay": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"description": "Colour or linear/radial gradient laid over the image or the fill."
|
|
177
|
+
},
|
|
178
|
+
"size": {
|
|
179
|
+
"type": "string",
|
|
180
|
+
"description": "cover, contain or auto; anything else draws as cover."
|
|
181
|
+
},
|
|
182
|
+
"position": {
|
|
183
|
+
"type": "string",
|
|
184
|
+
"description": "One or two of center/top/bottom/left/right or percentages."
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"columns": {
|
|
189
|
+
"type": "object",
|
|
190
|
+
"description": "Item columns at 390 (base), 768 (md) and 1280 (lg) px; a missing width follows the narrower one.",
|
|
191
|
+
"fields": {
|
|
192
|
+
"390": {
|
|
193
|
+
"type": "integer",
|
|
194
|
+
"min": 1,
|
|
195
|
+
"max": 6,
|
|
196
|
+
"description": "Phone."
|
|
197
|
+
},
|
|
198
|
+
"768": {
|
|
199
|
+
"type": "integer",
|
|
200
|
+
"min": 1,
|
|
201
|
+
"max": 6,
|
|
202
|
+
"description": "Tablet."
|
|
203
|
+
},
|
|
204
|
+
"1280": {
|
|
205
|
+
"type": "integer",
|
|
206
|
+
"min": 1,
|
|
207
|
+
"max": 6,
|
|
208
|
+
"description": "Desktop."
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
"gap": {
|
|
213
|
+
"type": "integer",
|
|
214
|
+
"min": 0,
|
|
215
|
+
"max": 200,
|
|
216
|
+
"description": "Gap between items."
|
|
217
|
+
},
|
|
218
|
+
"tone": {
|
|
219
|
+
"type": "select",
|
|
220
|
+
"options": [
|
|
221
|
+
"light",
|
|
222
|
+
"dark"
|
|
223
|
+
],
|
|
224
|
+
"description": "What the text is set for: dark = light text on a dark band. Without it, a fill's own lightness decides."
|
|
225
|
+
},
|
|
226
|
+
"align": {
|
|
227
|
+
"type": "select",
|
|
228
|
+
"options": [
|
|
229
|
+
"start",
|
|
230
|
+
"center",
|
|
231
|
+
"end"
|
|
232
|
+
],
|
|
233
|
+
"description": "Where the heading and lead sit; read by a component whose own align is not set."
|
|
234
|
+
},
|
|
235
|
+
"radius": {
|
|
236
|
+
"type": "integer",
|
|
237
|
+
"min": 0,
|
|
238
|
+
"max": 200,
|
|
239
|
+
"description": "Card and item corner radius."
|
|
240
|
+
},
|
|
241
|
+
"minHeight": {
|
|
242
|
+
"type": "integer",
|
|
243
|
+
"min": 0,
|
|
244
|
+
"max": 2000,
|
|
245
|
+
"description": "The section's minimum height."
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
102
249
|
"id": {
|
|
103
250
|
"type": "string",
|
|
104
251
|
"content": false,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
// How it works: an ordered sequence of steps, each a title and a line of
|
|
3
3
|
// text, optionally with an image — as a vertical list or a row across the
|
|
4
|
-
// page, numbered or plain.
|
|
4
|
+
// page, numbered or plain. `kind="timeline"` is the dated variant: a date per
|
|
5
|
+
// item on a vertical rail, optionally alternating left and right of it.
|
|
5
6
|
import { tv } from 'tailwind-variants'
|
|
6
7
|
import KitImage from '../_shared/KitImage.astro'
|
|
7
8
|
import Section from '../_shared/Section.astro'
|
|
9
|
+
import { measuredGrid } from '../_shared/measured'
|
|
10
|
+
import type { MeasuredStyle } from '../_shared/types'
|
|
8
11
|
import { imageOf, type ImageSource } from '../_shared/image'
|
|
9
12
|
|
|
10
13
|
const steps = tv({
|
|
@@ -14,6 +17,7 @@ const steps = tv({
|
|
|
14
17
|
intro: 'text-lg opacity-80',
|
|
15
18
|
list: 'grid gap-8 [counter-reset:kit-step]',
|
|
16
19
|
step: 'flex gap-4 [counter-increment:kit-step]',
|
|
20
|
+
date: 'text-sm font-semibold tabular-nums text-accent-text',
|
|
17
21
|
body: 'flex flex-col gap-2',
|
|
18
22
|
badge: 'shrink-0',
|
|
19
23
|
media: 'mb-2 overflow-hidden rounded-[var(--radius-image,var(--radius-card))]',
|
|
@@ -24,7 +28,14 @@ const steps = tv({
|
|
|
24
28
|
layout: {
|
|
25
29
|
list: { list: 'max-w-3xl' },
|
|
26
30
|
row: { list: 'sm:grid-cols-2 lg:auto-cols-fr lg:grid-flow-col lg:grid-cols-none', step: 'flex-col' },
|
|
31
|
+
// One rail on the inline-start side (the item's own side is the rail's, mirrored in RTL by the logical `ps-`/`border-s`).
|
|
32
|
+
rail: { list: 'max-w-3xl gap-0', step: 'relative border-s-2 border-line pb-8 ps-6 last:pb-0' },
|
|
33
|
+
// Items alternate either side of a centre rail from `md`; the DOM stays chronological, one rail on the start side on phones.
|
|
34
|
+
alternate: { list: 'gap-0 md:grid-cols-2', step: 'relative border-s-2 border-line pb-8 ps-6 md:[&:nth-child(even)]:col-start-2 md:[&:nth-child(odd)]:col-start-1 md:[&:nth-child(odd)]:border-s-0 md:[&:nth-child(odd)]:border-e-2 md:[&:nth-child(odd)]:pe-6 md:[&:nth-child(odd)]:ps-0 md:[&:nth-child(odd)]:text-end md:[&:nth-child(odd)]:flex-row-reverse md:[&:nth-child(even)]:-ms-px md:[&:nth-child(odd)]:after:start-auto md:[&:nth-child(odd)]:after:-end-[7px]' },
|
|
27
35
|
},
|
|
36
|
+
// What sits on the rail: the number, a plain dot, or the date (the timeline's own marker). The number marker is `style`'s.
|
|
37
|
+
marker: { number: {}, dot: { step: 'before:hidden after:absolute after:top-1.5 after:-start-[7px] after:size-3 after:rounded-full after:bg-accent after:content-[""]' } },
|
|
38
|
+
connector: { none: {}, line: {}, dashed: { step: 'border-dashed' } },
|
|
28
39
|
// The number is drawn from a CSS counter, so the list stays one <ol> a screen reader counts itself. A number the
|
|
29
40
|
// source wrote (`01`) is the page's text and is shown as written, hidden from the screen reader that already counts.
|
|
30
41
|
style: {
|
|
@@ -35,7 +46,7 @@ const steps = tv({
|
|
|
35
46
|
plain: { step: 'border-s-2 border-accent ps-4', badge: 'font-semibold tabular-nums' },
|
|
36
47
|
},
|
|
37
48
|
},
|
|
38
|
-
defaultVariants: { layout: 'list', style: 'numbered' },
|
|
49
|
+
defaultVariants: { layout: 'list', marker: 'number', connector: 'line', style: 'numbered' },
|
|
39
50
|
})
|
|
40
51
|
|
|
41
52
|
interface Step {
|
|
@@ -43,6 +54,10 @@ interface Step {
|
|
|
43
54
|
number?: string | undefined
|
|
44
55
|
title: string
|
|
45
56
|
text: string
|
|
57
|
+
/** A timeline's date as the source writes it (`2019`, `Mar 2021`); `datetime` only when it parses as an ISO date or year. */
|
|
58
|
+
date?: string | undefined
|
|
59
|
+
/** Marks the latest item: a visually hidden "Current" is added for readers. */
|
|
60
|
+
current?: boolean | undefined
|
|
46
61
|
/** The image's address. */
|
|
47
62
|
image?: ImageSource | undefined
|
|
48
63
|
imageAlt?: string | undefined
|
|
@@ -52,30 +67,43 @@ interface Props {
|
|
|
52
67
|
heading?: string | undefined
|
|
53
68
|
intro?: string | undefined
|
|
54
69
|
items: Step[]
|
|
55
|
-
|
|
70
|
+
/** `steps` numbers a sequence; `timeline` carries a date per item (the rail layouts below). */
|
|
71
|
+
kind?: 'steps' | 'timeline' | undefined
|
|
72
|
+
layout?: 'list' | 'row' | 'rail' | 'alternate' | undefined
|
|
73
|
+
marker?: 'number' | 'dot' | undefined
|
|
74
|
+
connector?: 'none' | 'line' | 'dashed' | undefined
|
|
75
|
+
currentLabel?: string | undefined
|
|
56
76
|
style?: 'numbered' | 'plain' | undefined
|
|
77
|
+
/** The source section's measured style (`MeasuredStyle`): frame, padding, fill, background image, columns per width, gap. Absent, the site's tokens; present, it wins over tone and columns. */
|
|
78
|
+
measured?: MeasuredStyle | undefined
|
|
57
79
|
id?: string | undefined
|
|
58
80
|
}
|
|
59
81
|
|
|
60
|
-
const { heading, intro, items, layout, style, id } = Astro.props
|
|
61
|
-
|
|
82
|
+
const { heading, intro, items, kind = 'steps', layout: givenLayout, marker, connector, currentLabel = 'Current', style, measured, id } = Astro.props
|
|
83
|
+
// A timeline defaults to the rail layout and, without numbers, to the plain dot marker.
|
|
84
|
+
const layout = givenLayout ?? (kind === 'timeline' ? 'rail' : 'list')
|
|
85
|
+
const s = steps({ layout, marker: marker ?? (kind === 'timeline' ? 'dot' : 'number'), connector, style })
|
|
86
|
+
// A bare year or an ISO date is machine-readable; anything else ("Spring 2021") stays text.
|
|
87
|
+
const isoDate = (date: string) => /^\d{4}(-\d{2}(-\d{2})?)?$/.test(date.trim()) ? date.trim() : undefined
|
|
62
88
|
const headingId = heading && id ? `${id}-title` : undefined
|
|
63
89
|
// One level under the section heading, or the section's heading when there is none.
|
|
64
90
|
const StepHeading = heading ? 'h3' : 'h2'
|
|
65
91
|
---
|
|
66
92
|
{items.length > 0 && (
|
|
67
|
-
<Section id={id} aria-labelledby={headingId}>
|
|
93
|
+
<Section measured={measured} id={id} aria-labelledby={headingId}>
|
|
68
94
|
{(heading || intro) && (
|
|
69
95
|
<header class={s.header()}>
|
|
70
96
|
{heading && <h2 id={headingId} class={s.heading()}>{heading}</h2>}
|
|
71
97
|
{intro && <p class={s.intro()} data-kit-text>{intro}</p>}
|
|
72
98
|
</header>
|
|
73
99
|
)}
|
|
74
|
-
<ol class={s.list()}>
|
|
100
|
+
<ol class={s.list({ class: layout === 'row' ? measuredGrid(measured) : undefined })}>
|
|
75
101
|
{items.map(step => (
|
|
76
|
-
<li class={s.step({ class: step.number ? 'before:hidden' : undefined })}>
|
|
102
|
+
<li class={s.step({ class: step.number || kind === 'timeline' ? 'before:hidden' : undefined })} aria-current={step.current ? 'step' : undefined}>
|
|
77
103
|
{step.number && <span class={s.badge()} aria-hidden="true">{step.number}</span>}
|
|
78
104
|
<div class={s.body()}>
|
|
105
|
+
{kind === 'timeline' && step.date && (isoDate(step.date) ? <time class={s.date()} datetime={isoDate(step.date)}>{step.date}</time> : <p class={s.date()}>{step.date}</p>)}
|
|
106
|
+
{step.current && <span class="sr-only">{currentLabel}</span>}
|
|
79
107
|
{imageOf(step.image, step.imageAlt) && <div class={s.media()}><KitImage image={imageOf(step.image, step.imageAlt)!} sizes="(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw" class="aspect-[3/2] w-full object-cover" /></div>}
|
|
80
108
|
<StepHeading class={s.title()}>{step.title}</StepHeading>
|
|
81
109
|
<p class={s.text()} data-kit-text>{step.text}</p>
|