@teseor/css 1.4.0 → 1.6.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.
Files changed (59) hide show
  1. package/dist/compiled.css +1 -1
  2. package/dist/index.css +22 -0
  3. package/package.json +1 -1
  4. package/src/04-components/actions/close-button/close-button-visual.png +0 -0
  5. package/src/04-components/actions/close-button/close-button.api.json +71 -0
  6. package/src/04-components/actions/close-button/close-button.docs.json +264 -0
  7. package/src/04-components/actions/close-button/close-button.visual.spec.ts +14 -0
  8. package/src/04-components/actions/close-button/index.scss +101 -0
  9. package/src/04-components/data-display/image/image-visual.png +0 -0
  10. package/src/04-components/data-display/image/image.api.json +76 -0
  11. package/src/04-components/data-display/image/image.docs.json +337 -0
  12. package/src/04-components/data-display/image/image.visual.spec.ts +14 -0
  13. package/src/04-components/data-display/image/index.scss +103 -0
  14. package/src/04-components/feedback/progress-circle/index.scss +92 -0
  15. package/src/04-components/feedback/progress-circle/progress-circle-visual.png +0 -0
  16. package/src/04-components/feedback/progress-circle/progress-circle.api.json +53 -0
  17. package/src/04-components/feedback/progress-circle/progress-circle.docs.json +377 -0
  18. package/src/04-components/feedback/progress-circle/progress-circle.visual.spec.ts +14 -0
  19. package/src/04-components/forms/checkbox-group/checkbox-group-visual.png +0 -0
  20. package/src/04-components/forms/checkbox-group/checkbox-group.api.json +54 -0
  21. package/src/04-components/forms/checkbox-group/checkbox-group.docs.json +338 -0
  22. package/src/04-components/forms/checkbox-group/checkbox-group.visual.spec.ts +14 -0
  23. package/src/04-components/forms/checkbox-group/index.scss +84 -0
  24. package/src/04-components/forms/fieldset/fieldset-visual.png +0 -0
  25. package/src/04-components/forms/fieldset/fieldset.api.json +49 -0
  26. package/src/04-components/forms/fieldset/fieldset.docs.json +520 -0
  27. package/src/04-components/forms/fieldset/fieldset.visual.spec.ts +14 -0
  28. package/src/04-components/forms/fieldset/index.scss +69 -0
  29. package/src/04-components/forms/form/form-visual.png +0 -0
  30. package/src/04-components/forms/form/form.api.json +38 -0
  31. package/src/04-components/forms/form/form.docs.json +482 -0
  32. package/src/04-components/forms/form/form.visual.spec.ts +14 -0
  33. package/src/04-components/forms/form/index.scss +62 -0
  34. package/src/04-components/forms/radio-group/index.scss +84 -0
  35. package/src/04-components/forms/radio-group/radio-group-visual.png +0 -0
  36. package/src/04-components/forms/radio-group/radio-group.api.json +54 -0
  37. package/src/04-components/forms/radio-group/radio-group.docs.json +350 -0
  38. package/src/04-components/forms/radio-group/radio-group.visual.spec.ts +14 -0
  39. package/src/04-components/forms/search-input/index.scss +172 -0
  40. package/src/04-components/forms/search-input/search-input-visual.png +0 -0
  41. package/src/04-components/forms/search-input/search-input.api.json +85 -0
  42. package/src/04-components/forms/search-input/search-input.docs.json +257 -0
  43. package/src/04-components/forms/search-input/search-input.visual.spec.ts +14 -0
  44. package/src/04-components/forms/slider/index.scss +153 -0
  45. package/src/04-components/forms/slider/slider-visual.png +0 -0
  46. package/src/04-components/forms/slider/slider.api.json +70 -0
  47. package/src/04-components/forms/slider/slider.docs.json +144 -0
  48. package/src/04-components/forms/slider/slider.visual.spec.ts +14 -0
  49. package/src/04-components/index.scss +11 -0
  50. package/src/04-components/typography/code-block/code-block-visual.png +0 -0
  51. package/src/04-components/typography/code-block/code-block.api.json +56 -0
  52. package/src/04-components/typography/code-block/code-block.docs.json +289 -0
  53. package/src/04-components/typography/code-block/code-block.visual.spec.ts +14 -0
  54. package/src/04-components/typography/code-block/index.scss +87 -0
  55. package/src/04-components/typography/list/index.scss +65 -0
  56. package/src/04-components/typography/list/list-visual.png +0 -0
  57. package/src/04-components/typography/list/list.api.json +33 -0
  58. package/src/04-components/typography/list/list.docs.json +293 -0
  59. package/src/04-components/typography/list/list.visual.spec.ts +14 -0
@@ -0,0 +1,101 @@
1
+ @use '../../../00-config/tokens/variables' as t;
2
+
3
+ // @component close-button
4
+ // @element button
5
+
6
+ @layer components.tokens {
7
+ .close-button {
8
+ --_size: var(--ui-close-button-size, var(--ui-row-2, #{t.$row-2}));
9
+ --_icon-size: var(--ui-close-button-icon-size, var(--ui-size-md, #{t.size(md)}));
10
+ --_color: var(--ui-close-button-color, var(--ui-color-text-muted, #{t.$color-text-muted}));
11
+ --_bg: var(--ui-close-button-bg, transparent);
12
+ --_hover-bg: var(--ui-close-button-hover-bg, var(--ui-color-bg-muted, #{t.$color-bg-muted}));
13
+ --_radius: var(--ui-close-button-radius, var(--ui-radius-md, #{t.$radius-md}));
14
+ }
15
+
16
+ // @modifier size
17
+ .close-button--sm {
18
+ --_size: var(--ui-close-button-size-sm, calc(#{t.$unit} * 3));
19
+ --_icon-size: var(--ui-close-button-icon-size-sm, var(--ui-size-sm, #{t.size(sm)}));
20
+ }
21
+
22
+ .close-button--lg {
23
+ --_size: var(--ui-close-button-size-lg, var(--ui-row-3, #{t.$row-3}));
24
+ --_icon-size: var(--ui-close-button-icon-size-lg, var(--ui-size-lg, #{t.size(lg)}));
25
+ }
26
+
27
+ // @modifier boolean subtle
28
+ .close-button--subtle {
29
+ --_color: var(--ui-close-button-subtle-color, var(--ui-color-border-strong, #{t.$color-border-strong}));
30
+ --_hover-bg: var(--ui-close-button-subtle-hover-bg, var(--ui-color-bg-subtle, #{t.$color-bg-subtle}));
31
+ }
32
+ }
33
+
34
+ @layer components.styles {
35
+ .close-button {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+
40
+ block-size: var(--_size);
41
+ inline-size: var(--_size);
42
+ padding: 0;
43
+ margin: 0;
44
+
45
+ font: inherit;
46
+ color: var(--_color);
47
+
48
+ background: var(--_bg);
49
+ border: none;
50
+ border-radius: var(--_radius);
51
+ cursor: pointer;
52
+ appearance: none;
53
+
54
+ transition:
55
+ background-color var(--ui-duration-base, 150ms) var(--ui-ease-default, ease),
56
+ color var(--ui-duration-base, 150ms) var(--ui-ease-default, ease);
57
+
58
+ &:hover,
59
+ &--hover {
60
+ color: var(--ui-color-text, #{t.$color-text});
61
+
62
+ background: var(--_hover-bg);
63
+ }
64
+
65
+ &:focus-visible,
66
+ &--focus {
67
+ outline: var(--ui-border-width-md, #{t.$border-width-md}) solid var(--ui-color-focus, #{t.$color-focus});
68
+ outline-offset: var(--ui-border-width-md, #{t.$border-width-md});
69
+ }
70
+
71
+ &:active,
72
+ &--active {
73
+ transform: scale(0.92);
74
+ }
75
+
76
+ &:disabled {
77
+ opacity: 0.5;
78
+ cursor: not-allowed;
79
+
80
+ &:hover {
81
+ color: var(--_color);
82
+
83
+ background: var(--_bg);
84
+ transform: none;
85
+ }
86
+ }
87
+ }
88
+
89
+ .close-button__icon {
90
+ flex-shrink: 0;
91
+
92
+ block-size: var(--_icon-size);
93
+ inline-size: var(--_icon-size);
94
+
95
+ fill: none;
96
+ stroke: currentcolor;
97
+ stroke-width: 2;
98
+ stroke-linecap: round;
99
+ stroke-linejoin: round;
100
+ }
101
+ }
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "image",
3
+ "element": "figure",
4
+ "modifiers": {
5
+ "size": {
6
+ "values": ["sm", "md", "lg", "xl", "full"]
7
+ },
8
+ "rounded": {
9
+ "type": "boolean"
10
+ },
11
+ "circle": {
12
+ "type": "boolean"
13
+ },
14
+ "object-fit": {
15
+ "values": ["cover", "contain"]
16
+ }
17
+ },
18
+ "elements": {
19
+ "img": {},
20
+ "caption": {}
21
+ },
22
+ "cssVars": [
23
+ {
24
+ "name": "--ui-image-size",
25
+ "default": "auto"
26
+ },
27
+ {
28
+ "name": "--ui-image-size-sm",
29
+ "default": "calc(var(--unit) * 12)"
30
+ },
31
+ {
32
+ "name": "--ui-image-size-md",
33
+ "default": "calc(var(--unit) * 24)"
34
+ },
35
+ {
36
+ "name": "--ui-image-size-lg",
37
+ "default": "calc(var(--unit) * 40)"
38
+ },
39
+ {
40
+ "name": "--ui-image-size-xl",
41
+ "default": "calc(var(--unit) * 60)"
42
+ },
43
+ {
44
+ "name": "--ui-image-bg",
45
+ "default": "var(--ui-color-bg-muted)"
46
+ },
47
+ {
48
+ "name": "--ui-image-radius",
49
+ "default": "0"
50
+ },
51
+ {
52
+ "name": "--ui-image-radius-rounded",
53
+ "default": "var(--ui-radius-lg)"
54
+ },
55
+ {
56
+ "name": "--ui-image-radius-circle",
57
+ "default": "50%"
58
+ },
59
+ {
60
+ "name": "--ui-image-object-fit",
61
+ "default": "cover"
62
+ },
63
+ {
64
+ "name": "--ui-image-caption-color",
65
+ "default": "var(--ui-color-text-muted)"
66
+ },
67
+ {
68
+ "name": "--ui-image-caption-font-size",
69
+ "default": "var(--ui-font-size-sm)"
70
+ },
71
+ {
72
+ "name": "--ui-image-caption-spacing",
73
+ "default": "var(--ui-space-1)"
74
+ }
75
+ ]
76
+ }
@@ -0,0 +1,337 @@
1
+ {
2
+ "id": "image",
3
+ "type": "component",
4
+ "title": "Image",
5
+ "description": "Responsive image with fallback placeholder, optional caption, and shape modifiers.",
6
+ "api": "./image.api.json",
7
+ "sections": [
8
+ {
9
+ "title": "Default",
10
+ "examples": [
11
+ {
12
+ "items": [
13
+ {
14
+ "tag": "figure",
15
+ "class": "ui-image",
16
+ "children": [
17
+ {
18
+ "tag": "img",
19
+ "class": "ui-image__img",
20
+ "attrs": {
21
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='160'%3E%3Crect fill='%23b0bec5' width='192' height='160'/%3E%3C/svg%3E",
22
+ "alt": "Placeholder"
23
+ }
24
+ }
25
+ ]
26
+ }
27
+ ],
28
+ "code": "<figure class=\"ui-image\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Description\">\n</figure>"
29
+ }
30
+ ]
31
+ },
32
+ {
33
+ "title": "Sizes",
34
+ "examples": [
35
+ {
36
+ "layout": "cluster",
37
+ "items": [
38
+ {
39
+ "tag": "figure",
40
+ "class": "ui-image ui-image--sm",
41
+ "children": [
42
+ {
43
+ "tag": "img",
44
+ "class": "ui-image__img",
45
+ "attrs": {
46
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Crect fill='%2390a4ae' width='96' height='96'/%3E%3C/svg%3E",
47
+ "alt": "Small"
48
+ }
49
+ }
50
+ ]
51
+ },
52
+ {
53
+ "tag": "figure",
54
+ "class": "ui-image ui-image--md",
55
+ "children": [
56
+ {
57
+ "tag": "img",
58
+ "class": "ui-image__img",
59
+ "attrs": {
60
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192'%3E%3Crect fill='%2378909c' width='192' height='192'/%3E%3C/svg%3E",
61
+ "alt": "Medium"
62
+ }
63
+ }
64
+ ]
65
+ },
66
+ {
67
+ "tag": "figure",
68
+ "class": "ui-image ui-image--lg",
69
+ "children": [
70
+ {
71
+ "tag": "img",
72
+ "class": "ui-image__img",
73
+ "attrs": {
74
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Crect fill='%23607d8b' width='320' height='320'/%3E%3C/svg%3E",
75
+ "alt": "Large"
76
+ }
77
+ }
78
+ ]
79
+ }
80
+ ],
81
+ "code": "<figure class=\"ui-image ui-image--sm\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Small\">\n</figure>\n<figure class=\"ui-image ui-image--md\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Medium\">\n</figure>\n<figure class=\"ui-image ui-image--lg\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Large\">\n</figure>"
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ "title": "Rounded",
87
+ "examples": [
88
+ {
89
+ "items": [
90
+ {
91
+ "tag": "figure",
92
+ "class": "ui-image ui-image--md ui-image--rounded",
93
+ "children": [
94
+ {
95
+ "tag": "img",
96
+ "class": "ui-image__img",
97
+ "attrs": {
98
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='140'%3E%3Crect fill='%234db6ac' width='192' height='140'/%3E%3C/svg%3E",
99
+ "alt": "Rounded"
100
+ }
101
+ }
102
+ ]
103
+ }
104
+ ],
105
+ "code": "<figure class=\"ui-image ui-image--rounded\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Rounded\">\n</figure>"
106
+ }
107
+ ]
108
+ },
109
+ {
110
+ "title": "Circle",
111
+ "examples": [
112
+ {
113
+ "layout": "cluster",
114
+ "items": [
115
+ {
116
+ "tag": "figure",
117
+ "class": "ui-image ui-image--sm ui-image--circle",
118
+ "children": [
119
+ {
120
+ "tag": "img",
121
+ "class": "ui-image__img",
122
+ "attrs": {
123
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Crect fill='%23ce93d8' width='96' height='96'/%3E%3C/svg%3E",
124
+ "alt": "Circle small"
125
+ }
126
+ }
127
+ ]
128
+ },
129
+ {
130
+ "tag": "figure",
131
+ "class": "ui-image ui-image--md ui-image--circle",
132
+ "children": [
133
+ {
134
+ "tag": "img",
135
+ "class": "ui-image__img",
136
+ "attrs": {
137
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='192'%3E%3Crect fill='%23ba68c8' width='192' height='192'/%3E%3C/svg%3E",
138
+ "alt": "Circle medium"
139
+ }
140
+ }
141
+ ]
142
+ }
143
+ ],
144
+ "code": "<figure class=\"ui-image ui-image--circle\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Circle\">\n</figure>"
145
+ }
146
+ ]
147
+ },
148
+ {
149
+ "title": "Object Fit",
150
+ "examples": [
151
+ {
152
+ "layout": "cluster",
153
+ "items": [
154
+ {
155
+ "tag": "figure",
156
+ "class": "ui-image ui-image--md ui-image--cover",
157
+ "children": [
158
+ {
159
+ "tag": "img",
160
+ "class": "ui-image__img",
161
+ "attrs": {
162
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='150'%3E%3Crect fill='%2364b5f6' width='300' height='150'/%3E%3Ctext x='150' y='80' text-anchor='middle' fill='%23fff' font-size='16'%3Ecover%3C/text%3E%3C/svg%3E",
163
+ "alt": "Cover fit"
164
+ }
165
+ }
166
+ ]
167
+ },
168
+ {
169
+ "tag": "figure",
170
+ "class": "ui-image ui-image--md ui-image--contain",
171
+ "children": [
172
+ {
173
+ "tag": "img",
174
+ "class": "ui-image__img",
175
+ "attrs": {
176
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='150'%3E%3Crect fill='%2381c784' width='300' height='150'/%3E%3Ctext x='150' y='80' text-anchor='middle' fill='%23fff' font-size='16'%3Econtain%3C/text%3E%3C/svg%3E",
177
+ "alt": "Contain fit"
178
+ }
179
+ }
180
+ ]
181
+ }
182
+ ],
183
+ "code": "<figure class=\"ui-image ui-image--cover\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Cover\">\n</figure>\n<figure class=\"ui-image ui-image--contain\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Contain\">\n</figure>"
184
+ }
185
+ ]
186
+ },
187
+ {
188
+ "title": "Caption",
189
+ "examples": [
190
+ {
191
+ "items": [
192
+ {
193
+ "tag": "figure",
194
+ "class": "ui-image ui-image--md ui-image--rounded",
195
+ "children": [
196
+ {
197
+ "tag": "img",
198
+ "class": "ui-image__img",
199
+ "attrs": {
200
+ "src": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='192' height='140'%3E%3Crect fill='%23ffb74d' width='192' height='140'/%3E%3C/svg%3E",
201
+ "alt": "With caption"
202
+ }
203
+ },
204
+ {
205
+ "tag": "figcaption",
206
+ "class": "ui-image__caption",
207
+ "text": "An optional image caption"
208
+ }
209
+ ]
210
+ }
211
+ ],
212
+ "code": "<figure class=\"ui-image\">\n <img class=\"ui-image__img\" src=\"...\" alt=\"Description\">\n <figcaption class=\"ui-image__caption\">Caption text</figcaption>\n</figure>"
213
+ }
214
+ ]
215
+ },
216
+ {
217
+ "title": "Fallback",
218
+ "examples": [
219
+ {
220
+ "layout": "cluster",
221
+ "items": [
222
+ {
223
+ "tag": "figure",
224
+ "class": "ui-image ui-image--sm",
225
+ "children": [
226
+ {
227
+ "tag": "img",
228
+ "class": "ui-image__img",
229
+ "attrs": {
230
+ "src": "",
231
+ "alt": "Broken image"
232
+ }
233
+ }
234
+ ]
235
+ },
236
+ {
237
+ "tag": "figure",
238
+ "class": "ui-image ui-image--sm ui-image--rounded",
239
+ "children": [
240
+ {
241
+ "tag": "img",
242
+ "class": "ui-image__img",
243
+ "attrs": {
244
+ "src": "",
245
+ "alt": "Broken rounded"
246
+ }
247
+ }
248
+ ]
249
+ },
250
+ {
251
+ "tag": "figure",
252
+ "class": "ui-image ui-image--sm ui-image--circle",
253
+ "children": [
254
+ {
255
+ "tag": "img",
256
+ "class": "ui-image__img",
257
+ "attrs": {
258
+ "src": "",
259
+ "alt": "Broken circle"
260
+ }
261
+ }
262
+ ]
263
+ }
264
+ ],
265
+ "code": "<figure class=\"ui-image\">\n <img class=\"ui-image__img\" src=\"\" alt=\"Fallback shown\">\n</figure>"
266
+ }
267
+ ]
268
+ }
269
+ ],
270
+ "customization": [
271
+ {
272
+ "token": "--ui-image-size",
273
+ "default": "auto",
274
+ "description": "Default image dimensions"
275
+ },
276
+ {
277
+ "token": "--ui-image-size-sm",
278
+ "default": "calc(var(--unit) * 12)",
279
+ "description": "Small size"
280
+ },
281
+ {
282
+ "token": "--ui-image-size-md",
283
+ "default": "calc(var(--unit) * 24)",
284
+ "description": "Medium size"
285
+ },
286
+ {
287
+ "token": "--ui-image-size-lg",
288
+ "default": "calc(var(--unit) * 40)",
289
+ "description": "Large size"
290
+ },
291
+ {
292
+ "token": "--ui-image-size-xl",
293
+ "default": "calc(var(--unit) * 60)",
294
+ "description": "Extra large size"
295
+ },
296
+ {
297
+ "token": "--ui-image-bg",
298
+ "default": "var(--ui-color-bg-muted)",
299
+ "description": "Fallback background"
300
+ },
301
+ {
302
+ "token": "--ui-image-radius",
303
+ "default": "0",
304
+ "description": "Border radius"
305
+ },
306
+ {
307
+ "token": "--ui-image-radius-rounded",
308
+ "default": "var(--ui-radius-lg)",
309
+ "description": "Rounded variant radius"
310
+ },
311
+ {
312
+ "token": "--ui-image-radius-circle",
313
+ "default": "50%",
314
+ "description": "Circle variant radius"
315
+ },
316
+ {
317
+ "token": "--ui-image-object-fit",
318
+ "default": "cover",
319
+ "description": "Object-fit strategy"
320
+ },
321
+ {
322
+ "token": "--ui-image-caption-color",
323
+ "default": "var(--ui-color-text-muted)",
324
+ "description": "Caption text color"
325
+ },
326
+ {
327
+ "token": "--ui-image-caption-font-size",
328
+ "default": "var(--ui-font-size-sm)",
329
+ "description": "Caption font size"
330
+ },
331
+ {
332
+ "token": "--ui-image-caption-spacing",
333
+ "default": "var(--ui-space-1)",
334
+ "description": "Space between image and caption"
335
+ }
336
+ ]
337
+ }
@@ -0,0 +1,14 @@
1
+ import { resolve } from 'node:path';
2
+ import { expect, test } from '@playwright/test';
3
+ import { saveForLostPixel, setupVisualTestFromDocs, validateGridRhythm } from '../../../testing';
4
+
5
+ const DOCS_PATH = resolve(__dirname, 'image.docs.json');
6
+
7
+ test.describe('image visual regression', () => {
8
+ test('all variations', async ({ page }) => {
9
+ await setupVisualTestFromDocs(page, DOCS_PATH);
10
+ await validateGridRhythm(page, 'image');
11
+ await saveForLostPixel(page, 'image');
12
+ await expect(page.locator('body')).toHaveScreenshot('image.visual.png');
13
+ });
14
+ });
@@ -0,0 +1,103 @@
1
+ @use '../../../00-config/tokens/variables' as t;
2
+
3
+ // @component image
4
+ // @element figure
5
+
6
+ @layer components.tokens {
7
+ .image {
8
+ --_size: var(--ui-image-size, auto);
9
+ --_radius: var(--ui-image-radius, 0);
10
+ --_object-fit: var(--ui-image-object-fit, cover);
11
+ --_bg: var(--ui-image-bg, var(--ui-color-bg-muted, #{t.$color-bg-muted}));
12
+ --_caption-color: var(--ui-image-caption-color, var(--ui-color-text-muted, #{t.$color-text-muted}));
13
+ --_caption-font-size: var(--ui-image-caption-font-size, var(--ui-font-size-sm, #{t.$font-size-sm}));
14
+ --_caption-spacing: var(--ui-image-caption-spacing, var(--ui-space-1));
15
+ }
16
+
17
+ // @modifier size
18
+ .image--sm {
19
+ --_size: var(--ui-image-size-sm, calc(#{t.$unit} * 12));
20
+ }
21
+
22
+ .image--md {
23
+ --_size: var(--ui-image-size-md, calc(#{t.$unit} * 24));
24
+ }
25
+
26
+ .image--lg {
27
+ --_size: var(--ui-image-size-lg, calc(#{t.$unit} * 40));
28
+ }
29
+
30
+ .image--xl {
31
+ --_size: var(--ui-image-size-xl, calc(#{t.$unit} * 60));
32
+ }
33
+
34
+ .image--full {
35
+ --_size: 100%;
36
+ }
37
+
38
+ // @modifier boolean rounded
39
+ .image--rounded {
40
+ --_radius: var(--ui-image-radius-rounded, var(--ui-radius-lg, #{t.$radius-lg}));
41
+ }
42
+
43
+ // @modifier boolean circle
44
+ .image--circle {
45
+ --_radius: var(--ui-image-radius-circle, 50%);
46
+ }
47
+
48
+ // @modifier object-fit
49
+ .image--cover {
50
+ --_object-fit: cover;
51
+ }
52
+
53
+ .image--contain {
54
+ --_object-fit: contain;
55
+ }
56
+ }
57
+
58
+ @layer components.styles {
59
+ .image {
60
+ display: inline-block;
61
+
62
+ max-inline-size: 100%;
63
+ padding: 0;
64
+ margin: 0;
65
+ }
66
+
67
+ .image__img {
68
+ display: block;
69
+
70
+ block-size: var(--_size);
71
+ inline-size: var(--_size);
72
+ max-inline-size: 100%;
73
+
74
+ object-fit: var(--_object-fit);
75
+
76
+ background: var(--_bg);
77
+ border-radius: var(--_radius);
78
+ }
79
+
80
+ // Fallback when image fails to load — :not([src]) or broken src
81
+ // The background from --_bg shows through as placeholder
82
+ .image__img:not([src]),
83
+ .image__img[src=''] {
84
+ aspect-ratio: 1 / 1;
85
+
86
+ // Ensure minimum dimensions for empty state
87
+ min-block-size: calc(#{t.$unit} * 8);
88
+ min-inline-size: calc(#{t.$unit} * 8);
89
+ }
90
+
91
+ .image__caption {
92
+ margin-block-start: var(--_caption-spacing);
93
+
94
+ font-size: var(--_caption-font-size);
95
+ line-height: var(--ui-row-1, #{t.$row-1});
96
+ color: var(--_caption-color);
97
+ }
98
+
99
+ // Circle needs equal aspect ratio to stay round
100
+ .image--circle .image__img {
101
+ aspect-ratio: 1 / 1;
102
+ }
103
+ }