@ponchia/ui 0.2.2 → 0.3.1
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 +108 -79
- package/behaviors/index.d.ts +53 -0
- package/behaviors/index.js +745 -34
- package/classes/index.d.ts +216 -3
- package/classes/index.js +85 -10
- package/classes/vscode.css-custom-data.json +407 -0
- package/css/app.css +53 -44
- package/css/base.css +14 -23
- package/css/content.css +37 -2
- package/css/core.css +5 -5
- package/css/disclosure.css +17 -5
- package/css/dots.css +1 -1
- package/css/feedback.css +87 -2
- package/css/forms.css +128 -2
- package/css/navigation.css +16 -85
- package/css/overlay.css +73 -2
- package/css/primitives.css +100 -3
- package/css/site.css +295 -0
- package/css/table.css +59 -0
- package/css/tokens.css +79 -24
- package/dist/bronto.css +1 -1
- package/dist/css/app.css +1 -0
- package/dist/css/base.css +1 -0
- package/dist/css/content.css +1 -0
- package/dist/css/disclosure.css +1 -0
- package/dist/css/dots.css +1 -0
- package/dist/css/feedback.css +1 -0
- package/dist/css/fonts.css +1 -0
- package/dist/css/forms.css +1 -0
- package/dist/css/motion.css +1 -0
- package/dist/css/navigation.css +1 -0
- package/dist/css/overlay.css +1 -0
- package/dist/css/primitives.css +1 -0
- package/dist/css/site.css +1 -0
- package/dist/css/table.css +1 -0
- package/dist/css/tokens.css +1 -0
- package/package.json +60 -30
- package/shiki/nothing.json +83 -0
- package/tokens/index.d.ts +18 -10
- package/tokens/index.js +49 -16
- package/tokens/index.json +98 -32
- package/tokens/tokens.dtcg.json +241 -22
- package/css/cards.css +0 -336
- package/css/index.css +0 -5
- package/css/layout.css +0 -219
- package/css/responsive.css +0 -157
- package/css/typography.css +0 -139
- package/dist/bronto-core.css +0 -1
package/css/forms.css
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
.ui-input:focus-visible,
|
|
67
67
|
.ui-select:focus-visible,
|
|
68
68
|
.ui-textarea:focus-visible {
|
|
69
|
-
outline: 2px solid var(--
|
|
69
|
+
outline: 2px solid var(--focus-ring);
|
|
70
70
|
outline-offset: 1px;
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -92,6 +92,108 @@
|
|
|
92
92
|
color: var(--danger);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/* --- Input group: prefix/suffix affix around a control --- */
|
|
96
|
+
.ui-input-group {
|
|
97
|
+
display: flex;
|
|
98
|
+
isolation: isolate;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ui-input-group > .ui-input,
|
|
102
|
+
.ui-input-group > .ui-select {
|
|
103
|
+
border-radius: 0;
|
|
104
|
+
flex: 1;
|
|
105
|
+
margin-inline-start: -1px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.ui-input-group > :first-child {
|
|
109
|
+
border-start-start-radius: var(--radius-md);
|
|
110
|
+
border-end-start-radius: var(--radius-md);
|
|
111
|
+
margin-inline-start: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.ui-input-group > :last-child {
|
|
115
|
+
border-start-end-radius: var(--radius-md);
|
|
116
|
+
border-end-end-radius: var(--radius-md);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.ui-input-group > .ui-input:focus-visible {
|
|
120
|
+
z-index: 1; /* keep the focus ring above the adjacent addon border */
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.ui-input-group__addon {
|
|
124
|
+
align-items: center;
|
|
125
|
+
background: var(--panel-soft);
|
|
126
|
+
border: 1px solid var(--line);
|
|
127
|
+
color: var(--text-dim);
|
|
128
|
+
display: flex;
|
|
129
|
+
font-size: var(--text-sm);
|
|
130
|
+
padding-inline: var(--space-sm);
|
|
131
|
+
white-space: nowrap;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* --- File input --- */
|
|
135
|
+
.ui-file {
|
|
136
|
+
color: var(--text-soft);
|
|
137
|
+
font-size: var(--text-sm);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.ui-file::file-selector-button {
|
|
141
|
+
background: var(--panel-soft);
|
|
142
|
+
border: 1px solid var(--line-strong);
|
|
143
|
+
border-radius: var(--radius-md);
|
|
144
|
+
color: var(--text);
|
|
145
|
+
cursor: pointer;
|
|
146
|
+
font: inherit;
|
|
147
|
+
margin-inline-end: var(--space-sm);
|
|
148
|
+
padding: 0.5rem 0.85rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.ui-file::file-selector-button:hover {
|
|
152
|
+
border-color: var(--accent);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* --- Range --- */
|
|
156
|
+
.ui-range {
|
|
157
|
+
accent-color: var(--accent);
|
|
158
|
+
inline-size: 100%;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.ui-range:focus-visible {
|
|
162
|
+
outline: 2px solid var(--focus-ring);
|
|
163
|
+
outline-offset: 4px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* --- Error summary: one focusable, assertive list of form errors --- */
|
|
167
|
+
.ui-error-summary {
|
|
168
|
+
border: 1px solid var(--danger);
|
|
169
|
+
border-radius: var(--radius-md);
|
|
170
|
+
color: var(--text);
|
|
171
|
+
padding: var(--space-md);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.ui-error-summary[hidden] {
|
|
175
|
+
display: none;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.ui-error-summary__title {
|
|
179
|
+
color: var(--danger);
|
|
180
|
+
font-family: var(--display);
|
|
181
|
+
font-size: var(--text-sm);
|
|
182
|
+
font-weight: 700;
|
|
183
|
+
letter-spacing: var(--tracking-wide);
|
|
184
|
+
margin: 0 0 var(--space-xs);
|
|
185
|
+
text-transform: uppercase;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.ui-error-summary__list {
|
|
189
|
+
margin: 0;
|
|
190
|
+
padding-inline-start: var(--space-md);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.ui-error-summary__list a {
|
|
194
|
+
color: var(--danger);
|
|
195
|
+
}
|
|
196
|
+
|
|
95
197
|
/* Search field with leading dot. */
|
|
96
198
|
.ui-search {
|
|
97
199
|
align-items: center;
|
|
@@ -183,10 +285,34 @@
|
|
|
183
285
|
}
|
|
184
286
|
|
|
185
287
|
.ui-switch input:focus-visible + .ui-switch__track {
|
|
186
|
-
outline: 2px solid var(--
|
|
288
|
+
outline: 2px solid var(--focus-ring);
|
|
187
289
|
outline-offset: 2px;
|
|
188
290
|
}
|
|
189
291
|
|
|
292
|
+
/* ARIA contract: `.ui-switch` is a visually-styled checkbox. Author
|
|
293
|
+
`role="switch"` on the `<input>` so AT announces "switch, on/off"
|
|
294
|
+
rather than "checkbox, checked" — the native `checked` state then
|
|
295
|
+
drives `aria-checked` automatically, so no JS is required. In
|
|
296
|
+
forced-colors mode the colour cues are dropped by the OS, so convey
|
|
297
|
+
on/off with system-colour border + thumb instead. */
|
|
298
|
+
@media (forced-colors: active) {
|
|
299
|
+
.ui-switch__track {
|
|
300
|
+
border-color: ButtonBorder;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.ui-switch__thumb {
|
|
304
|
+
background: ButtonText;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.ui-switch input:checked + .ui-switch__track {
|
|
308
|
+
border-color: Highlight;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.ui-switch input:checked + .ui-switch__track .ui-switch__thumb {
|
|
312
|
+
background: Highlight;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
190
316
|
/* Checkbox / radio — square accent. */
|
|
191
317
|
.ui-check {
|
|
192
318
|
align-items: center;
|
package/css/navigation.css
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
/* ==========================================================================
|
|
2
|
-
navigation —
|
|
3
|
-
|
|
2
|
+
navigation — theme toggle (Nothing flat, dot-thumb switch).
|
|
3
|
+
Site nav/menu live in site.css as ui-sitenav / ui-sitemenu; the legacy
|
|
4
|
+
.site-nav / .site-menu vocabulary was removed in 0.3.0.
|
|
4
5
|
========================================================================== */
|
|
5
6
|
|
|
6
|
-
.
|
|
7
|
-
display: none;
|
|
8
|
-
position: relative;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.site-menu__toggle,
|
|
12
|
-
.theme-toggle__button {
|
|
7
|
+
.ui-themetoggle__button {
|
|
13
8
|
align-items: center;
|
|
14
9
|
background: transparent;
|
|
15
10
|
border: 1px solid var(--line-strong);
|
|
@@ -21,9 +16,10 @@
|
|
|
21
16
|
font-size: var(--text-xs);
|
|
22
17
|
font-weight: 600;
|
|
23
18
|
gap: 0.4rem;
|
|
19
|
+
justify-content: center;
|
|
24
20
|
letter-spacing: var(--tracking-wide);
|
|
25
|
-
list-style: none;
|
|
26
21
|
min-block-size: 2rem;
|
|
22
|
+
min-inline-size: 7rem;
|
|
27
23
|
padding: 0.42rem 0.66rem;
|
|
28
24
|
text-transform: uppercase;
|
|
29
25
|
transition:
|
|
@@ -33,32 +29,21 @@
|
|
|
33
29
|
white-space: nowrap;
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
.
|
|
37
|
-
justify-content: center;
|
|
38
|
-
min-inline-size: 7rem;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.site-menu__toggle::-webkit-details-marker {
|
|
42
|
-
display: none;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.site-menu[open] .site-menu__toggle,
|
|
46
|
-
.site-menu__toggle:hover,
|
|
47
|
-
.theme-toggle__button:hover {
|
|
32
|
+
.ui-themetoggle__button:hover {
|
|
48
33
|
border-color: var(--accent);
|
|
49
|
-
color: var(--accent);
|
|
34
|
+
color: var(--accent-text);
|
|
50
35
|
}
|
|
51
36
|
|
|
52
|
-
.
|
|
37
|
+
.ui-themetoggle__prefix {
|
|
53
38
|
color: var(--text-dim);
|
|
54
39
|
}
|
|
55
40
|
|
|
56
|
-
.
|
|
41
|
+
.ui-themetoggle__label {
|
|
57
42
|
color: var(--text);
|
|
58
43
|
font-weight: 700;
|
|
59
44
|
}
|
|
60
45
|
|
|
61
|
-
.
|
|
46
|
+
.ui-themetoggle__track {
|
|
62
47
|
background: var(--panel-soft);
|
|
63
48
|
border: 1px solid var(--line-strong);
|
|
64
49
|
border-radius: var(--radius-pill);
|
|
@@ -68,7 +53,7 @@
|
|
|
68
53
|
inline-size: 1.5rem;
|
|
69
54
|
}
|
|
70
55
|
|
|
71
|
-
.
|
|
56
|
+
.ui-themetoggle__thumb {
|
|
72
57
|
background: var(--text-dim);
|
|
73
58
|
border-radius: 50%;
|
|
74
59
|
display: block;
|
|
@@ -80,72 +65,18 @@
|
|
|
80
65
|
inline-size: 0.56rem;
|
|
81
66
|
}
|
|
82
67
|
|
|
83
|
-
[data-theme='dark'] .
|
|
68
|
+
[data-theme='dark'] .ui-themetoggle__thumb {
|
|
84
69
|
background: var(--accent);
|
|
85
70
|
transform: translateX(0.6rem);
|
|
86
71
|
}
|
|
87
72
|
|
|
88
|
-
[dir='rtl'][data-theme='dark'] .
|
|
89
|
-
[dir='rtl'] [data-theme='dark'] .
|
|
73
|
+
[dir='rtl'][data-theme='dark'] .ui-themetoggle__thumb,
|
|
74
|
+
[dir='rtl'] [data-theme='dark'] .ui-themetoggle__thumb {
|
|
90
75
|
transform: translateX(-0.6rem);
|
|
91
76
|
}
|
|
92
77
|
|
|
93
|
-
.site-nav {
|
|
94
|
-
display: inline-flex;
|
|
95
|
-
gap: 0.15rem;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.site-nav a {
|
|
99
|
-
align-items: center;
|
|
100
|
-
border: 1px solid transparent;
|
|
101
|
-
border-radius: var(--radius-md);
|
|
102
|
-
color: var(--text-soft);
|
|
103
|
-
display: inline-flex;
|
|
104
|
-
font-family: var(--mono);
|
|
105
|
-
font-size: var(--text-xs);
|
|
106
|
-
gap: 0.45rem;
|
|
107
|
-
letter-spacing: var(--tracking-wide);
|
|
108
|
-
padding: 0.4rem 0.6rem;
|
|
109
|
-
position: relative;
|
|
110
|
-
text-transform: uppercase;
|
|
111
|
-
transition:
|
|
112
|
-
border-color var(--duration-fast) var(--ease-standard),
|
|
113
|
-
background-color var(--duration-fast) var(--ease-standard),
|
|
114
|
-
color var(--duration-fast) var(--ease-standard);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/* Leading dot is the active/hover indicator — Nothing glyph cue. */
|
|
118
|
-
.site-nav a::before {
|
|
119
|
-
background: currentColor;
|
|
120
|
-
border-radius: 50%;
|
|
121
|
-
content: '';
|
|
122
|
-
block-size: 0.32rem;
|
|
123
|
-
opacity: 0;
|
|
124
|
-
transform: scale(0.5);
|
|
125
|
-
transition:
|
|
126
|
-
opacity var(--duration-fast) var(--ease-standard),
|
|
127
|
-
transform var(--duration-fast) var(--ease-spring);
|
|
128
|
-
inline-size: 0.32rem;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.site-nav a:hover,
|
|
132
|
-
.site-nav a.is-active {
|
|
133
|
-
color: var(--text);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.site-nav a.is-active {
|
|
137
|
-
color: var(--accent);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.site-nav a:hover::before,
|
|
141
|
-
.site-nav a.is-active::before {
|
|
142
|
-
opacity: 1;
|
|
143
|
-
transform: scale(1);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
78
|
@media (hover: hover) {
|
|
147
|
-
.
|
|
148
|
-
.theme-toggle__button:active {
|
|
79
|
+
.ui-themetoggle__button:active {
|
|
149
80
|
transform: translateY(1px);
|
|
150
81
|
}
|
|
151
82
|
}
|
package/css/overlay.css
CHANGED
|
@@ -91,12 +91,20 @@
|
|
|
91
91
|
@media (hover: hover) {
|
|
92
92
|
.ui-modal__close:hover {
|
|
93
93
|
border-color: var(--accent);
|
|
94
|
-
color: var(--accent);
|
|
94
|
+
color: var(--accent-text);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/* --- Dropdown menu — pairs with native <details> --- */
|
|
99
99
|
|
|
100
|
+
/* The positioned host for a <details> dropdown: .ui-menu is absolute, so
|
|
101
|
+
its <details> wrapper must establish a containing block. (Replaces the
|
|
102
|
+
role the legacy .site-menu wrapper served, now a first-class ui-*.) */
|
|
103
|
+
.ui-menu-host {
|
|
104
|
+
display: inline-block;
|
|
105
|
+
position: relative;
|
|
106
|
+
}
|
|
107
|
+
|
|
100
108
|
.ui-menu {
|
|
101
109
|
background: var(--panel-strong);
|
|
102
110
|
border: 1px solid var(--line-strong);
|
|
@@ -109,7 +117,7 @@
|
|
|
109
117
|
position: absolute;
|
|
110
118
|
inset-inline-end: 0;
|
|
111
119
|
inset-block-start: calc(100% + 0.4rem);
|
|
112
|
-
z-index:
|
|
120
|
+
z-index: var(--z-overlay);
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
.ui-menu__label {
|
|
@@ -164,6 +172,69 @@
|
|
|
164
172
|
}
|
|
165
173
|
}
|
|
166
174
|
|
|
175
|
+
/* --- Combobox: an input with a filtered listbox popup (APG pattern,
|
|
176
|
+
wired by initCombobox). Reuses the menu surface tokens. --- */
|
|
177
|
+
.ui-combobox {
|
|
178
|
+
display: inline-block;
|
|
179
|
+
min-inline-size: 14rem;
|
|
180
|
+
position: relative;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.ui-combobox__input {
|
|
184
|
+
inline-size: 100%;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.ui-combobox__list {
|
|
188
|
+
background: var(--panel-strong);
|
|
189
|
+
border: 1px solid var(--line-strong);
|
|
190
|
+
border-radius: var(--radius-md);
|
|
191
|
+
box-shadow: var(--shadow-raised);
|
|
192
|
+
display: grid;
|
|
193
|
+
gap: 1px;
|
|
194
|
+
list-style: none;
|
|
195
|
+
margin: 0;
|
|
196
|
+
max-block-size: 16rem;
|
|
197
|
+
overflow-y: auto;
|
|
198
|
+
padding: 0.3rem;
|
|
199
|
+
position: absolute;
|
|
200
|
+
inset-block-start: calc(100% + 0.4rem);
|
|
201
|
+
inset-inline: 0;
|
|
202
|
+
z-index: var(--z-overlay);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.ui-combobox__list[hidden] {
|
|
206
|
+
display: none;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.ui-combobox__option {
|
|
210
|
+
border-radius: var(--radius-sm);
|
|
211
|
+
color: var(--text-soft);
|
|
212
|
+
cursor: pointer;
|
|
213
|
+
font-family: var(--mono);
|
|
214
|
+
font-size: var(--text-sm);
|
|
215
|
+
padding: 0.5rem 0.55rem;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.ui-combobox__option[hidden] {
|
|
219
|
+
display: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.ui-combobox__option.is-active,
|
|
223
|
+
.ui-combobox__option[aria-selected='true'] {
|
|
224
|
+
background: var(--bg-accent);
|
|
225
|
+
color: var(--text);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.ui-combobox__empty {
|
|
229
|
+
color: var(--text-dim);
|
|
230
|
+
font-size: var(--text-2xs);
|
|
231
|
+
padding: 0.5rem 0.55rem;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.ui-combobox__empty[hidden] {
|
|
235
|
+
display: none;
|
|
236
|
+
}
|
|
237
|
+
|
|
167
238
|
/* --- Mobile: modal becomes a bottom sheet, drawer goes full-width --- */
|
|
168
239
|
|
|
169
240
|
@media (max-width: 560px) {
|
package/css/primitives.css
CHANGED
|
@@ -27,6 +27,75 @@
|
|
|
27
27
|
grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--grid-min, 16rem)), 1fr));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/* Every-Layout set — the layouts consumers otherwise hand-roll. All
|
|
31
|
+
intrinsic (no media queries): they respond to content + available
|
|
32
|
+
space, so they work the same in a viewport or a container. */
|
|
33
|
+
|
|
34
|
+
/* Sidebar + main; the sidebar is its natural width, main takes the
|
|
35
|
+
rest, and they stack once main would go below --sidebar-min. */
|
|
36
|
+
.ui-sidebar {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-wrap: wrap;
|
|
39
|
+
gap: var(--sidebar-gap, var(--space-md));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.ui-sidebar > :first-child {
|
|
43
|
+
flex-basis: var(--sidebar-width, 16rem);
|
|
44
|
+
flex-grow: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.ui-sidebar > :last-child {
|
|
48
|
+
flex-basis: 0;
|
|
49
|
+
flex-grow: 999;
|
|
50
|
+
min-inline-size: var(--sidebar-min, 60%);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* All children in one row until they no longer fit --switcher-min,
|
|
54
|
+
then all switch to a column together (no half-states). */
|
|
55
|
+
.ui-switcher {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-wrap: wrap;
|
|
58
|
+
gap: var(--switcher-gap, var(--space-md));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ui-switcher > * {
|
|
62
|
+
flex-basis: calc((var(--switcher-min, 24rem) - 100%) * 999);
|
|
63
|
+
flex-grow: 1;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Centered measure-bounded column. */
|
|
67
|
+
.ui-center {
|
|
68
|
+
box-sizing: content-box;
|
|
69
|
+
margin-inline: auto;
|
|
70
|
+
max-inline-size: var(--center-max, 64rem);
|
|
71
|
+
padding-inline: var(--center-gutter, var(--space-md));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Intrinsic aspect-ratio box; the media child fills it. */
|
|
75
|
+
.ui-ratio {
|
|
76
|
+
aspect-ratio: var(--ratio, 16 / 9);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.ui-ratio > * {
|
|
80
|
+
block-size: 100%;
|
|
81
|
+
inline-size: 100%;
|
|
82
|
+
object-fit: cover;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Opt-in containment: add .ui-cq to a wrapper to make descendant
|
|
86
|
+
.ui-grid / .ui-app-metrics adapt to THIS box, not the viewport
|
|
87
|
+
(island-safe). Inert until applied, so existing layouts/baselines
|
|
88
|
+
are unaffected. */
|
|
89
|
+
.ui-cq {
|
|
90
|
+
container: var(--cq-name, bronto) / inline-size;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@container bronto (max-width: 34rem) {
|
|
94
|
+
.ui-grid {
|
|
95
|
+
--grid-min: 100%;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
30
99
|
/* --- Surfaces --- */
|
|
31
100
|
|
|
32
101
|
.ui-surface,
|
|
@@ -78,7 +147,7 @@
|
|
|
78
147
|
.ui-eyebrow {
|
|
79
148
|
/* accent-strong, not accent: this is small bold text and must clear
|
|
80
149
|
WCAG AA 4.5:1 on the soft/tinted surfaces eyebrows sit on too. */
|
|
81
|
-
color: var(--accent-
|
|
150
|
+
color: var(--accent-text);
|
|
82
151
|
font-family: var(--display);
|
|
83
152
|
font-size: var(--text-xs);
|
|
84
153
|
font-weight: 700;
|
|
@@ -153,6 +222,32 @@
|
|
|
153
222
|
transform: translateY(1px);
|
|
154
223
|
}
|
|
155
224
|
|
|
225
|
+
/* Async/pending state — set aria-busy="true" (and disable) on submit.
|
|
226
|
+
A leading ring spinner is injected with no extra markup; the label
|
|
227
|
+
stays for context. Inert until aria-busy is set, so default buttons
|
|
228
|
+
and visual baselines are unaffected. */
|
|
229
|
+
.ui-button[aria-busy='true'] {
|
|
230
|
+
cursor: progress;
|
|
231
|
+
pointer-events: none;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.ui-button[aria-busy='true']::before {
|
|
235
|
+
animation: uiSpin 0.6s linear infinite;
|
|
236
|
+
block-size: 0.9em;
|
|
237
|
+
border: 2px solid currentcolor;
|
|
238
|
+
border-block-start-color: transparent;
|
|
239
|
+
border-radius: var(--radius-pill);
|
|
240
|
+
content: '';
|
|
241
|
+
flex: none;
|
|
242
|
+
inline-size: 0.9em;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@media (prefers-reduced-motion: reduce) {
|
|
246
|
+
.ui-button[aria-busy='true']::before {
|
|
247
|
+
animation-duration: 1.4s;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
156
251
|
/* --- Link --- */
|
|
157
252
|
|
|
158
253
|
.ui-link {
|
|
@@ -203,8 +298,10 @@
|
|
|
203
298
|
}
|
|
204
299
|
|
|
205
300
|
.ui-chip--accent {
|
|
301
|
+
/* accent-strong, not accent: chip text is small uppercase mono and must
|
|
302
|
+
clear WCAG AA 4.5:1 — same rule as .ui-eyebrow above. */
|
|
303
|
+
color: var(--accent-text);
|
|
206
304
|
border-color: var(--accent);
|
|
207
|
-
color: var(--accent);
|
|
208
305
|
}
|
|
209
306
|
|
|
210
307
|
/* --- Badge / status pill --- */
|
|
@@ -307,7 +404,7 @@
|
|
|
307
404
|
}
|
|
308
405
|
|
|
309
406
|
.ui-link:hover {
|
|
310
|
-
color: var(--accent);
|
|
407
|
+
color: var(--accent-text);
|
|
311
408
|
text-decoration-color: var(--accent);
|
|
312
409
|
}
|
|
313
410
|
|