css-tags 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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +875 -0
  3. package/carousel.js +86 -0
  4. package/components/accessibility.css +51 -0
  5. package/components/actions.css +76 -0
  6. package/components/alert.css +122 -0
  7. package/components/application-patterns.css +122 -0
  8. package/components/badge.css +125 -0
  9. package/components/box-extra.css +220 -0
  10. package/components/box.css +75 -0
  11. package/components/card.css +130 -0
  12. package/components/carousel.css +76 -0
  13. package/components/chip.css +71 -0
  14. package/components/container.css +55 -0
  15. package/components/content-patterns.css +234 -0
  16. package/components/disclosure.css +581 -0
  17. package/components/divider.css +68 -0
  18. package/components/flex.css +59 -0
  19. package/components/form-patterns.css +273 -0
  20. package/components/form.css +130 -0
  21. package/components/grid.css +82 -0
  22. package/components/identity.css +59 -0
  23. package/components/img-container.css +141 -0
  24. package/components/img-container.js +75 -0
  25. package/components/list.css +69 -0
  26. package/components/loading.css +112 -0
  27. package/components/masonry.css +48 -0
  28. package/components/modal.css +73 -0
  29. package/components/navigation-patterns.css +245 -0
  30. package/components/navigation.css +200 -0
  31. package/components/popover.css +49 -0
  32. package/components/site-shell.css +180 -0
  33. package/components/status.css +110 -0
  34. package/components/table.css +98 -0
  35. package/components/tabs.css +103 -0
  36. package/components/tooltip.css +87 -0
  37. package/components/tooltips.css +73 -0
  38. package/components/view-transition.css +73 -0
  39. package/core/base.css +62 -0
  40. package/core/defaults.css +490 -0
  41. package/core/engine.css +32 -0
  42. package/core/mixins.css +376 -0
  43. package/core/palette-accent.css +8 -0
  44. package/core/palette-base.css +107 -0
  45. package/core/palette-extended.css +142 -0
  46. package/core/palette-feedback.css +62 -0
  47. package/core/palette.css +7 -0
  48. package/core/reset.css +270 -0
  49. package/core/text.css +171 -0
  50. package/core/theme.css +608 -0
  51. package/core/tokens.css +488 -0
  52. package/core/typography.css +327 -0
  53. package/index.css +66 -0
  54. package/layouts/layout-extra.css +204 -0
  55. package/layouts/layout-extras-helpers.css +19 -0
  56. package/layouts/layout.css +348 -0
  57. package/package.json +66 -0
  58. package/theme-generator.css +979 -0
  59. package/themes/example-brand.css +59 -0
  60. package/themes/theme-packs.css +31 -0
  61. package/types/css-tags.d.ts +482 -0
  62. package/utilities/utilities.css +564 -0
  63. package/view-transition.js +111 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * flex.css
3
+ *
4
+ * A declarative flexbox layout component.
5
+ * ------------------------------------------------------------------------------
6
+ * This component provides an intuitive way to create one-dimensional layouts
7
+ * using Flexbox, configured declaratively through HTML attributes.
8
+ *
9
+ * @feature {Flexbox} - For powerful and flexible one-dimensional layouts.
10
+ * @feature {CSS Custom Properties} - For clean and maintainable style definitions.
11
+ * @feature {attr()} - Powers the entire declarative API.
12
+ * @feature {CSS Nesting} - Co-locates child item styles for better organization.
13
+ */
14
+
15
+ :is(flex, [data-flex], .flex) {
16
+ /* --- Core Flex Container Properties --- */
17
+ --flex-direction: attr(direction type(*), row);
18
+ --flex-wrap: attr(wrap type(*), nowrap);
19
+ --justify-content: attr(justify type(*), flex-start);
20
+ --align-items: attr(align type(*), stretch);
21
+ --gap: attr(gap type(*), 1.5rem);
22
+
23
+ display: flex;
24
+ flex-direction: var(--flex-direction);
25
+ flex-wrap: var(--flex-wrap);
26
+ justify-content: var(--justify-content);
27
+ align-items: var(--align-items);
28
+ gap: var(--gap);
29
+
30
+ /*
31
+ * --- Flex Item Styling (applied to direct children) ---
32
+ * This uses the child combinator `>` to style any element placed
33
+ * directly inside the <flex> container.
34
+ */
35
+ & > * {
36
+ /* --- Individual Item Sizing and Ordering --- */
37
+ flex-grow: attr(grow type(*), 0);
38
+ flex-shrink: attr(shrink type(*), 1);
39
+ flex-basis: attr(basis type(*), auto);
40
+ order: attr(order type(*), 0);
41
+
42
+ /* --- Individual Item Alignment --- */
43
+ align-self: attr(align-self type(*), auto);
44
+ }
45
+
46
+ /*
47
+ * --- Theming Example ---
48
+ * A `theme="brand"` attribute could apply a pre-defined theme mixin.
49
+ * This demonstrates how components can integrate with the mixin library.
50
+ */
51
+ &[theme="brand"] {
52
+ /*
53
+ @apply --theme-colors(
54
+ --primary: var(--brand-blue),
55
+ --bg: var(--brand-surface)
56
+ );
57
+ */
58
+ }
59
+ }
@@ -0,0 +1,273 @@
1
+ /** Native-first compound form patterns. */
2
+
3
+ input[type="checkbox"][role="switch"] {
4
+ --_switch-width: var(--switch-width, 2.75rem);
5
+ --_switch-height: var(--switch-height, 1.5rem);
6
+ --_switch-padding: var(--switch-padding, 0.1875rem);
7
+ --_switch-thumb: calc(var(--_switch-height) - (2 * var(--_switch-padding)));
8
+
9
+ appearance: none;
10
+ box-sizing: border-box;
11
+ display: inline-grid;
12
+ align-items: center;
13
+ inline-size: var(--_switch-width);
14
+ block-size: var(--_switch-height);
15
+ padding: var(--_switch-padding);
16
+ margin: 0;
17
+ border: var(--switch-border-width, var(--border-width, 1px)) solid
18
+ var(--switch-border-color, var(--outline-overt));
19
+ border-radius: var(--switch-radius, var(--radius-full, 9999px));
20
+ background: var(--switch-background, var(--surface-overt));
21
+ cursor: pointer;
22
+ transition: background-color 160ms ease-out, border-color 160ms ease-out;
23
+ }
24
+
25
+ input[type="checkbox"][role="switch"]::before {
26
+ content: "";
27
+ inline-size: var(--_switch-thumb);
28
+ block-size: var(--_switch-thumb);
29
+ border-radius: 50%;
30
+ background: var(--switch-thumb-background, var(--surface-default));
31
+ box-shadow: var(--switch-thumb-shadow, var(--shadow-sm));
32
+ transform: translateX(0);
33
+ transition: transform 160ms ease-out;
34
+ }
35
+
36
+ input[type="checkbox"][role="switch"]:checked {
37
+ border-color: var(--switch-checked-border-color, var(--accent));
38
+ background: var(--switch-checked-background, var(--accent));
39
+ }
40
+
41
+ input[type="checkbox"][role="switch"]:checked::before {
42
+ transform: translateX(calc(var(--_switch-width) - var(--_switch-thumb) - (2 * var(--_switch-padding)) - (2 * var(--switch-border-width, var(--border-width, 1px)))));
43
+ }
44
+
45
+ input[type="checkbox"][role="switch"]:focus-visible {
46
+ outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color);
47
+ outline-offset: var(--focus-ring-offset, 2px);
48
+ }
49
+
50
+ input[type="checkbox"][role="switch"]:disabled {
51
+ opacity: var(--opacity-disabled, 0.5);
52
+ cursor: not-allowed;
53
+ }
54
+
55
+ :is(input-group, [data-input-group], .input-group) {
56
+ display: flex;
57
+ align-items: stretch;
58
+ inline-size: 100%;
59
+ min-inline-size: 0;
60
+ }
61
+
62
+ :is(input-group, [data-input-group], .input-group) > * {
63
+ min-inline-size: 0;
64
+ margin: 0;
65
+ border-radius: 0;
66
+ }
67
+
68
+ :is(input-group, [data-input-group], .input-group) > :first-child {
69
+ border-start-start-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
70
+ border-end-start-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
71
+ }
72
+
73
+ :is(input-group, [data-input-group], .input-group) > :last-child {
74
+ border-start-end-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
75
+ border-end-end-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
76
+ }
77
+
78
+ :is(input-group, [data-input-group], .input-group) > :not(:first-child) {
79
+ margin-inline-start: calc(-1 * var(--input-group-border-overlap, var(--border-width, 1px)));
80
+ }
81
+
82
+ :is(input-group, [data-input-group], .input-group) > :is(input, select, textarea) {
83
+ flex: 1 1 auto;
84
+ }
85
+
86
+ :is([data-input-affix], .input-affix) {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ padding-inline: var(--input-affix-padding-inline, var(--space-sm, 0.75rem));
90
+ border: var(--border-width, 1px) solid var(--form-control-border-color, var(--outline-default));
91
+ background: var(--input-affix-background, var(--surface-subtle));
92
+ color: var(--input-affix-color, var(--text-subtle));
93
+ white-space: nowrap;
94
+ }
95
+
96
+ :is(input-group, [data-input-group], .input-group):focus-within {
97
+ position: relative;
98
+ z-index: 1;
99
+ }
100
+
101
+ @media (max-width: 30rem) {
102
+ :is(input-group, [data-input-group], .input-group)[data-stack="auto"] {
103
+ flex-direction: column;
104
+ }
105
+
106
+ :is(input-group, [data-input-group], .input-group)[data-stack="auto"] > * {
107
+ margin: 0 0 calc(-1 * var(--input-group-border-overlap, var(--border-width, 1px)));
108
+ border-radius: 0;
109
+ }
110
+
111
+ :is(input-group, [data-input-group], .input-group)[data-stack="auto"] > :first-child {
112
+ border-start-start-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
113
+ border-start-end-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
114
+ }
115
+
116
+ :is(input-group, [data-input-group], .input-group)[data-stack="auto"] > :last-child {
117
+ margin-block-end: 0;
118
+ border-end-start-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
119
+ border-end-end-radius: var(--input-group-radius, var(--radius-md, 0.5rem));
120
+ }
121
+ }
122
+
123
+ :is(search-input, [data-search-input], .search-input) {
124
+ display: grid;
125
+ grid-template-columns: auto minmax(0, 1fr) auto;
126
+ align-items: center;
127
+ inline-size: 100%;
128
+ gap: var(--search-input-gap, var(--space-sm, 0.5rem));
129
+ padding-inline: var(--search-input-padding-inline, var(--space-sm, 0.75rem));
130
+ border: var(--search-input-border-width, var(--border-width, 1px)) solid
131
+ var(--search-input-border-color, var(--outline-default));
132
+ border-radius: var(--search-input-radius, var(--radius-md, 0.5rem));
133
+ background: var(--search-input-background, var(--surface-default));
134
+ color: var(--search-input-color, var(--text-default));
135
+ }
136
+
137
+ :is(search-input, [data-search-input], .search-input) > input[type="search"] {
138
+ inline-size: 100%;
139
+ min-inline-size: 0;
140
+ padding: var(--search-input-padding-block, var(--space-sm, 0.625rem)) 0;
141
+ border: 0;
142
+ outline: 0;
143
+ background: transparent;
144
+ color: inherit;
145
+ font: inherit;
146
+ }
147
+
148
+ :is(search-input, [data-search-input], .search-input):focus-within {
149
+ border-color: var(--outline-focus);
150
+ box-shadow: 0 0 0 var(--focus-ring-width, 2px) var(--focus-ring-color);
151
+ }
152
+
153
+ :is(search-input, [data-search-input], .search-input) > :is(svg, [data-search-icon]) {
154
+ inline-size: var(--search-input-icon-size, 1.125rem);
155
+ block-size: var(--search-input-icon-size, 1.125rem);
156
+ color: var(--search-input-icon-color, var(--text-muted));
157
+ }
158
+
159
+ :is(file-dropzone, [data-file-dropzone], .file-dropzone) {
160
+ position: relative;
161
+ display: grid;
162
+ place-items: center;
163
+ gap: var(--dropzone-gap, var(--space-sm, 0.5rem));
164
+ min-block-size: var(--dropzone-min-height, 10rem);
165
+ padding: var(--dropzone-padding, var(--space-xl, 2rem));
166
+ border: var(--dropzone-border-width, 2px) dashed
167
+ var(--dropzone-border-color, var(--outline-default));
168
+ border-radius: var(--dropzone-radius, var(--radius-lg, 0.75rem));
169
+ background: var(--dropzone-background, var(--surface-subtle));
170
+ color: var(--dropzone-color, var(--text-default));
171
+ text-align: center;
172
+ }
173
+
174
+ :is(file-dropzone, [data-file-dropzone], .file-dropzone) > input[type="file"] {
175
+ position: absolute;
176
+ inset: 0;
177
+ inline-size: 100%;
178
+ block-size: 100%;
179
+ opacity: 0;
180
+ cursor: pointer;
181
+ }
182
+
183
+ :is(file-dropzone, [data-file-dropzone], .file-dropzone):is(:hover, :focus-within, [data-dragover="true"]) {
184
+ border-color: var(--dropzone-active-border-color, var(--accent));
185
+ background: var(--dropzone-active-background, var(--accent-subtle));
186
+ }
187
+
188
+ :is(file-dropzone, [data-file-dropzone], .file-dropzone):focus-within {
189
+ outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color);
190
+ outline-offset: var(--focus-ring-offset, 2px);
191
+ }
192
+
193
+ :is(rating-output, [data-rating-output], .rating-output) {
194
+ --_rating: var(--rating-value, 0%);
195
+ --_rating-empty: var(--rating-empty-color, var(--surface-overt));
196
+ --_rating-fill: var(--rating-fill-color, var(--warning));
197
+
198
+ display: inline-block;
199
+ inline-size: max-content;
200
+ color: transparent;
201
+ font-size: var(--rating-size, 1.25rem);
202
+ line-height: 1;
203
+ letter-spacing: var(--rating-gap, 0.125em);
204
+ background: linear-gradient(90deg, var(--_rating-fill) var(--_rating), var(--_rating-empty) var(--_rating));
205
+ background-clip: text;
206
+ }
207
+
208
+ :is(rating-input, [data-rating-input], .rating-input) {
209
+ display: inline-flex;
210
+ flex-direction: row;
211
+ direction: rtl;
212
+ inline-size: max-content;
213
+ padding: 0;
214
+ border: 0;
215
+ }
216
+
217
+ :is(rating-input, [data-rating-input], .rating-input) > label {
218
+ color: var(--rating-empty-color, var(--surface-overt));
219
+ font-size: var(--rating-size, 1.5rem);
220
+ line-height: 1;
221
+ cursor: pointer;
222
+ }
223
+
224
+ :is(rating-input, [data-rating-input], .rating-input) input {
225
+ position: absolute;
226
+ inline-size: 1px;
227
+ block-size: 1px;
228
+ opacity: 0;
229
+ }
230
+
231
+ :is(rating-input, [data-rating-input], .rating-input) > label:has(input:checked),
232
+ :is(rating-input, [data-rating-input], .rating-input) > label:has(input:checked) ~ label,
233
+ :is(rating-input, [data-rating-input], .rating-input) > label:hover,
234
+ :is(rating-input, [data-rating-input], .rating-input) > label:hover ~ label {
235
+ color: var(--rating-fill-color, var(--warning));
236
+ }
237
+
238
+ :is(rating-input, [data-rating-input], .rating-input) > label:has(input:focus-visible) {
239
+ outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color);
240
+ outline-offset: var(--focus-ring-offset, 2px);
241
+ }
242
+
243
+ :is(reaction-select, [data-reaction-select], .reaction-select) {
244
+ display: inline-flex;
245
+ }
246
+
247
+ :is(reaction-select, [data-reaction-select], .reaction-select) > select {
248
+ min-inline-size: var(--reaction-select-min-width, 8rem);
249
+ }
250
+
251
+ @supports (appearance: base-select) {
252
+ :is(reaction-select, [data-reaction-select], .reaction-select) > select,
253
+ :is(reaction-select, [data-reaction-select], .reaction-select) > select::picker(select) {
254
+ appearance: base-select;
255
+ }
256
+
257
+ :is(reaction-select, [data-reaction-select], .reaction-select) option {
258
+ padding: var(--reaction-option-padding, var(--space-sm, 0.75rem));
259
+ }
260
+ }
261
+
262
+ @media (prefers-reduced-motion: reduce) {
263
+ input[type="checkbox"][role="switch"],
264
+ input[type="checkbox"][role="switch"]::before {
265
+ transition: none;
266
+ }
267
+ }
268
+
269
+ @media (forced-colors: active) {
270
+ input[type="checkbox"][role="switch"]:checked {
271
+ background: Highlight;
272
+ }
273
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * form.css
3
+ *
4
+ * Explicit class hooks for native form controls. Classes are placed directly
5
+ * on the semantic element so the public API works without scope-root quirks.
6
+ */
7
+
8
+ :is(.form-input, .form-button, .form-select, .form-textarea) {
9
+ box-sizing: border-box;
10
+ font-family: var(--font-family-ui, inherit);
11
+ font-size: var(--font-size-control, var(--font-size-base, 1rem));
12
+ font-weight: var(--form-control-weight, var(--font-weight-normal, 400));
13
+ line-height: var(--line-height-control, var(--line-height-normal, 1.5));
14
+ }
15
+
16
+ :is(.form-input, .form-select, .form-textarea) {
17
+ display: block;
18
+ inline-size: 100%;
19
+ padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
20
+ border: var(--border-width, 1px) solid var(--form-control-border-color, var(--outline-default, var(--outline, currentColor)));
21
+ border-radius: var(--radius-md, 6px);
22
+ background: var(--form-control-background, var(--surface-default));
23
+ color: var(--form-control-color, var(--text-default));
24
+ transition: border-color 150ms ease-out, box-shadow 150ms ease-out, background-color 150ms ease-out;
25
+ }
26
+
27
+ :where(.form-field, label:has(> :is(.form-input, .form-select, .form-textarea))) {
28
+ display: grid;
29
+ inline-size: 100%;
30
+ gap: var(--form-field-gap, var(--space-xs, 0.5rem));
31
+ color: var(--form-label-color, var(--text-overt, var(--text-default)));
32
+ font-weight: var(--form-label-weight, var(--font-weight-medium, 500));
33
+ }
34
+
35
+ :where(.form-field, label:has(> :is(.form-input, .form-select, .form-textarea))) > :is(small, .form-help) {
36
+ color: var(--text-muted);
37
+ font-weight: var(--font-weight-normal, 400);
38
+ }
39
+
40
+ .form-input::placeholder,
41
+ .form-textarea::placeholder {
42
+ color: var(--text-muted);
43
+ opacity: 1;
44
+ }
45
+
46
+ :is(.form-input, .form-select, .form-textarea):hover:not(:disabled, :focus) {
47
+ border-color: var(--outline-overt);
48
+ }
49
+
50
+ :is(.form-input, .form-select, .form-textarea):focus-visible {
51
+ border-color: var(--outline-focus);
52
+ outline: none;
53
+ box-shadow: 0 0 0 var(--focus-ring-width, 2px) var(--focus-ring-color);
54
+ }
55
+
56
+ .form-select {
57
+ cursor: pointer;
58
+ }
59
+
60
+ /* `appearance: base-select` turns the control into a customizable button.
61
+ * Preserve the inline selected-content/picker-icon arrangement instead of
62
+ * inheriting the generic block layout used by text fields. */
63
+ @supports (appearance: base-select) {
64
+ .form-select {
65
+ display: inline-flex;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ }
69
+
70
+ .form-select::picker-icon {
71
+ flex: 0 0 auto;
72
+ margin-inline-start: var(--form-select-icon-gap, var(--space-xs, 0.5rem));
73
+ }
74
+ }
75
+
76
+ .form-textarea {
77
+ min-block-size: 6rem;
78
+ resize: vertical;
79
+ }
80
+
81
+ .form-button {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ inline-size: auto;
86
+ padding: var(--spacing-sm, 0.5rem) var(--spacing-lg, 1.5rem);
87
+ border: var(--form-button-border, 0);
88
+ border-radius: var(--radius-md, 6px);
89
+ background: var(--bg, var(--accent));
90
+ color: var(--fg, var(--text-on-accent, white));
91
+ font-weight: var(--font-weight-medium, 500);
92
+ text-decoration: none;
93
+ cursor: pointer;
94
+ transition: background-color 150ms ease-out, transform 100ms ease-out, box-shadow 150ms ease-out;
95
+ }
96
+
97
+ .form-button:hover:not(:disabled) {
98
+ background: var(--form-button-hover-background, oklch(from var(--bg, var(--accent)) calc(l - 0.08) c h));
99
+ }
100
+
101
+ .form-button:active:not(:disabled) {
102
+ transform: scale(0.98);
103
+ background: var(--form-button-active-background, oklch(from var(--bg, var(--accent)) calc(l - 0.14) c h));
104
+ }
105
+
106
+ .form-button:focus-visible {
107
+ outline: var(--focus-ring-width, 2px) solid var(--focus-ring-color);
108
+ outline-offset: var(--focus-ring-offset, 2px);
109
+ }
110
+
111
+ :is(.form-input, .form-select, .form-textarea, .form-button):disabled {
112
+ opacity: var(--opacity-disabled, 0.5);
113
+ cursor: not-allowed;
114
+ }
115
+
116
+ /* Button color variants */
117
+ .btn-primary { --bg: var(--accent); --fg: var(--text-on-accent); }
118
+ .btn-secondary { --bg: var(--secondary); --fg: var(--text-on-secondary); }
119
+ .btn-success { --bg: var(--success); --fg: var(--text-on-success); }
120
+ .btn-warning { --bg: var(--warning); --fg: var(--text-on-warning); }
121
+ .btn-error { --bg: var(--error); --fg: var(--text-on-error); }
122
+
123
+ /* Visual state follows semantic state when available. */
124
+ :is(.form-input, .form-select, .form-textarea):is(.input-error, [aria-invalid="true"]) {
125
+ border-color: var(--outline-error, var(--error));
126
+ }
127
+
128
+ :is(.form-input, .form-select, .form-textarea).input-success {
129
+ border-color: var(--outline-success, var(--success));
130
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * grid.css
3
+ *
4
+ * A declarative, powerful, and comprehensive CSS grid system.
5
+ * ------------------------------------------------------------------------------
6
+ * @feature {CSS Grid} - With declarative areas, tracks, and placement.
7
+ * @feature {CSS Gap Decorations} (Experimental) - For styling grid lines.
8
+ * @feature {attr()} - Powers the entire declarative API.
9
+ * @feature {Subgrid} - Allows nested grids to align with the parent grid.
10
+ */
11
+
12
+ :is(grid, [data-grid], .grid) {
13
+ /* --- Core Grid Layout & Template Properties --- */
14
+ --grid-display: attr(display type(*), grid);
15
+ --grid-columns: attr(columns type(*), none);
16
+ --grid-rows: attr(rows type(*), none);
17
+ --grid-areas: attr(areas type(*), none);
18
+ --grid-gap: attr(gap type(*), 1.5rem);
19
+ --grid-flow-tolerance: attr(flow-tolerance type(*), 1em);
20
+
21
+ display: grid;
22
+ display: var(--grid-display);
23
+ grid-template-columns: var(--grid-columns);
24
+ grid-template-rows: var(--grid-rows);
25
+ grid-template-areas: var(--grid-areas);
26
+ gap: var(--grid-gap);
27
+
28
+ /* --- Grid-wide Item Alignment --- */
29
+ justify-items: attr(justify-items type(*), stretch);
30
+ align-items: attr(align-items type(*), stretch);
31
+
32
+ /* --- CSS Gap Decoration Properties (Experimental) --- */
33
+ column-rule-width: attr(col-rule-width type(*), none);
34
+ column-rule-style: attr(col-rule-style type(*), none);
35
+ column-rule-color: attr(col-rule-color type(*), currentColor);
36
+ row-rule-width: attr(row-rule-width type(*), none);
37
+ row-rule-style: attr(row-rule-style type(*), none);
38
+ row-rule-color: attr(row-rule-color type(*), currentColor);
39
+ }
40
+
41
+ :is(grid, [data-grid], .grid):is([lanes], [data-lanes]) {
42
+ /* Unsupported browsers retain the normal grid layout. */
43
+ display: grid;
44
+ }
45
+
46
+ @supports (display: grid-lanes) {
47
+ :is(grid, [data-grid], .grid):is([lanes], [data-lanes]) {
48
+ display: grid-lanes;
49
+ flow-tolerance: var(--grid-flow-tolerance);
50
+ }
51
+ }
52
+
53
+ /* Target any direct child of <grid> for maximum flexibility */
54
+ :is(grid, [data-grid], .grid) > * {
55
+ /* --- Item Placement Properties --- */
56
+ grid-area: attr(area type(*), auto);
57
+ grid-column: attr(col type(*), auto);
58
+ grid-row: attr(row type(*), auto);
59
+
60
+ /* --- Individual Item Self-Alignment --- */
61
+ justify-self: attr(justify-self type(*), auto);
62
+ align-self: attr(align-self type(*), auto);
63
+
64
+ /* --- Subgrid Capability --- */
65
+ &[subgrid] {
66
+ display: grid;
67
+ grid-template-columns: subgrid;
68
+ grid-template-rows: subgrid;
69
+ gap: 0; /* Gaps are inherited from parent grid */
70
+ }
71
+ }
72
+
73
+ /* Named line placement when shorthand col/row are not provided */
74
+ :is(grid, [data-grid], .grid) > *:not([col]) {
75
+ grid-column-start: attr(col-start type(*), auto);
76
+ grid-column-end: attr(col-end type(*), auto);
77
+ }
78
+
79
+ :is(grid, [data-grid], .grid) > *:not([row]) {
80
+ grid-row-start: attr(row-start type(*), auto);
81
+ grid-row-end: attr(row-end type(*), auto);
82
+ }
@@ -0,0 +1,59 @@
1
+ /** Identity primitives. */
2
+
3
+ :is(user-avatar, [data-avatar], .avatar) {
4
+ --_avatar-size: var(--avatar-size, 2.75rem);
5
+
6
+ position: relative;
7
+ display: inline-grid;
8
+ place-items: center;
9
+ flex: 0 0 auto;
10
+ inline-size: var(--_avatar-size);
11
+ block-size: var(--_avatar-size);
12
+ overflow: hidden;
13
+ border: var(--avatar-border-width, var(--border-width, 1px)) solid
14
+ var(--avatar-border-color, var(--outline-subtle));
15
+ border-radius: var(--avatar-radius, var(--radius-full, 9999px));
16
+ background: var(--avatar-background, var(--surface-overt));
17
+ color: var(--avatar-color, var(--text-overt));
18
+ font-size: calc(var(--_avatar-size) * 0.36);
19
+ font-weight: var(--avatar-font-weight, var(--font-weight-semibold, 600));
20
+ line-height: 1;
21
+ text-transform: uppercase;
22
+ isolation: isolate;
23
+ }
24
+
25
+ :is(user-avatar, [data-avatar], .avatar) > :is(img, picture) {
26
+ position: absolute;
27
+ z-index: 1;
28
+ inset: 0;
29
+ inline-size: 100%;
30
+ block-size: 100%;
31
+ object-fit: var(--avatar-image-fit, cover);
32
+ }
33
+
34
+ :is(user-avatar, [data-avatar], .avatar):is([size="sm"], [data-size="sm"]) {
35
+ --avatar-size: 2rem;
36
+ }
37
+
38
+ :is(user-avatar, [data-avatar], .avatar):is([size="lg"], [data-size="lg"]) {
39
+ --avatar-size: 4rem;
40
+ }
41
+
42
+ :is(user-avatar, [data-avatar], .avatar):is([shape="square"], [data-shape="square"]) {
43
+ --avatar-radius: var(--radius-md, 0.5rem);
44
+ }
45
+
46
+ :is(avatar-group, [data-avatar-group], .avatar-group) {
47
+ display: flex;
48
+ align-items: center;
49
+ inline-size: max-content;
50
+ padding-inline-start: var(--avatar-group-overlap, 0.625rem);
51
+ }
52
+
53
+ :is(avatar-group, [data-avatar-group], .avatar-group)
54
+ > :is(user-avatar, [data-avatar], .avatar) {
55
+ margin-inline-start: calc(-1 * var(--avatar-group-overlap, 0.625rem));
56
+ box-shadow: 0 0 0 var(--avatar-group-ring-width, 2px)
57
+ var(--avatar-group-ring-color, var(--surface-default));
58
+ }
59
+