@wtfalch/design 0.7.0 → 0.9.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/README.md +18 -0
- package/dist/components/Button.js +8 -7
- package/dist/components/Callout.js +1 -1
- package/dist/components/Card.d.ts +1 -1
- package/dist/components/Card.js +21 -4
- package/dist/components/Command.js +2 -2
- package/dist/components/Empty.js +22 -1
- package/dist/components/Field.d.ts +22 -19
- package/dist/components/Field.js +11 -9
- package/dist/components/Input.d.ts +10 -0
- package/dist/components/Input.js +26 -5
- package/dist/components/Kbd.js +11 -1
- package/dist/components/Menu.js +3 -3
- package/dist/components/Modal.js +2 -2
- package/dist/components/Pagination.js +6 -1
- package/dist/components/Progress.js +8 -1
- package/dist/components/Rows.d.ts +1 -1
- package/dist/components/Rows.js +1 -1
- package/dist/components/Select.d.ts +3 -1
- package/dist/components/Select.js +28 -6
- package/dist/components/Shell.d.ts +35 -0
- package/dist/components/Shell.js +36 -0
- package/dist/components/SizeGrid.js +14 -2
- package/dist/components/Stat.js +11 -2
- package/dist/components/Table.js +7 -1
- package/dist/components/Textarea.js +14 -4
- package/dist/components/ThemeSwitch.d.ts +19 -0
- package/dist/components/ThemeSwitch.js +65 -0
- package/dist/components/Toast.js +1 -1
- package/dist/components/Tooltip.js +16 -2
- package/dist/components/Tour.js +1 -1
- package/dist/components/fieldWiring.d.ts +44 -0
- package/dist/components/fieldWiring.js +30 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +8 -0
- package/dist/styles/index.css +1110 -355
- package/dist/tf.css +1110 -355
- package/dist/themes/choice.d.ts +71 -0
- package/dist/themes/choice.js +81 -0
- package/dist/valet.css +1110 -355
- package/package.json +3 -1
package/dist/styles/index.css
CHANGED
|
@@ -8,6 +8,705 @@
|
|
|
8
8
|
*
|
|
9
9
|
* `scripts/copy-css.mjs` flattens these into one file at build time.
|
|
10
10
|
*/
|
|
11
|
+
/* ---- ./_tailwind.built.css ---- */
|
|
12
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
13
|
+
@layer properties;
|
|
14
|
+
@layer theme, base, components, utilities;
|
|
15
|
+
@layer theme {
|
|
16
|
+
:root, :host {
|
|
17
|
+
--font-sans: var(--font-sans);
|
|
18
|
+
--font-mono: var(--font-mono);
|
|
19
|
+
--text-xs: var(--text-xs);
|
|
20
|
+
--text-xs--line-height: inherit;
|
|
21
|
+
--text-sm: var(--text-sm);
|
|
22
|
+
--text-sm--line-height: inherit;
|
|
23
|
+
--text-base: var(--text-base);
|
|
24
|
+
--text-lg: var(--text-lg);
|
|
25
|
+
--text-lg--line-height: inherit;
|
|
26
|
+
--text-xl: var(--text-xl);
|
|
27
|
+
--font-weight-normal: var(--weight);
|
|
28
|
+
--tracking-normal: var(--tracking);
|
|
29
|
+
--radius-sm: var(--radius-sm);
|
|
30
|
+
--radius-md: var(--radius-md);
|
|
31
|
+
--radius-lg: var(--radius-lg);
|
|
32
|
+
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
33
|
+
--spacing-1: var(--space-1);
|
|
34
|
+
--spacing-2: var(--space-2);
|
|
35
|
+
--spacing-3: var(--space-3);
|
|
36
|
+
--spacing-4: var(--space-4);
|
|
37
|
+
--spacing-5: var(--space-5);
|
|
38
|
+
--spacing-6: var(--space-6);
|
|
39
|
+
--spacing-10: var(--space-10);
|
|
40
|
+
--text-2xs--line-height: inherit;
|
|
41
|
+
--text-2xs: var(--text-2xs);
|
|
42
|
+
--text-md: var(--text-md);
|
|
43
|
+
--font-weight-strong: var(--weight-strong);
|
|
44
|
+
--radius-pill: var(--radius-pill);
|
|
45
|
+
--color-text: var(--text);
|
|
46
|
+
--color-muted: var(--muted);
|
|
47
|
+
--color-accent: var(--accent);
|
|
48
|
+
--color-border: var(--border);
|
|
49
|
+
--color-border-strong: var(--border-strong);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
@layer utilities {
|
|
53
|
+
.collapse {
|
|
54
|
+
visibility: collapse;
|
|
55
|
+
}
|
|
56
|
+
.invisible {
|
|
57
|
+
visibility: hidden;
|
|
58
|
+
}
|
|
59
|
+
.visible {
|
|
60
|
+
visibility: visible;
|
|
61
|
+
}
|
|
62
|
+
.sr-only {
|
|
63
|
+
position: absolute;
|
|
64
|
+
width: 1px;
|
|
65
|
+
height: 1px;
|
|
66
|
+
padding: 0;
|
|
67
|
+
margin: -1px;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
clip-path: inset(50%);
|
|
70
|
+
white-space: nowrap;
|
|
71
|
+
border-width: 0;
|
|
72
|
+
}
|
|
73
|
+
.absolute {
|
|
74
|
+
position: absolute;
|
|
75
|
+
}
|
|
76
|
+
.fixed {
|
|
77
|
+
position: fixed;
|
|
78
|
+
}
|
|
79
|
+
.relative {
|
|
80
|
+
position: relative;
|
|
81
|
+
}
|
|
82
|
+
.sticky {
|
|
83
|
+
position: sticky;
|
|
84
|
+
}
|
|
85
|
+
.z-\[60\] {
|
|
86
|
+
z-index: 60;
|
|
87
|
+
}
|
|
88
|
+
.container {
|
|
89
|
+
width: 100%;
|
|
90
|
+
@media (width >= 40rem) {
|
|
91
|
+
max-width: 40rem;
|
|
92
|
+
}
|
|
93
|
+
@media (width >= 48rem) {
|
|
94
|
+
max-width: 48rem;
|
|
95
|
+
}
|
|
96
|
+
@media (width >= 64rem) {
|
|
97
|
+
max-width: 64rem;
|
|
98
|
+
}
|
|
99
|
+
@media (width >= 80rem) {
|
|
100
|
+
max-width: 80rem;
|
|
101
|
+
}
|
|
102
|
+
@media (width >= 96rem) {
|
|
103
|
+
max-width: 96rem;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
.m-0 {
|
|
107
|
+
margin: 0px;
|
|
108
|
+
}
|
|
109
|
+
.m-auto {
|
|
110
|
+
margin: auto;
|
|
111
|
+
}
|
|
112
|
+
.mx-auto {
|
|
113
|
+
margin-inline: auto;
|
|
114
|
+
}
|
|
115
|
+
.mt-1 {
|
|
116
|
+
margin-top: var(--spacing-1);
|
|
117
|
+
}
|
|
118
|
+
.mb-3 {
|
|
119
|
+
margin-bottom: var(--spacing-3);
|
|
120
|
+
}
|
|
121
|
+
.ml-2 {
|
|
122
|
+
margin-left: var(--spacing-2);
|
|
123
|
+
}
|
|
124
|
+
.block {
|
|
125
|
+
display: block;
|
|
126
|
+
}
|
|
127
|
+
.contents {
|
|
128
|
+
display: contents;
|
|
129
|
+
}
|
|
130
|
+
.flex {
|
|
131
|
+
display: flex;
|
|
132
|
+
}
|
|
133
|
+
.grid {
|
|
134
|
+
display: grid;
|
|
135
|
+
}
|
|
136
|
+
.hidden {
|
|
137
|
+
display: none;
|
|
138
|
+
}
|
|
139
|
+
.inline {
|
|
140
|
+
display: inline;
|
|
141
|
+
}
|
|
142
|
+
.inline-flex {
|
|
143
|
+
display: inline-flex;
|
|
144
|
+
}
|
|
145
|
+
.table {
|
|
146
|
+
display: table;
|
|
147
|
+
}
|
|
148
|
+
.h-\[14px\] {
|
|
149
|
+
height: 14px;
|
|
150
|
+
}
|
|
151
|
+
.h-\[18px\] {
|
|
152
|
+
height: 18px;
|
|
153
|
+
}
|
|
154
|
+
.max-h-\[24rem\] {
|
|
155
|
+
max-height: 24rem;
|
|
156
|
+
}
|
|
157
|
+
.max-h-\[280px\] {
|
|
158
|
+
max-height: 280px;
|
|
159
|
+
}
|
|
160
|
+
.min-h-0 {
|
|
161
|
+
min-height: 0px;
|
|
162
|
+
}
|
|
163
|
+
.min-h-screen {
|
|
164
|
+
min-height: 100vh;
|
|
165
|
+
}
|
|
166
|
+
.w-\[18px\] {
|
|
167
|
+
width: 18px;
|
|
168
|
+
}
|
|
169
|
+
.w-full {
|
|
170
|
+
width: 100%;
|
|
171
|
+
}
|
|
172
|
+
.max-w-\[46ch\] {
|
|
173
|
+
max-width: 46ch;
|
|
174
|
+
}
|
|
175
|
+
.max-w-\[min\(20rem\,calc\(100vw-var\(--space-6\)\)\)\] {
|
|
176
|
+
max-width: min(20rem, calc(100vw - var(--space-6)));
|
|
177
|
+
}
|
|
178
|
+
.max-w-\[var\(--shell-measure\)\] {
|
|
179
|
+
max-width: var(--shell-measure);
|
|
180
|
+
}
|
|
181
|
+
.max-w-\[var\(--shell-measure-wide\)\] {
|
|
182
|
+
max-width: var(--shell-measure-wide);
|
|
183
|
+
}
|
|
184
|
+
.min-w-0 {
|
|
185
|
+
min-width: 0px;
|
|
186
|
+
}
|
|
187
|
+
.min-w-\[12rem\] {
|
|
188
|
+
min-width: 12rem;
|
|
189
|
+
}
|
|
190
|
+
.flex-1 {
|
|
191
|
+
flex: 1;
|
|
192
|
+
}
|
|
193
|
+
.flex-none {
|
|
194
|
+
flex: none;
|
|
195
|
+
}
|
|
196
|
+
.shrink {
|
|
197
|
+
flex-shrink: 1;
|
|
198
|
+
}
|
|
199
|
+
.grow {
|
|
200
|
+
flex-grow: 1;
|
|
201
|
+
}
|
|
202
|
+
.transform {
|
|
203
|
+
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
|
204
|
+
}
|
|
205
|
+
.cursor-help {
|
|
206
|
+
cursor: help;
|
|
207
|
+
}
|
|
208
|
+
.cursor-pointer {
|
|
209
|
+
cursor: pointer;
|
|
210
|
+
}
|
|
211
|
+
.resize {
|
|
212
|
+
resize: both;
|
|
213
|
+
}
|
|
214
|
+
.list-none {
|
|
215
|
+
list-style-type: none;
|
|
216
|
+
}
|
|
217
|
+
.flex-col {
|
|
218
|
+
flex-direction: column;
|
|
219
|
+
}
|
|
220
|
+
.flex-wrap {
|
|
221
|
+
flex-wrap: wrap;
|
|
222
|
+
}
|
|
223
|
+
.items-baseline {
|
|
224
|
+
align-items: baseline;
|
|
225
|
+
}
|
|
226
|
+
.items-center {
|
|
227
|
+
align-items: center;
|
|
228
|
+
}
|
|
229
|
+
.items-start {
|
|
230
|
+
align-items: flex-start;
|
|
231
|
+
}
|
|
232
|
+
.justify-between {
|
|
233
|
+
justify-content: space-between;
|
|
234
|
+
}
|
|
235
|
+
.justify-items-center {
|
|
236
|
+
justify-items: center;
|
|
237
|
+
}
|
|
238
|
+
.gap-0 {
|
|
239
|
+
gap: 0px;
|
|
240
|
+
}
|
|
241
|
+
.gap-1 {
|
|
242
|
+
gap: var(--spacing-1);
|
|
243
|
+
}
|
|
244
|
+
.gap-2 {
|
|
245
|
+
gap: var(--spacing-2);
|
|
246
|
+
}
|
|
247
|
+
.gap-3 {
|
|
248
|
+
gap: var(--spacing-3);
|
|
249
|
+
}
|
|
250
|
+
.gap-4 {
|
|
251
|
+
gap: var(--spacing-4);
|
|
252
|
+
}
|
|
253
|
+
.gap-\[var\(--border-width\)\] {
|
|
254
|
+
gap: var(--border-width);
|
|
255
|
+
}
|
|
256
|
+
.self-center {
|
|
257
|
+
align-self: center;
|
|
258
|
+
}
|
|
259
|
+
.truncate {
|
|
260
|
+
overflow: hidden;
|
|
261
|
+
text-overflow: ellipsis;
|
|
262
|
+
white-space: nowrap;
|
|
263
|
+
}
|
|
264
|
+
.overflow-auto {
|
|
265
|
+
overflow: auto;
|
|
266
|
+
}
|
|
267
|
+
.overflow-hidden {
|
|
268
|
+
overflow: hidden;
|
|
269
|
+
}
|
|
270
|
+
.overflow-x-auto {
|
|
271
|
+
overflow-x: auto;
|
|
272
|
+
}
|
|
273
|
+
.overflow-y-auto {
|
|
274
|
+
overflow-y: auto;
|
|
275
|
+
}
|
|
276
|
+
.overscroll-contain {
|
|
277
|
+
overscroll-behavior: contain;
|
|
278
|
+
}
|
|
279
|
+
.rounded {
|
|
280
|
+
border-radius: 0.25rem;
|
|
281
|
+
}
|
|
282
|
+
.rounded-full {
|
|
283
|
+
border-radius: calc(infinity * 1px);
|
|
284
|
+
}
|
|
285
|
+
.rounded-md {
|
|
286
|
+
border-radius: var(--radius-md);
|
|
287
|
+
}
|
|
288
|
+
.rounded-sm {
|
|
289
|
+
border-radius: var(--radius-sm);
|
|
290
|
+
}
|
|
291
|
+
.border {
|
|
292
|
+
border-style: var(--tw-border-style);
|
|
293
|
+
border-width: var(--border-width);
|
|
294
|
+
}
|
|
295
|
+
.border-b {
|
|
296
|
+
border-bottom-style: var(--tw-border-style);
|
|
297
|
+
border-bottom-width: var(--border-width);
|
|
298
|
+
}
|
|
299
|
+
.border-dashed {
|
|
300
|
+
--tw-border-style: dashed;
|
|
301
|
+
border-style: dashed;
|
|
302
|
+
}
|
|
303
|
+
.border-accent {
|
|
304
|
+
border-color: var(--color-accent);
|
|
305
|
+
}
|
|
306
|
+
.border-border {
|
|
307
|
+
border-color: var(--color-border);
|
|
308
|
+
}
|
|
309
|
+
.border-border-strong {
|
|
310
|
+
border-color: var(--color-border-strong);
|
|
311
|
+
}
|
|
312
|
+
.p-0 {
|
|
313
|
+
padding: 0px;
|
|
314
|
+
}
|
|
315
|
+
.p-1 {
|
|
316
|
+
padding: var(--spacing-1);
|
|
317
|
+
}
|
|
318
|
+
.p-2 {
|
|
319
|
+
padding: var(--spacing-2);
|
|
320
|
+
}
|
|
321
|
+
.p-4 {
|
|
322
|
+
padding: var(--spacing-4);
|
|
323
|
+
}
|
|
324
|
+
.px-4 {
|
|
325
|
+
padding-inline: var(--spacing-4);
|
|
326
|
+
}
|
|
327
|
+
.py-2 {
|
|
328
|
+
padding-block: var(--spacing-2);
|
|
329
|
+
}
|
|
330
|
+
.py-3 {
|
|
331
|
+
padding-block: var(--spacing-3);
|
|
332
|
+
}
|
|
333
|
+
.py-5 {
|
|
334
|
+
padding-block: var(--spacing-5);
|
|
335
|
+
}
|
|
336
|
+
.py-6 {
|
|
337
|
+
padding-block: var(--spacing-6);
|
|
338
|
+
}
|
|
339
|
+
.py-10 {
|
|
340
|
+
padding-block: var(--spacing-10);
|
|
341
|
+
}
|
|
342
|
+
.pb-2 {
|
|
343
|
+
padding-bottom: var(--spacing-2);
|
|
344
|
+
}
|
|
345
|
+
.pb-3 {
|
|
346
|
+
padding-bottom: var(--spacing-3);
|
|
347
|
+
}
|
|
348
|
+
.text-center {
|
|
349
|
+
text-align: center;
|
|
350
|
+
}
|
|
351
|
+
.font-mono {
|
|
352
|
+
font-family: var(--font-mono);
|
|
353
|
+
}
|
|
354
|
+
.text-2xs {
|
|
355
|
+
font-size: var(--text-2xs);
|
|
356
|
+
line-height: var(--tw-leading, var(--text-2xs--line-height));
|
|
357
|
+
}
|
|
358
|
+
.text-lg {
|
|
359
|
+
font-size: var(--text-lg);
|
|
360
|
+
line-height: var(--tw-leading, var(--text-lg--line-height));
|
|
361
|
+
}
|
|
362
|
+
.text-sm {
|
|
363
|
+
font-size: var(--text-sm);
|
|
364
|
+
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
365
|
+
}
|
|
366
|
+
.text-xs {
|
|
367
|
+
font-size: var(--text-xs);
|
|
368
|
+
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
369
|
+
}
|
|
370
|
+
.leading-\[0\] {
|
|
371
|
+
--tw-leading: 0;
|
|
372
|
+
line-height: 0;
|
|
373
|
+
}
|
|
374
|
+
.leading-\[1\.5\] {
|
|
375
|
+
--tw-leading: 1.5;
|
|
376
|
+
line-height: 1.5;
|
|
377
|
+
}
|
|
378
|
+
.leading-\[1\.25\] {
|
|
379
|
+
--tw-leading: 1.25;
|
|
380
|
+
line-height: 1.25;
|
|
381
|
+
}
|
|
382
|
+
.leading-\[16px\] {
|
|
383
|
+
--tw-leading: 16px;
|
|
384
|
+
line-height: 16px;
|
|
385
|
+
}
|
|
386
|
+
.font-normal {
|
|
387
|
+
--tw-font-weight: var(--font-weight-normal);
|
|
388
|
+
font-weight: var(--font-weight-normal);
|
|
389
|
+
}
|
|
390
|
+
.font-strong {
|
|
391
|
+
--tw-font-weight: var(--font-weight-strong);
|
|
392
|
+
font-weight: var(--font-weight-strong);
|
|
393
|
+
}
|
|
394
|
+
.tracking-normal {
|
|
395
|
+
--tw-tracking: var(--tracking-normal);
|
|
396
|
+
letter-spacing: var(--tracking-normal);
|
|
397
|
+
}
|
|
398
|
+
.text-ellipsis {
|
|
399
|
+
text-overflow: ellipsis;
|
|
400
|
+
}
|
|
401
|
+
.whitespace-nowrap {
|
|
402
|
+
white-space: nowrap;
|
|
403
|
+
}
|
|
404
|
+
.text-muted {
|
|
405
|
+
color: var(--color-muted);
|
|
406
|
+
}
|
|
407
|
+
.text-text {
|
|
408
|
+
color: var(--color-text);
|
|
409
|
+
}
|
|
410
|
+
.lowercase {
|
|
411
|
+
text-transform: lowercase;
|
|
412
|
+
}
|
|
413
|
+
.normal-case {
|
|
414
|
+
text-transform: none;
|
|
415
|
+
}
|
|
416
|
+
.uppercase {
|
|
417
|
+
text-transform: uppercase;
|
|
418
|
+
}
|
|
419
|
+
.tabular-nums {
|
|
420
|
+
--tw-numeric-spacing: tabular-nums;
|
|
421
|
+
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
422
|
+
}
|
|
423
|
+
.opacity-0 {
|
|
424
|
+
opacity: 0%;
|
|
425
|
+
}
|
|
426
|
+
.opacity-60 {
|
|
427
|
+
opacity: 60%;
|
|
428
|
+
}
|
|
429
|
+
.opacity-\[0\.55\] {
|
|
430
|
+
opacity: 0.55;
|
|
431
|
+
}
|
|
432
|
+
.shadow {
|
|
433
|
+
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
434
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
435
|
+
}
|
|
436
|
+
.ring {
|
|
437
|
+
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
438
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
439
|
+
}
|
|
440
|
+
.outline {
|
|
441
|
+
outline-style: var(--tw-outline-style);
|
|
442
|
+
outline-width: 1px;
|
|
443
|
+
}
|
|
444
|
+
.blur {
|
|
445
|
+
--tw-blur: blur(8px);
|
|
446
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
447
|
+
}
|
|
448
|
+
.sepia {
|
|
449
|
+
--tw-sepia: sepia(100%);
|
|
450
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
451
|
+
}
|
|
452
|
+
.filter {
|
|
453
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
454
|
+
}
|
|
455
|
+
.outline-none {
|
|
456
|
+
--tw-outline-style: none;
|
|
457
|
+
outline-style: none;
|
|
458
|
+
}
|
|
459
|
+
.\[font\:inherit\] {
|
|
460
|
+
font: inherit;
|
|
461
|
+
}
|
|
462
|
+
.surface-bg {
|
|
463
|
+
background: var(--bg);
|
|
464
|
+
}
|
|
465
|
+
.surface-panel {
|
|
466
|
+
background: var(--panel);
|
|
467
|
+
}
|
|
468
|
+
.surface-panel-2 {
|
|
469
|
+
background: var(--panel-2);
|
|
470
|
+
}
|
|
471
|
+
.disabled\:cursor-default:disabled {
|
|
472
|
+
cursor: default;
|
|
473
|
+
}
|
|
474
|
+
.disabled\:opacity-50:disabled {
|
|
475
|
+
opacity: 50%;
|
|
476
|
+
}
|
|
477
|
+
.\[\&\>p\]\:m-0 > p {
|
|
478
|
+
margin: 0px;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
@property --tw-rotate-x {
|
|
482
|
+
syntax: "*";
|
|
483
|
+
inherits: false;
|
|
484
|
+
}
|
|
485
|
+
@property --tw-rotate-y {
|
|
486
|
+
syntax: "*";
|
|
487
|
+
inherits: false;
|
|
488
|
+
}
|
|
489
|
+
@property --tw-rotate-z {
|
|
490
|
+
syntax: "*";
|
|
491
|
+
inherits: false;
|
|
492
|
+
}
|
|
493
|
+
@property --tw-skew-x {
|
|
494
|
+
syntax: "*";
|
|
495
|
+
inherits: false;
|
|
496
|
+
}
|
|
497
|
+
@property --tw-skew-y {
|
|
498
|
+
syntax: "*";
|
|
499
|
+
inherits: false;
|
|
500
|
+
}
|
|
501
|
+
@property --tw-border-style {
|
|
502
|
+
syntax: "*";
|
|
503
|
+
inherits: false;
|
|
504
|
+
initial-value: solid;
|
|
505
|
+
}
|
|
506
|
+
@property --tw-leading {
|
|
507
|
+
syntax: "*";
|
|
508
|
+
inherits: false;
|
|
509
|
+
}
|
|
510
|
+
@property --tw-font-weight {
|
|
511
|
+
syntax: "*";
|
|
512
|
+
inherits: false;
|
|
513
|
+
}
|
|
514
|
+
@property --tw-tracking {
|
|
515
|
+
syntax: "*";
|
|
516
|
+
inherits: false;
|
|
517
|
+
}
|
|
518
|
+
@property --tw-ordinal {
|
|
519
|
+
syntax: "*";
|
|
520
|
+
inherits: false;
|
|
521
|
+
}
|
|
522
|
+
@property --tw-slashed-zero {
|
|
523
|
+
syntax: "*";
|
|
524
|
+
inherits: false;
|
|
525
|
+
}
|
|
526
|
+
@property --tw-numeric-figure {
|
|
527
|
+
syntax: "*";
|
|
528
|
+
inherits: false;
|
|
529
|
+
}
|
|
530
|
+
@property --tw-numeric-spacing {
|
|
531
|
+
syntax: "*";
|
|
532
|
+
inherits: false;
|
|
533
|
+
}
|
|
534
|
+
@property --tw-numeric-fraction {
|
|
535
|
+
syntax: "*";
|
|
536
|
+
inherits: false;
|
|
537
|
+
}
|
|
538
|
+
@property --tw-shadow {
|
|
539
|
+
syntax: "*";
|
|
540
|
+
inherits: false;
|
|
541
|
+
initial-value: 0 0 #0000;
|
|
542
|
+
}
|
|
543
|
+
@property --tw-shadow-color {
|
|
544
|
+
syntax: "*";
|
|
545
|
+
inherits: false;
|
|
546
|
+
}
|
|
547
|
+
@property --tw-shadow-alpha {
|
|
548
|
+
syntax: "<percentage>";
|
|
549
|
+
inherits: false;
|
|
550
|
+
initial-value: 100%;
|
|
551
|
+
}
|
|
552
|
+
@property --tw-inset-shadow {
|
|
553
|
+
syntax: "*";
|
|
554
|
+
inherits: false;
|
|
555
|
+
initial-value: 0 0 #0000;
|
|
556
|
+
}
|
|
557
|
+
@property --tw-inset-shadow-color {
|
|
558
|
+
syntax: "*";
|
|
559
|
+
inherits: false;
|
|
560
|
+
}
|
|
561
|
+
@property --tw-inset-shadow-alpha {
|
|
562
|
+
syntax: "<percentage>";
|
|
563
|
+
inherits: false;
|
|
564
|
+
initial-value: 100%;
|
|
565
|
+
}
|
|
566
|
+
@property --tw-ring-color {
|
|
567
|
+
syntax: "*";
|
|
568
|
+
inherits: false;
|
|
569
|
+
}
|
|
570
|
+
@property --tw-ring-shadow {
|
|
571
|
+
syntax: "*";
|
|
572
|
+
inherits: false;
|
|
573
|
+
initial-value: 0 0 #0000;
|
|
574
|
+
}
|
|
575
|
+
@property --tw-inset-ring-color {
|
|
576
|
+
syntax: "*";
|
|
577
|
+
inherits: false;
|
|
578
|
+
}
|
|
579
|
+
@property --tw-inset-ring-shadow {
|
|
580
|
+
syntax: "*";
|
|
581
|
+
inherits: false;
|
|
582
|
+
initial-value: 0 0 #0000;
|
|
583
|
+
}
|
|
584
|
+
@property --tw-ring-inset {
|
|
585
|
+
syntax: "*";
|
|
586
|
+
inherits: false;
|
|
587
|
+
}
|
|
588
|
+
@property --tw-ring-offset-width {
|
|
589
|
+
syntax: "<length>";
|
|
590
|
+
inherits: false;
|
|
591
|
+
initial-value: 0px;
|
|
592
|
+
}
|
|
593
|
+
@property --tw-ring-offset-color {
|
|
594
|
+
syntax: "*";
|
|
595
|
+
inherits: false;
|
|
596
|
+
initial-value: #fff;
|
|
597
|
+
}
|
|
598
|
+
@property --tw-ring-offset-shadow {
|
|
599
|
+
syntax: "*";
|
|
600
|
+
inherits: false;
|
|
601
|
+
initial-value: 0 0 #0000;
|
|
602
|
+
}
|
|
603
|
+
@property --tw-outline-style {
|
|
604
|
+
syntax: "*";
|
|
605
|
+
inherits: false;
|
|
606
|
+
initial-value: solid;
|
|
607
|
+
}
|
|
608
|
+
@property --tw-blur {
|
|
609
|
+
syntax: "*";
|
|
610
|
+
inherits: false;
|
|
611
|
+
}
|
|
612
|
+
@property --tw-brightness {
|
|
613
|
+
syntax: "*";
|
|
614
|
+
inherits: false;
|
|
615
|
+
}
|
|
616
|
+
@property --tw-contrast {
|
|
617
|
+
syntax: "*";
|
|
618
|
+
inherits: false;
|
|
619
|
+
}
|
|
620
|
+
@property --tw-grayscale {
|
|
621
|
+
syntax: "*";
|
|
622
|
+
inherits: false;
|
|
623
|
+
}
|
|
624
|
+
@property --tw-hue-rotate {
|
|
625
|
+
syntax: "*";
|
|
626
|
+
inherits: false;
|
|
627
|
+
}
|
|
628
|
+
@property --tw-invert {
|
|
629
|
+
syntax: "*";
|
|
630
|
+
inherits: false;
|
|
631
|
+
}
|
|
632
|
+
@property --tw-opacity {
|
|
633
|
+
syntax: "*";
|
|
634
|
+
inherits: false;
|
|
635
|
+
}
|
|
636
|
+
@property --tw-saturate {
|
|
637
|
+
syntax: "*";
|
|
638
|
+
inherits: false;
|
|
639
|
+
}
|
|
640
|
+
@property --tw-sepia {
|
|
641
|
+
syntax: "*";
|
|
642
|
+
inherits: false;
|
|
643
|
+
}
|
|
644
|
+
@property --tw-drop-shadow {
|
|
645
|
+
syntax: "*";
|
|
646
|
+
inherits: false;
|
|
647
|
+
}
|
|
648
|
+
@property --tw-drop-shadow-color {
|
|
649
|
+
syntax: "*";
|
|
650
|
+
inherits: false;
|
|
651
|
+
}
|
|
652
|
+
@property --tw-drop-shadow-alpha {
|
|
653
|
+
syntax: "<percentage>";
|
|
654
|
+
inherits: false;
|
|
655
|
+
initial-value: 100%;
|
|
656
|
+
}
|
|
657
|
+
@property --tw-drop-shadow-size {
|
|
658
|
+
syntax: "*";
|
|
659
|
+
inherits: false;
|
|
660
|
+
}
|
|
661
|
+
@layer properties {
|
|
662
|
+
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
663
|
+
*, ::before, ::after, ::backdrop {
|
|
664
|
+
--tw-rotate-x: initial;
|
|
665
|
+
--tw-rotate-y: initial;
|
|
666
|
+
--tw-rotate-z: initial;
|
|
667
|
+
--tw-skew-x: initial;
|
|
668
|
+
--tw-skew-y: initial;
|
|
669
|
+
--tw-border-style: solid;
|
|
670
|
+
--tw-leading: initial;
|
|
671
|
+
--tw-font-weight: initial;
|
|
672
|
+
--tw-tracking: initial;
|
|
673
|
+
--tw-ordinal: initial;
|
|
674
|
+
--tw-slashed-zero: initial;
|
|
675
|
+
--tw-numeric-figure: initial;
|
|
676
|
+
--tw-numeric-spacing: initial;
|
|
677
|
+
--tw-numeric-fraction: initial;
|
|
678
|
+
--tw-shadow: 0 0 #0000;
|
|
679
|
+
--tw-shadow-color: initial;
|
|
680
|
+
--tw-shadow-alpha: 100%;
|
|
681
|
+
--tw-inset-shadow: 0 0 #0000;
|
|
682
|
+
--tw-inset-shadow-color: initial;
|
|
683
|
+
--tw-inset-shadow-alpha: 100%;
|
|
684
|
+
--tw-ring-color: initial;
|
|
685
|
+
--tw-ring-shadow: 0 0 #0000;
|
|
686
|
+
--tw-inset-ring-color: initial;
|
|
687
|
+
--tw-inset-ring-shadow: 0 0 #0000;
|
|
688
|
+
--tw-ring-inset: initial;
|
|
689
|
+
--tw-ring-offset-width: 0px;
|
|
690
|
+
--tw-ring-offset-color: #fff;
|
|
691
|
+
--tw-ring-offset-shadow: 0 0 #0000;
|
|
692
|
+
--tw-outline-style: solid;
|
|
693
|
+
--tw-blur: initial;
|
|
694
|
+
--tw-brightness: initial;
|
|
695
|
+
--tw-contrast: initial;
|
|
696
|
+
--tw-grayscale: initial;
|
|
697
|
+
--tw-hue-rotate: initial;
|
|
698
|
+
--tw-invert: initial;
|
|
699
|
+
--tw-opacity: initial;
|
|
700
|
+
--tw-saturate: initial;
|
|
701
|
+
--tw-sepia: initial;
|
|
702
|
+
--tw-drop-shadow: initial;
|
|
703
|
+
--tw-drop-shadow-color: initial;
|
|
704
|
+
--tw-drop-shadow-alpha: 100%;
|
|
705
|
+
--tw-drop-shadow-size: initial;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
11
710
|
/* ---- ./base.css ---- */
|
|
12
711
|
/* Light, only under the `system` theme. This used to override `:root`
|
|
13
712
|
unconditionally, so choosing a dark theme on a light-mode laptop got
|
|
@@ -101,23 +800,31 @@ body::before {
|
|
|
101
800
|
`[aria-disabled='true']` twin rather than a rewrite, which leaves each
|
|
102
801
|
`button` selector at the specificity it had and every committed baseline
|
|
103
802
|
untouched. */
|
|
104
|
-
|
|
803
|
+
.btn {
|
|
804
|
+
/* The three an anchor brings that a `<button>` does not. Harmless on the
|
|
805
|
+
button form -- it has no underline and centres already -- and the reason
|
|
806
|
+
`Button` puts one class on both elements rather than keeping a twin
|
|
807
|
+
selector for each. */
|
|
105
808
|
text-decoration: none;
|
|
106
809
|
color: var(--text);
|
|
107
810
|
text-align: center;
|
|
108
811
|
}
|
|
109
812
|
|
|
110
|
-
|
|
813
|
+
.btn[aria-disabled='true'] {
|
|
111
814
|
/* A disabled anchor still takes the pointer, so say so. The click itself is
|
|
112
815
|
blocked in the capture phase by the component. */
|
|
113
816
|
cursor: not-allowed;
|
|
114
817
|
}
|
|
115
818
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
input,
|
|
119
|
-
|
|
120
|
-
|
|
819
|
+
/* `:where`, so this base carries no specificity of its own.
|
|
820
|
+
*
|
|
821
|
+
* It was `button, input, textarea, select` -- an element selector, which
|
|
822
|
+
* `.size-sm` and every other class outranked without anyone thinking about
|
|
823
|
+
* it. Moving it to `.btn` to stop a tab inheriting a control's look raised it
|
|
824
|
+
* to a class, so it tied with `.size-sm` and won on source order: every
|
|
825
|
+
* button came out `8px 12px` whatever size it asked for. `:where` puts it
|
|
826
|
+
* back to zero, which is what the element selector was silently providing. */
|
|
827
|
+
:where(.btn, input, textarea, select) {
|
|
121
828
|
font: inherit;
|
|
122
829
|
color: var(--text);
|
|
123
830
|
background: var(--control);
|
|
@@ -138,8 +845,7 @@ select {
|
|
|
138
845
|
the icon; the button simply had no opinion about how to arrange two things.
|
|
139
846
|
`inline-flex` and a gap gives it one, and the gap replaces the space
|
|
140
847
|
character people were putting between an icon and its label. */
|
|
141
|
-
|
|
142
|
-
a.btn {
|
|
848
|
+
.btn {
|
|
143
849
|
display: inline-flex;
|
|
144
850
|
align-items: center;
|
|
145
851
|
justify-content: center;
|
|
@@ -155,18 +861,41 @@ a.btn {
|
|
|
155
861
|
|
|
156
862
|
Several places already drew this by hand as `.chat-bar-btn.on`. This is the
|
|
157
863
|
same look, said once, on a plain button. */
|
|
158
|
-
|
|
864
|
+
.btn[aria-pressed='true'] {
|
|
159
865
|
border-color: var(--accent);
|
|
160
866
|
color: var(--accent);
|
|
161
867
|
background: color-mix(in srgb, var(--accent) 10%, var(--panel));
|
|
162
868
|
}
|
|
163
869
|
|
|
164
|
-
|
|
870
|
+
.btn[aria-pressed='true']:hover:not(:disabled) { border-color: var(--accent); }
|
|
165
871
|
|
|
166
872
|
/* The glyph never shrinks: in a narrow row flexbox would take it from the icon
|
|
167
873
|
before the text, and half an icon is not a smaller icon. */
|
|
168
|
-
|
|
169
|
-
|
|
874
|
+
.btn > svg { flex: none; }
|
|
875
|
+
|
|
876
|
+
/* `Select`'s control wears the control styling, and says so.
|
|
877
|
+
*
|
|
878
|
+
* It renders React Aria's `Button` -- a bare `<button>` -- and used to take
|
|
879
|
+
* `font`, colour, the surface and the border from the
|
|
880
|
+
* `button, input, textarea, select` reset without asking. When that reset
|
|
881
|
+
* moved to `.btn`, so a tab and a row would stop inheriting a control's look
|
|
882
|
+
* only to undo it, this lost all of it at once.
|
|
883
|
+
*
|
|
884
|
+
* Here rather than in `select.css`, and that placement is the rule, not
|
|
885
|
+
* tidiness: `font` is a shorthand and it resets `font-size`, so declared
|
|
886
|
+
* after `.size-sm` below it silently makes every small control full size.
|
|
887
|
+
* `index.css` says the import order is behaviour; this is what that means.
|
|
888
|
+
*
|
|
889
|
+
* `:where` for the same reason the reset above uses it: this is a base a
|
|
890
|
+
* `size` class has to be able to beat, and a bare class ties with one. */
|
|
891
|
+
:where(.sel-control) {
|
|
892
|
+
font: inherit;
|
|
893
|
+
color: var(--text);
|
|
894
|
+
background: var(--control);
|
|
895
|
+
border: var(--border-width) solid var(--border-strong);
|
|
896
|
+
border-radius: var(--radius);
|
|
897
|
+
cursor: pointer;
|
|
898
|
+
}
|
|
170
899
|
|
|
171
900
|
.size-sm { font-size: var(--text-xs); padding: var(--space-1) var(--space-2); }
|
|
172
901
|
|
|
@@ -191,8 +920,7 @@ input, textarea, select { width: 100%; }
|
|
|
191
920
|
same disagreement written twice. */
|
|
192
921
|
textarea { resize: none; }
|
|
193
922
|
|
|
194
|
-
|
|
195
|
-
a.btn:hover:not([aria-disabled='true']),
|
|
923
|
+
.btn:hover:not(:disabled),
|
|
196
924
|
input:hover:not(:disabled),
|
|
197
925
|
textarea:hover:not(:disabled),
|
|
198
926
|
select:hover:not(:disabled) { border-color: var(--accent); }
|
|
@@ -200,8 +928,7 @@ select:hover:not(:disabled) { border-color: var(--accent); }
|
|
|
200
928
|
/* `:focus-visible` on the button so a click does not leave a ring behind it,
|
|
201
929
|
`:focus` on the fields because a focused field is a place you are typing and
|
|
202
930
|
should say so however you got there. */
|
|
203
|
-
|
|
204
|
-
a.btn:focus-visible,
|
|
931
|
+
.btn:focus-visible,
|
|
205
932
|
input:focus,
|
|
206
933
|
textarea:focus,
|
|
207
934
|
select:focus { outline: none; border-color: var(--accent); }
|
|
@@ -294,14 +1021,13 @@ input[type='radio']:focus-visible { outline: none; box-shadow: var(--focus-ring)
|
|
|
294
1021
|
input[type='checkbox']:disabled,
|
|
295
1022
|
input[type='radio']:disabled { cursor: not-allowed; background: var(--panel-2); }
|
|
296
1023
|
|
|
297
|
-
|
|
298
|
-
|
|
1024
|
+
.btn:disabled,
|
|
1025
|
+
.btn[aria-disabled='true'],
|
|
299
1026
|
input:disabled,
|
|
300
1027
|
textarea:disabled,
|
|
301
1028
|
select:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
302
1029
|
|
|
303
|
-
|
|
304
|
-
a.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
|
1030
|
+
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
|
305
1031
|
|
|
306
1032
|
/* A disabled primary is not a faded primary.
|
|
307
1033
|
`opacity: .45` was the whole of it, and a coloured fill at 45% is still a
|
|
@@ -309,8 +1035,7 @@ a.btn.primary { background: var(--accent); border-color: var(--accent); color: v
|
|
|
309
1035
|
thing on the panel. That got worse when onboarding started holding people at
|
|
310
1036
|
a disabled Next. So it gives up the fill entirely and becomes the shape of a
|
|
311
1037
|
disabled control -- the opacity then has nothing left to do. */
|
|
312
|
-
|
|
313
|
-
a.btn.primary[aria-disabled='true'] {
|
|
1038
|
+
.btn.primary:disabled {
|
|
314
1039
|
background: var(--panel-2);
|
|
315
1040
|
border-color: var(--border);
|
|
316
1041
|
color: var(--muted);
|
|
@@ -324,7 +1049,7 @@ a.btn.primary[aria-disabled='true'] {
|
|
|
324
1049
|
line under it that travels.
|
|
325
1050
|
`aria-busy` rather than a class: the attribute is what a screen reader reads,
|
|
326
1051
|
and styling the thing that carries the meaning is how they stay in step. */
|
|
327
|
-
|
|
1052
|
+
.btn[aria-busy='true'] {
|
|
328
1053
|
position: relative;
|
|
329
1054
|
overflow: hidden;
|
|
330
1055
|
cursor: progress;
|
|
@@ -337,18 +1062,18 @@ button[aria-busy='true'] {
|
|
|
337
1062
|
something that is working, that reads as a control that failed and went
|
|
338
1063
|
grey. So a busy button keeps every colour it had and takes only the loss of
|
|
339
1064
|
the cursor and the press; the travelling line is what says why. */
|
|
340
|
-
|
|
1065
|
+
.btn[aria-busy='true']:disabled {
|
|
341
1066
|
opacity: 1;
|
|
342
1067
|
cursor: progress;
|
|
343
1068
|
}
|
|
344
1069
|
|
|
345
|
-
|
|
1070
|
+
.btn.primary[aria-busy='true']:disabled {
|
|
346
1071
|
background: var(--accent);
|
|
347
1072
|
border-color: var(--accent);
|
|
348
1073
|
color: var(--on-accent);
|
|
349
1074
|
}
|
|
350
1075
|
|
|
351
|
-
|
|
1076
|
+
.btn[aria-busy='true']::after {
|
|
352
1077
|
content: '';
|
|
353
1078
|
position: absolute;
|
|
354
1079
|
left: 0;
|
|
@@ -380,15 +1105,13 @@ button[aria-busy='true']::after {
|
|
|
380
1105
|
|
|
381
1106
|
/* Quiet: no border, no fill. For the action beside the action -- Cancel next to
|
|
382
1107
|
Save -- where a bordered box competes with the thing it is next to. */
|
|
383
|
-
|
|
384
|
-
a.btn.ghost {
|
|
1108
|
+
.btn.ghost {
|
|
385
1109
|
background: transparent;
|
|
386
1110
|
border-color: transparent;
|
|
387
1111
|
color: var(--muted);
|
|
388
1112
|
}
|
|
389
1113
|
|
|
390
|
-
|
|
391
|
-
a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
1114
|
+
.btn.ghost:hover:not(:disabled) {
|
|
392
1115
|
background: var(--panel-2);
|
|
393
1116
|
border-color: transparent;
|
|
394
1117
|
color: var(--text);
|
|
@@ -470,7 +1193,7 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
470
1193
|
header.) */
|
|
471
1194
|
.row { display: flex; align-items: center; gap: var(--space-3); }
|
|
472
1195
|
|
|
473
|
-
.grow { flex: 1; min-width: 0; }
|
|
1196
|
+
.ctl-grow { flex: 1; min-width: 0; }
|
|
474
1197
|
|
|
475
1198
|
.mono { font-family: var(--font-mono); font-size: var(--text-sm); }
|
|
476
1199
|
|
|
@@ -534,10 +1257,17 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
534
1257
|
/* A pill following a name needs the gap outside its own border. Leading
|
|
535
1258
|
whitespace inside the span puts it under the pill's background instead,
|
|
536
1259
|
which reads as the badge touching the word it qualifies. */
|
|
537
|
-
|
|
1260
|
+
/* A pill beside a name, and the one thing that keeps the pair working:
|
|
1261
|
+
`flex: none`, so the pill never shrinks and the name ellipsises instead.
|
|
1262
|
+
That was `rows.css`'s `.named > .pill`, which meant anybody laying out a
|
|
1263
|
+
name and its pills had to know a package class by name to get it. The
|
|
1264
|
+
variant already says "I am in a row"; it may as well say what that costs. */
|
|
1265
|
+
.row-pill { margin-left: var(--space-2); vertical-align: baseline; flex: none; }
|
|
538
1266
|
|
|
539
1267
|
/* The tile's only control. Dim until hovered: it is chrome on someone's app. */
|
|
540
1268
|
.icon-btn {
|
|
1269
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
1270
|
+
font: inherit;
|
|
541
1271
|
display: inline-flex; align-items: center; padding: var(--space-1);
|
|
542
1272
|
background: none; border: 0; color: var(--muted); opacity: 0.6; cursor: pointer;
|
|
543
1273
|
}
|
|
@@ -603,19 +1333,17 @@ a.btn.ghost:hover:not([aria-disabled='true']) {
|
|
|
603
1333
|
transition: none;
|
|
604
1334
|
}
|
|
605
1335
|
|
|
606
|
-
|
|
607
|
-
a.btn.primary:active:not([aria-disabled='true']) {
|
|
1336
|
+
.btn.primary:active:not(:disabled) {
|
|
608
1337
|
background: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
|
|
609
1338
|
border-color: color-mix(in srgb, var(--text) var(--press-ink), var(--accent));
|
|
610
1339
|
}
|
|
611
1340
|
|
|
612
|
-
|
|
613
|
-
a.btn.ghost:active:not([aria-disabled='true']) {
|
|
1341
|
+
.btn.ghost:active:not(:disabled) {
|
|
614
1342
|
background: color-mix(in srgb, var(--text) var(--press-ink), var(--panel-2));
|
|
615
1343
|
border-color: transparent;
|
|
616
1344
|
}
|
|
617
1345
|
|
|
618
|
-
|
|
1346
|
+
.btn[aria-pressed='true']:active:not(:disabled) {
|
|
619
1347
|
background: color-mix(in srgb, var(--accent) 18%, var(--panel));
|
|
620
1348
|
}
|
|
621
1349
|
|
|
@@ -786,7 +1514,7 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
786
1514
|
|
|
787
1515
|
/* The top bar carries the title, the views and the way into settings. Nothing
|
|
788
1516
|
that belongs to a conversation lives here any more, so it can breathe. */
|
|
789
|
-
.topbar .grow { flex: 1; min-width: 0; }
|
|
1517
|
+
.topbar .ctl-grow { flex: 1; min-width: 0; }
|
|
790
1518
|
|
|
791
1519
|
/* Back on the left, Next on the right, with the gap between them doing the
|
|
792
1520
|
separating -- so the button that goes forward is in the same place on both
|
|
@@ -818,6 +1546,57 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
818
1546
|
to { opacity: 1; }
|
|
819
1547
|
}
|
|
820
1548
|
|
|
1549
|
+
/* The states the `button` element rule used to hand every bare `<button>` in
|
|
1550
|
+
the package, now asked for by name.
|
|
1551
|
+
*
|
|
1552
|
+
* This is the half of the decoupling that a screenshot cannot show: `:focus-visible`
|
|
1553
|
+
* is not photographed, so nine components would have lost their focus ring in
|
|
1554
|
+
* silence. `keyboard.spec.ts` is what actually holds this.
|
|
1555
|
+
*
|
|
1556
|
+
* `.btn` has its own, in the rules above. These are the ones that are a button
|
|
1557
|
+
* for their behaviour and not for their appearance -- a tab, a row, a card, a
|
|
1558
|
+
* pager step, a grid cell, a remove cross. */
|
|
1559
|
+
.tab:focus-visible,
|
|
1560
|
+
.row-hit:focus-visible,
|
|
1561
|
+
.card:focus-visible,
|
|
1562
|
+
.ident-remove:focus-visible,
|
|
1563
|
+
.size-cell:focus-visible,
|
|
1564
|
+
.pager-step:focus-visible,
|
|
1565
|
+
.pager-page:focus-visible,
|
|
1566
|
+
.sel-control:focus-visible {
|
|
1567
|
+
outline: 2px solid var(--accent);
|
|
1568
|
+
outline-offset: 2px;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
/* `:disabled` came from the same rule. A control that cannot be pressed has to
|
|
1572
|
+
say so whatever element it is. */
|
|
1573
|
+
.tab:disabled,
|
|
1574
|
+
.row-hit:disabled,
|
|
1575
|
+
.card:disabled,
|
|
1576
|
+
.ident-remove:disabled,
|
|
1577
|
+
.size-cell:disabled,
|
|
1578
|
+
.pager-step:disabled,
|
|
1579
|
+
.pager-page:disabled,
|
|
1580
|
+
.sel-control:disabled {
|
|
1581
|
+
opacity: 0.45;
|
|
1582
|
+
cursor: not-allowed;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/* The anchor form's disabled states, alongside the button's.
|
|
1586
|
+
*
|
|
1587
|
+
* `.btn` is one class on two elements, and an `<a>` has no `:disabled` -- it
|
|
1588
|
+
* carries `aria-disabled` and a capture-phase click block instead. Every
|
|
1589
|
+
* rule above that reads `:disabled` needs the attribute twin, or a disabled
|
|
1590
|
+
* link is a link that looks pressable and refuses silently. Folding the old
|
|
1591
|
+
* `a.btn` twins into `.btn` dropped these, and the baselines showed a
|
|
1592
|
+
* disabled link at full strength. */
|
|
1593
|
+
.btn.primary[aria-disabled='true'] {
|
|
1594
|
+
background: var(--panel-2);
|
|
1595
|
+
border-color: var(--border);
|
|
1596
|
+
color: var(--muted);
|
|
1597
|
+
opacity: 1;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
821
1600
|
/* ---- ./select.css ---- */
|
|
822
1601
|
/* How big a control is, asked for rather than inherited.
|
|
823
1602
|
Four sizes existed and every one of them came from a descendant selector:
|
|
@@ -833,8 +1612,7 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
833
1612
|
/* Full width, for the one action a card or a step is about. Not a size: a
|
|
834
1613
|
`block` button is the same height as any other, it just stops being a thing
|
|
835
1614
|
you have to aim at. */
|
|
836
|
-
|
|
837
|
-
a.btn.block { display: flex; width: 100%; }
|
|
1615
|
+
.btn.ctl-block { display: flex; width: 100%; }
|
|
838
1616
|
|
|
839
1617
|
/* The default is `size-md`, spelled once for every control.
|
|
840
1618
|
The paragraph above promised one scale for buttons, inputs and selects, and
|
|
@@ -842,13 +1620,24 @@ a.btn.block { display: flex; width: 100%; }
|
|
|
842
1620
|
input was eight pixels taller than the button beside it and no row of the two
|
|
843
1621
|
could line up. The download modal's search box against its Search button was
|
|
844
1622
|
the version you could see from across the room. */
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
input,
|
|
848
|
-
|
|
849
|
-
|
|
1623
|
+
/* `:where`, so this base carries no specificity of its own.
|
|
1624
|
+
*
|
|
1625
|
+
* It was `button, input, textarea, select` -- an element selector, which
|
|
1626
|
+
* `.size-sm` and every other class outranked without anyone thinking about
|
|
1627
|
+
* it. Moving it to `.btn` to stop a tab inheriting a control's look raised it
|
|
1628
|
+
* to a class, so it tied with `.size-sm` and won on source order: every
|
|
1629
|
+
* button came out `8px 12px` whatever size it asked for. `:where` puts it
|
|
1630
|
+
* back to zero, which is what the element selector was silently providing. */
|
|
1631
|
+
:where(.btn, input, textarea, select) { padding: var(--space-2) var(--space-3); }
|
|
1632
|
+
|
|
1633
|
+
/* The select's control keeps its padding at full class weight, and after
|
|
1634
|
+
`.size-sm` in the cascade, because that is where it has always been: this
|
|
1635
|
+
file is imported after `base.css`, so a `size`d select took the size's type
|
|
1636
|
+
and this padding. Folding it into the `:where` above handed the padding
|
|
1637
|
+
back to `.size-sm` and shrank every small select by seven pixels. */
|
|
850
1638
|
.sel-control { padding: var(--space-2) var(--space-3); }
|
|
851
1639
|
|
|
1640
|
+
|
|
852
1641
|
/* Centred on the whole block -- the caption and the sentence together -- rather
|
|
853
1642
|
than aligned to either end of it. `.field-row` pins to the bottom, which is
|
|
854
1643
|
right for a field beside a button and wrong beside two lines of prose. */
|
|
@@ -872,16 +1661,16 @@ select,
|
|
|
872
1661
|
.sel { position: relative; display: inline-block; }
|
|
873
1662
|
|
|
874
1663
|
/* The subject of its pane rather than a field in it: full width and a size up.
|
|
875
|
-
That was `.select-field.block` on the native element, and it carried the
|
|
1664
|
+
That was `.select-field.ctl-block` on the native element, and it carried the
|
|
876
1665
|
reason with it -- model ids are long (`qwen2.5-coder:32b-instruct-q4_K_M`) and
|
|
877
1666
|
at the narrow size they truncated mid-name. */
|
|
878
|
-
.sel.block { display: block; width: 100%; }
|
|
1667
|
+
.sel.ctl-block { display: block; width: 100%; }
|
|
879
1668
|
|
|
880
|
-
.sel.block .sel-control { padding: var(--space-2) var(--space-3); font-weight: 500; }
|
|
1669
|
+
.sel.ctl-block .sel-control { padding: var(--space-2) var(--space-3); font-weight: 500; }
|
|
881
1670
|
|
|
882
1671
|
/* Not full width otherwise: a select as wide as its row, holding one short
|
|
883
1672
|
word, reads as an input somebody forgot to fill in. */
|
|
884
|
-
.sel:not(.block) .sel-control { width: auto; max-width: 320px; }
|
|
1673
|
+
.sel:not(.ctl-block) .sel-control { width: auto; max-width: 320px; }
|
|
885
1674
|
|
|
886
1675
|
.sel-control {
|
|
887
1676
|
display: flex;
|
|
@@ -894,9 +1683,7 @@ select,
|
|
|
894
1683
|
background: var(--control);
|
|
895
1684
|
}
|
|
896
1685
|
|
|
897
|
-
.sel-
|
|
898
|
-
|
|
899
|
-
.sel-caret { flex: none; opacity: 0.6; transition: transform var(--dur-fast) var(--ease); }
|
|
1686
|
+
.sel-caret { transition: transform var(--dur-fast) var(--ease); }
|
|
900
1687
|
|
|
901
1688
|
.sel[data-open] .sel-caret { transform: rotate(180deg); }
|
|
902
1689
|
|
|
@@ -905,21 +1692,7 @@ select,
|
|
|
905
1692
|
/* State is read off React Aria's attributes: `data-open` on the root,
|
|
906
1693
|
`data-focused` / `data-selected` / `data-disabled` on an item, where
|
|
907
1694
|
`.open`, `[data-active]`, `.on` and `.off` used to be. */
|
|
908
|
-
.sel-list {
|
|
909
|
-
/* `fixed`, and in `document.body`: an ancestor that scrolls or hides its
|
|
910
|
-
overflow would otherwise clip it, which in this app means every settings
|
|
911
|
-
pane. Position comes from the button's measured rectangle. */
|
|
912
|
-
/* Positioned by React Aria -- inline `top`/`left` on a portalled popover
|
|
913
|
-
that flips when the edge is near. `position: fixed` and the measured
|
|
914
|
-
rectangle it was placed by are gone with the hand-rolled version. */
|
|
915
|
-
z-index: 60;
|
|
916
|
-
max-height: 280px;
|
|
917
|
-
overflow-y: auto;
|
|
918
|
-
margin: 0;
|
|
919
|
-
padding: var(--space-1);
|
|
920
|
-
/* The same room while the list is scrolled as it has at rest. Padding at
|
|
921
|
-
the top of a scroll container scrolls away with the content, so the row
|
|
922
|
-
`scrollIntoView({block: 'nearest'})` brings up ended flush against the
|
|
1695
|
+
.sel-list { scroll-padding-block: var(--space-1); box-shadow: var(--shadow-2); })` brings up ended flush against the
|
|
923
1696
|
border and read as clipped rather than as one of a set -- and this list
|
|
924
1697
|
opens scrolled to whatever is chosen, so that was the ordinary state.
|
|
925
1698
|
`scroll-padding` insets what counts as "in view", so it stops short by
|
|
@@ -932,18 +1705,6 @@ select,
|
|
|
932
1705
|
box-shadow: var(--shadow-2);
|
|
933
1706
|
}
|
|
934
1707
|
|
|
935
|
-
.sel-item {
|
|
936
|
-
display: flex;
|
|
937
|
-
align-items: center;
|
|
938
|
-
gap: var(--space-2);
|
|
939
|
-
padding: var(--space-2) var(--space-2);
|
|
940
|
-
border-radius: var(--radius-sm);
|
|
941
|
-
cursor: pointer;
|
|
942
|
-
white-space: nowrap;
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
.sel-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
946
|
-
|
|
947
1708
|
/* Hover and keyboard land on the same row, because they are the same idea --
|
|
948
1709
|
two highlights for one cursor is how a list starts lying about where Enter
|
|
949
1710
|
will go. */
|
|
@@ -955,8 +1716,6 @@ select,
|
|
|
955
1716
|
|
|
956
1717
|
/* The tick marks the chosen row. Colour alone would not: a list where the only
|
|
957
1718
|
difference is a hue is a list you cannot read past. */
|
|
958
|
-
.sel-tick { flex: none; opacity: 0; }
|
|
959
|
-
|
|
960
1719
|
.sel-item[data-selected] .sel-tick { opacity: 1; }
|
|
961
1720
|
|
|
962
1721
|
/* The icon on a speaker's row in the open list -- `Select`'s `aside`. Last in
|
|
@@ -994,21 +1753,18 @@ select,
|
|
|
994
1753
|
|
|
995
1754
|
/* ---- ./dangerzone.css ---- */
|
|
996
1755
|
/* Destructive, and legible as such standing still. */
|
|
997
|
-
|
|
998
|
-
a.btn.danger {
|
|
1756
|
+
.btn.danger {
|
|
999
1757
|
color: var(--bad);
|
|
1000
1758
|
border-color: color-mix(in srgb, var(--bad) 45%, var(--border-strong));
|
|
1001
1759
|
}
|
|
1002
1760
|
|
|
1003
|
-
|
|
1004
|
-
a.btn.danger:hover:not([aria-disabled='true']) {
|
|
1761
|
+
.btn.danger:hover:not(:disabled) {
|
|
1005
1762
|
background: color-mix(in srgb, var(--bad) 12%, var(--panel));
|
|
1006
1763
|
border-color: var(--bad);
|
|
1007
1764
|
color: var(--bad);
|
|
1008
1765
|
}
|
|
1009
1766
|
|
|
1010
|
-
|
|
1011
|
-
a.btn.danger:active:not([aria-disabled='true']) {
|
|
1767
|
+
.btn.danger:active:not(:disabled) {
|
|
1012
1768
|
background: color-mix(in srgb, var(--bad) 20%, var(--panel));
|
|
1013
1769
|
border-color: var(--bad);
|
|
1014
1770
|
}
|
|
@@ -1249,33 +2005,46 @@ a.btn.danger:active:not([aria-disabled='true']) {
|
|
|
1249
2005
|
.callout button { flex: none; }
|
|
1250
2006
|
|
|
1251
2007
|
/* ---- ./card.css ---- */
|
|
2008
|
+
/* `.card` is public API, not this component's private styling.
|
|
2009
|
+
*
|
|
2010
|
+
* Consumers apply it to their own markup -- the gallery's skeleton specimen
|
|
2011
|
+
* renders `<div className="card">` around three rows, and app-template uses
|
|
2012
|
+
* `card-pick`. Moving the box into `Card`'s own class list took that away
|
|
2013
|
+
* with no type error and no failing test in this package: it broke only
|
|
2014
|
+
* where somebody else had used the class, which is the worst way for an API
|
|
2015
|
+
* to go.
|
|
2016
|
+
*
|
|
2017
|
+
* So the rule stays and `Card` wears it. The lesson generalises to every
|
|
2018
|
+
* class in this package that a consumer can reach: a component may draw
|
|
2019
|
+
* itself with utilities only where its class is genuinely private. */
|
|
1252
2020
|
.card {
|
|
2021
|
+
display: block;
|
|
2022
|
+
width: 100%;
|
|
2023
|
+
box-sizing: border-box;
|
|
2024
|
+
font: inherit;
|
|
2025
|
+
color: var(--text);
|
|
2026
|
+
text-align: left;
|
|
1253
2027
|
background: var(--panel);
|
|
1254
2028
|
border: var(--border-width) solid var(--border);
|
|
1255
2029
|
border-radius: var(--radius-md);
|
|
1256
|
-
padding: var(--space-3)
|
|
2030
|
+
padding: var(--space-3);
|
|
1257
2031
|
margin-bottom: var(--space-3);
|
|
1258
2032
|
}
|
|
1259
2033
|
|
|
2034
|
+
/* What is left once `Card` draws its own box: the tones, the pick and
|
|
2035
|
+
selected states, and the rules that reach from the card into what it
|
|
2036
|
+
holds. `:has(.card-icon) .card-inline` is a relationship, and a tone is a
|
|
2037
|
+
`color-mix`; neither is a property on one element. */
|
|
2038
|
+
|
|
1260
2039
|
/* Header, when there is one. The title and the line under it were retyped at
|
|
1261
2040
|
every call site and no two agreed on the gap between them. */
|
|
1262
|
-
.card-head { display: flex; align-items: flex-start; gap: var(--space-3); }
|
|
1263
|
-
|
|
1264
|
-
.card-head:not(:last-child) { margin-bottom: var(--space-3); }
|
|
1265
|
-
|
|
1266
|
-
.card-headings { min-width: 0; flex: 1; }
|
|
1267
|
-
|
|
1268
2041
|
/* The card owns the space between the things it holds. Without this a callout
|
|
1269
2042
|
and the button under it sit edge to edge, and every caller has to remember a
|
|
1270
2043
|
margin on whichever child happens to be second. */
|
|
1271
|
-
.card-body { display: grid; gap: var(--space-3); }
|
|
1272
|
-
|
|
1273
2044
|
/* The card's own control, on the card's padding rather than indented into its
|
|
1274
2045
|
body. Centred against the whole heading block, not against the title -- a
|
|
1275
2046
|
switch aligned to the first line drifts upward the moment the description
|
|
1276
2047
|
runs to two. */
|
|
1277
|
-
.card-action { flex: none; align-self: center; display: flex; align-items: center; }
|
|
1278
|
-
|
|
1279
2048
|
/* A row inside a card that lines up with the header rather than indenting past
|
|
1280
2049
|
it: same left edge as the title, same right edge as the action. Its label is
|
|
1281
2050
|
a quiet caption, not a second heading -- the card already has one, and two
|
|
@@ -1322,17 +2091,6 @@ a.btn.danger:active:not([aria-disabled='true']) {
|
|
|
1322
2091
|
color: var(--muted);
|
|
1323
2092
|
}
|
|
1324
2093
|
|
|
1325
|
-
/* A card that is itself the choice. Reset first, because it is a `<button>`
|
|
1326
|
-
now and inherits a control's padding and centring. */
|
|
1327
|
-
button.card {
|
|
1328
|
-
display: block;
|
|
1329
|
-
width: 100%;
|
|
1330
|
-
text-align: left;
|
|
1331
|
-
font: inherit;
|
|
1332
|
-
color: inherit;
|
|
1333
|
-
padding: var(--space-3);
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
2094
|
/* Variants, because a card is doing four jobs and looked like one.
|
|
1337
2095
|
A search result you can act on, a thing already installed, something that
|
|
1338
2096
|
went wrong, and a heading with rows under it are not the same object, and
|
|
@@ -1375,6 +2133,20 @@ button.card {
|
|
|
1375
2133
|
|
|
1376
2134
|
.modal-body .card { background: var(--panel-2); }
|
|
1377
2135
|
|
|
2136
|
+
/* Selected, which used to arrive from `button[aria-pressed='true']`.
|
|
2137
|
+
*
|
|
2138
|
+
* A card marks its choice with `aria-pressed`, and the tint came from the
|
|
2139
|
+
* element rule every bare `<button>` in the package was picking up. That rule
|
|
2140
|
+
* belongs to `Button` now, so the card says what being chosen looks like --
|
|
2141
|
+
* which is the right place for it anyway: a chosen card is a card's idea, not
|
|
2142
|
+
* a button's. */
|
|
2143
|
+
.card[aria-pressed='true'] {
|
|
2144
|
+
border-color: var(--accent);
|
|
2145
|
+
background: color-mix(in srgb, var(--accent) 10%, var(--panel));
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
.card[aria-pressed='true']:hover { border-color: var(--accent); }
|
|
2149
|
+
|
|
1378
2150
|
/* ---- ./toggle.css ---- */
|
|
1379
2151
|
.card-action .switch-row { padding: 0; gap: var(--space-2); }
|
|
1380
2152
|
|
|
@@ -1925,71 +2697,21 @@ input[type='radio']:active:not(:disabled) {
|
|
|
1925
2697
|
|
|
1926
2698
|
.row-hit:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
1927
2699
|
|
|
1928
|
-
/* ---- ./empty.css ---- */
|
|
1929
|
-
/* `Empty`: a list with nothing in it.
|
|
1930
|
-
|
|
1931
|
-
Quieter than `.empty`, which is a whole-screen state at `--space-10`. These
|
|
1932
|
-
sit inside a card that already has a heading and a description, so the same
|
|
1933
|
-
padding would leave a card that is mostly air about nothing.
|
|
1934
|
-
|
|
1935
|
-
Dashed rather than solid: a solid border reads as a thing, and the point of
|
|
1936
|
-
this box is that there is no thing. It marks out where the list will be. */
|
|
1937
|
-
.nothing {
|
|
1938
|
-
display: grid;
|
|
1939
|
-
justify-items: center;
|
|
1940
|
-
gap: var(--space-2);
|
|
1941
|
-
padding: var(--space-5) var(--space-4);
|
|
1942
|
-
border: var(--border-width) dashed var(--border-strong);
|
|
1943
|
-
border-radius: var(--radius-md);
|
|
1944
|
-
text-align: center;
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
|
-
.nothing-mark { color: var(--muted); line-height: 0; }
|
|
1948
|
-
|
|
1949
|
-
/* The same box with a figure in it, for a whole surface rather than a slot in
|
|
1950
|
-
a card. Two things change and both follow from the size: the dashed outline
|
|
1951
|
-
goes, because an outline marks out where a list will be and a window-sized
|
|
1952
|
-
dashed rectangle reads as a layout that failed rather than a view with
|
|
1953
|
-
nothing on it; and the box centres itself in whatever it was dropped into,
|
|
1954
|
-
which is what makes it land in the middle of an empty dashboard rather than
|
|
1955
|
-
under the header. */
|
|
1956
|
-
.nothing-surface {
|
|
1957
|
-
border: none;
|
|
1958
|
-
padding: var(--space-10) var(--space-4);
|
|
1959
|
-
gap: var(--space-3);
|
|
1960
|
-
margin: auto;
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
/* `currentColor` reaches the figure through the two rules the illustrations
|
|
1964
|
-
ship with, so the colour is set here and the drawing follows it -- the same
|
|
1965
|
-
grey as the sentence under it, in every theme.
|
|
1966
|
-
Two classes, not one: `.illo` sets `color: inherit` further down this file,
|
|
1967
|
-
which beats a single-class rule written earlier and drew the figure in full
|
|
1968
|
-
text black beside a muted sentence. */
|
|
1969
|
-
.nothing-surface .nothing-figure { color: var(--muted); }
|
|
1970
|
-
|
|
1971
|
-
/* `--text-sm`, not the `--text-xs` these lines used to be: it is a sentence
|
|
1972
|
-
somebody is meant to read, not a caption qualifying something else. */
|
|
1973
|
-
.nothing-said { margin: 0; color: var(--muted); font-size: var(--text-sm); line-height: 1.5; max-width: 46ch; }
|
|
1974
|
-
|
|
1975
|
-
.nothing-act { margin-top: var(--space-1); }
|
|
1976
|
-
|
|
1977
2700
|
/* ---- ./progress.css ---- */
|
|
1978
2701
|
/* progress ----------------------------------------------------------- */
|
|
1979
2702
|
|
|
1980
|
-
/* The bar
|
|
2703
|
+
/* The bar itself: a track with a child it fills, an animation and a
|
|
2704
|
+
reduced-motion answer. A utility is a property on one element, so none of
|
|
2705
|
+
that is one -- `Progress` draws its own wrapper and head with utilities and
|
|
2706
|
+
this is what is left.
|
|
2707
|
+
|
|
2708
|
+
The bar sat 4px under its own label and flush against whatever was above
|
|
1981
2709
|
the whole block, so a download row read as four lines of text with a rule
|
|
1982
2710
|
drawn through the last one. The label is a caption for the bar and stays
|
|
1983
2711
|
close to it; the block as a whole is a separate statement from the row it
|
|
1984
2712
|
follows. */
|
|
1985
|
-
.progress { display: grid; gap: var(--space-1); }
|
|
1986
|
-
|
|
1987
2713
|
.card > .progress { margin-top: var(--space-3); }
|
|
1988
2714
|
|
|
1989
|
-
.progress-head { display: flex; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); }
|
|
1990
|
-
|
|
1991
|
-
.progress-detail { color: var(--muted); font-size: var(--text-xs); }
|
|
1992
|
-
|
|
1993
2715
|
.bar { height: 6px; background: var(--panel-2); border-radius: var(--radius-pill); overflow: hidden; }
|
|
1994
2716
|
|
|
1995
2717
|
.bar > i {
|
|
@@ -2023,6 +2745,14 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2023
2745
|
.tabs { position: relative; display: flex; gap: var(--space-1); }
|
|
2024
2746
|
|
|
2025
2747
|
.tab {
|
|
2748
|
+
/* Layout the `button` element rule used to supply. A tab is a button for its behaviour, not its look, so it now says what it wants instead of taking a control's arrangement and undoing the rest. */
|
|
2749
|
+
display: inline-flex;
|
|
2750
|
+
align-items: center;
|
|
2751
|
+
justify-content: center;
|
|
2752
|
+
gap: var(--space-2);
|
|
2753
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
2754
|
+
font: inherit;
|
|
2755
|
+
cursor: pointer;
|
|
2026
2756
|
position: relative;
|
|
2027
2757
|
z-index: 1;
|
|
2028
2758
|
background: transparent;
|
|
@@ -2179,6 +2909,38 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2179
2909
|
.toast[data-exiting] { animation: none; }
|
|
2180
2910
|
}
|
|
2181
2911
|
|
|
2912
|
+
/* The dismiss control, in its own words.
|
|
2913
|
+
*
|
|
2914
|
+
* It was `className="ghost size-sm"` -- `Button`'s vocabulary, borrowed from
|
|
2915
|
+
* a component that does not render a `Button`. That only ever worked because
|
|
2916
|
+
* `.ghost` and `.size-sm` were element-and-class rules any `<button>` could
|
|
2917
|
+
* pick up, which is the coupling this pass is removing. Nothing photographed
|
|
2918
|
+
* it, either: the toast is transient and the close button is not in any
|
|
2919
|
+
* baseline, so this would have gone quiet. */
|
|
2920
|
+
.toast-close {
|
|
2921
|
+
display: inline-flex;
|
|
2922
|
+
align-items: center;
|
|
2923
|
+
justify-content: center;
|
|
2924
|
+
font: inherit;
|
|
2925
|
+
font-size: var(--text-xs);
|
|
2926
|
+
padding: var(--space-1) var(--space-2);
|
|
2927
|
+
background: transparent;
|
|
2928
|
+
border: var(--border-width) solid transparent;
|
|
2929
|
+
border-radius: var(--radius);
|
|
2930
|
+
color: var(--muted);
|
|
2931
|
+
cursor: pointer;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
.toast-close:hover:not(:disabled) {
|
|
2935
|
+
background: var(--panel-2);
|
|
2936
|
+
color: var(--text);
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
.toast-close:focus-visible {
|
|
2940
|
+
outline: 2px solid var(--accent);
|
|
2941
|
+
outline-offset: 2px;
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2182
2944
|
/* ---- ./modal.css ---- */
|
|
2183
2945
|
/* modal --------------------------------------------------------------- */
|
|
2184
2946
|
|
|
@@ -2219,13 +2981,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2219
2981
|
Not `display: contents`, which was the first attempt. An element with no box
|
|
2220
2982
|
cannot take focus, so React Aria's initial focus fell through to the first
|
|
2221
2983
|
input and Escape -- handled on the section -- stopped closing the window. */
|
|
2222
|
-
.modal-dialog {
|
|
2223
|
-
display: flex;
|
|
2224
|
-
flex-direction: column;
|
|
2225
|
-
min-height: 0;
|
|
2226
|
-
flex: 1;
|
|
2227
|
-
}
|
|
2228
|
-
|
|
2229
2984
|
.modal {
|
|
2230
2985
|
background: var(--panel);
|
|
2231
2986
|
border: 1px solid var(--border);
|
|
@@ -2276,18 +3031,9 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2276
3031
|
laid out for the bare `<strong>` it used to hold -- 86px tall with them,
|
|
2277
3032
|
41px without, on a head whose padding is 12 over 8. `font: inherit` so the
|
|
2278
3033
|
`<strong>` rule above is the one that sets the size. */
|
|
2279
|
-
.modal-title { margin: 0; font: inherit; }
|
|
2280
|
-
|
|
2281
3034
|
/* Under the title, on the header's padding rather than the body's, so it reads
|
|
2282
3035
|
as part of the heading rather than as the first line of content. */
|
|
2283
|
-
.modal-desc {
|
|
2284
|
-
margin: 0;
|
|
2285
|
-
padding: 0 var(--space-4) var(--space-3);
|
|
2286
|
-
color: var(--muted);
|
|
2287
|
-
font-size: var(--text-sm);
|
|
2288
|
-
line-height: 1.5;
|
|
2289
|
-
max-width: 62ch;
|
|
2290
|
-
}
|
|
3036
|
+
.modal-desc { line-height: 1.5; }
|
|
2291
3037
|
|
|
2292
3038
|
.modal-body { padding: var(--space-2) var(--space-4) var(--space-3); overflow-y: auto; }
|
|
2293
3039
|
|
|
@@ -2647,7 +3393,8 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
2647
3393
|
buttons only, so a button in a row stood 25px beside a 35px select and no
|
|
2648
3394
|
size class could ask for the select's height. Type from the row, box from
|
|
2649
3395
|
the scale, and the two line up; an explicit `size-*` still wins. */
|
|
2650
|
-
:where(.set-row) button,
|
|
3396
|
+
:where(.set-row) button,
|
|
3397
|
+
:where(.set-row) .slider-box { font-size: var(--text-xs); }
|
|
2651
3398
|
|
|
2652
3399
|
/* ---- ./checkbox.css ---- */
|
|
2653
3400
|
/* A row you choose. There is no checkbox in it.
|
|
@@ -2825,30 +3572,28 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
2825
3572
|
one. The cell is bold because it is a heading; what hangs under it is not,
|
|
2826
3573
|
and inherited the weight -- so a pinned version read as loud as the thing it
|
|
2827
3574
|
versions. */
|
|
2828
|
-
.table th .set-hint { font-weight: 400; }
|
|
3575
|
+
.data-table th .set-hint { font-weight: 400; }
|
|
2829
3576
|
|
|
2830
|
-
.table
|
|
2831
|
-
|
|
2832
|
-
.table {
|
|
3577
|
+
.data-table {
|
|
2833
3578
|
width: 100%;
|
|
2834
3579
|
border-collapse: collapse;
|
|
2835
3580
|
font-size: var(--text-sm);
|
|
2836
3581
|
}
|
|
2837
3582
|
|
|
2838
|
-
.table th,
|
|
2839
|
-
.table td {
|
|
3583
|
+
.data-table th,
|
|
3584
|
+
.data-table td {
|
|
2840
3585
|
text-align: left;
|
|
2841
3586
|
padding: var(--space-2) var(--space-3);
|
|
2842
3587
|
border-bottom: var(--border-width) solid var(--border);
|
|
2843
3588
|
}
|
|
2844
3589
|
|
|
2845
|
-
.table th:first-child,
|
|
2846
|
-
.table td:first-child { padding-left: 0; }
|
|
3590
|
+
.data-table th:first-child,
|
|
3591
|
+
.data-table td:first-child { padding-left: 0; }
|
|
2847
3592
|
|
|
2848
|
-
.table th:last-child,
|
|
2849
|
-
.table td:last-child { padding-right: 0; }
|
|
3593
|
+
.data-table th:last-child,
|
|
3594
|
+
.data-table td:last-child { padding-right: 0; }
|
|
2850
3595
|
|
|
2851
|
-
.table thead th {
|
|
3596
|
+
.data-table thead th {
|
|
2852
3597
|
font-size: var(--text-xs);
|
|
2853
3598
|
font-weight: var(--weight-strong);
|
|
2854
3599
|
text-transform: uppercase;
|
|
@@ -2859,40 +3604,31 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
2859
3604
|
|
|
2860
3605
|
/* The row's own name: a `<th scope="row">`, so it carries weight rather than
|
|
2861
3606
|
reading as one more cell. */
|
|
2862
|
-
.table tbody th { font-weight: var(--weight-strong); }
|
|
3607
|
+
.data-table tbody th { font-weight: var(--weight-strong); }
|
|
2863
3608
|
|
|
2864
|
-
.table tbody tr:last-child th,
|
|
2865
|
-
.table tbody tr:last-child td { border-bottom: none; }
|
|
3609
|
+
.data-table tbody tr:last-child th,
|
|
3610
|
+
.data-table tbody tr:last-child td { border-bottom: none; }
|
|
2866
3611
|
|
|
2867
3612
|
/* Numbers compare by column, so they align right and hold their tracks --
|
|
2868
3613
|
proportional digits shift the alignment by a pixel per glyph, which is
|
|
2869
3614
|
exactly the comparison the column was for. */
|
|
2870
|
-
.table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3615
|
+
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
2871
3616
|
|
|
2872
|
-
.table thead th[style*='right'] { text-align: right; }
|
|
3617
|
+
.data-table thead th[style*='right'] { text-align: right; }
|
|
2873
3618
|
|
|
2874
3619
|
/* ---- ./sizegrid.css ---- */
|
|
2875
|
-
/*
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
3620
|
+
/* What is left of the size grid once it draws itself.
|
|
3621
|
+
*
|
|
3622
|
+
* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3623
|
+
* when nothing is hovered so the two can never contradict each other.
|
|
3624
|
+
* `chosen` is a border colour and says so at the call site; `on` is a fill
|
|
3625
|
+
* mixed from the accent, and `color-mix` in an arbitrary value is less
|
|
3626
|
+
* readable than the rule it replaces. */
|
|
3627
|
+
.size-cell.on {
|
|
3628
|
+
border-color: var(--accent);
|
|
3629
|
+
background: color-mix(in srgb, var(--accent) 45%, transparent);
|
|
2884
3630
|
}
|
|
2885
3631
|
|
|
2886
|
-
/* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
2887
|
-
when nothing is hovered so the two can never contradict each other. */
|
|
2888
|
-
.size-cell.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 45%, transparent); }
|
|
2889
|
-
|
|
2890
|
-
.size-cell.chosen { border-color: var(--accent); }
|
|
2891
|
-
|
|
2892
|
-
.size-cell:disabled { cursor: default; opacity: 0.5; }
|
|
2893
|
-
|
|
2894
|
-
.size-ceiling { opacity: 0.55; }
|
|
2895
|
-
|
|
2896
3632
|
/* ---- ./tooltip.css ---- */
|
|
2897
3633
|
/* A callout: something worth knowing, with nothing to answer. Distinct from a
|
|
2898
3634
|
`?`, which is an offer to read more, and from a banner, which is a problem.
|
|
@@ -2901,36 +3637,15 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
2901
3637
|
/* An info-toned `.callout`, spelled the old way. Identical to it now rather than
|
|
2902
3638
|
nearly identical to it, which is the whole point of the consolidation: the
|
|
2903
3639
|
|
|
2904
|
-
/*
|
|
3640
|
+
/* What is left once `Tooltip` draws its own mark: the hover and focus that
|
|
3641
|
+
reach the mark from its parent, and the tip -- whose closed and open
|
|
3642
|
+
states are three rules the cascade resolves in order, with
|
|
3643
|
+
`data-entering` and `data-exiting` around the transition. None of that is
|
|
3644
|
+
a property on one element.
|
|
3645
|
+
|
|
3646
|
+
The `?` beside a setting, and the box it shows on hover. Built like the
|
|
2905
3647
|
status dot's tooltip and for the same reasons: `title` waits a second and a
|
|
2906
3648
|
half, renders newlines however it likes, and cannot be styled. */
|
|
2907
|
-
.explain {
|
|
2908
|
-
position: relative;
|
|
2909
|
-
flex: none;
|
|
2910
|
-
display: inline-flex;
|
|
2911
|
-
align-items: center;
|
|
2912
|
-
/* The heading it follows is tracked out, which leaves the last letter's
|
|
2913
|
-
spacing sitting between them and reads as none at all. */
|
|
2914
|
-
margin-left: var(--space-2);
|
|
2915
|
-
cursor: help;
|
|
2916
|
-
/* Headings here are uppercase and tracked out, and one of these sits inside
|
|
2917
|
-
a heading. */
|
|
2918
|
-
text-transform: none;
|
|
2919
|
-
letter-spacing: normal;
|
|
2920
|
-
font-weight: 400;
|
|
2921
|
-
}
|
|
2922
|
-
|
|
2923
|
-
.explain-mark {
|
|
2924
|
-
width: 18px;
|
|
2925
|
-
height: 18px;
|
|
2926
|
-
border-radius: 50%;
|
|
2927
|
-
border: 1px solid var(--border);
|
|
2928
|
-
color: var(--muted);
|
|
2929
|
-
font-size: var(--text-xs);
|
|
2930
|
-
line-height: 16px;
|
|
2931
|
-
text-align: center;
|
|
2932
|
-
}
|
|
2933
|
-
|
|
2934
3649
|
.explain:hover .explain-mark,
|
|
2935
3650
|
.explain:focus-visible .explain-mark { color: var(--text); border-color: var(--accent); }
|
|
2936
3651
|
|
|
@@ -3031,6 +3746,18 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3031
3746
|
a shirt that lets the arm behind it show through reads as a hole. */
|
|
3032
3747
|
.illo .paper { fill: var(--illo-paper); }
|
|
3033
3748
|
|
|
3749
|
+
/* The figure in a whole-surface `Empty`, drawn in the muted grey of the
|
|
3750
|
+
sentence under it.
|
|
3751
|
+
*
|
|
3752
|
+
* A utility cannot do this, and the reason is worth keeping: `.illo` sets
|
|
3753
|
+
* `color: inherit` and is unlayered, while every Tailwind utility lives in
|
|
3754
|
+
* `@layer utilities` -- and an unlayered declaration beats a layered one
|
|
3755
|
+
* whatever the specificity. So `text-muted` on the figure lost, silently,
|
|
3756
|
+
* and the shirt came out full text black beside a muted sentence. The
|
|
3757
|
+
* original rule already carried a note about needing two classes to beat
|
|
3758
|
+
* `.illo`; layers make that impossible rather than merely fiddly. */
|
|
3759
|
+
.nothing-figure { color: var(--muted); }
|
|
3760
|
+
|
|
3034
3761
|
/* ---- ./field.css ---- */
|
|
3035
3762
|
/* fields --------------------------------------------------------------- */
|
|
3036
3763
|
|
|
@@ -3118,6 +3845,95 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3118
3845
|
|
|
3119
3846
|
.secret-lg > .secret-eye { padding: var(--space-2); }
|
|
3120
3847
|
|
|
3848
|
+
/* An input with something inside its edges: a glyph on the left, a hint or a
|
|
3849
|
+
clear button on the right. Same arrangement as `.secret` above, and for the
|
|
3850
|
+
same reason -- one grid cell with everything stacked in it, and the room
|
|
3851
|
+
reserved in the input's own padding, so nothing is positioned against a
|
|
3852
|
+
height that changes with `size`. */
|
|
3853
|
+
.adorned { display: grid; align-items: center; }
|
|
3854
|
+
|
|
3855
|
+
.adorned > input,
|
|
3856
|
+
.adorned > .adorned-mark,
|
|
3857
|
+
.adorned > .adorned-end { grid-area: 1 / 1; }
|
|
3858
|
+
|
|
3859
|
+
.adorned.ctl-block { width: 100%; }
|
|
3860
|
+
|
|
3861
|
+
.adorned > .adorned-mark {
|
|
3862
|
+
justify-self: start;
|
|
3863
|
+
margin-left: var(--space-2);
|
|
3864
|
+
color: var(--muted);
|
|
3865
|
+
/* The glyph is decoration over the box; clicks belong to the input under
|
|
3866
|
+
it, which is otherwise unreachable in its own left edge. */
|
|
3867
|
+
pointer-events: none;
|
|
3868
|
+
/* Over the input, not under it. Both share one grid cell, the input has an
|
|
3869
|
+
opaque `--control` background, and it comes later in the DOM -- so
|
|
3870
|
+
without this the glyph is painted and then covered, which looks exactly
|
|
3871
|
+
like an icon that failed to render. `.secret` never hit this because its
|
|
3872
|
+
button is written after the input. */
|
|
3873
|
+
z-index: 1;
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
/* Room for the glyph, on the scale, so a density change moves the text with
|
|
3877
|
+
the mark rather than leaving one behind. `--space-8` is what `.secret`
|
|
3878
|
+
reserves on the right for the same reason; the scale has no 7, and an
|
|
3879
|
+
undefined custom property does not fall back -- the declaration computes
|
|
3880
|
+
to 0 and the text sits under the glyph. */
|
|
3881
|
+
.adorned-icon > input { padding-left: var(--space-8); }
|
|
3882
|
+
|
|
3883
|
+
/* No `--space-12` on the scale; two steps that are, added. Same arithmetic
|
|
3884
|
+
as `.secret-lg`. */
|
|
3885
|
+
.adorned-icon.adorned-lg > input { padding-left: calc(var(--space-10) + var(--space-1)); }
|
|
3886
|
+
|
|
3887
|
+
.adorned > .adorned-end {
|
|
3888
|
+
justify-self: end;
|
|
3889
|
+
display: flex;
|
|
3890
|
+
align-items: center;
|
|
3891
|
+
gap: var(--space-1);
|
|
3892
|
+
margin-right: var(--space-1);
|
|
3893
|
+
}
|
|
3894
|
+
|
|
3895
|
+
/* `:has`, not a sibling combinator: the input comes *before* the end cap in
|
|
3896
|
+
the DOM, so `~` reads the wrong way and matches nothing. */
|
|
3897
|
+
.adorned:has(> .adorned-end) > input { padding-right: var(--space-8); }
|
|
3898
|
+
.adorned-lg:has(> .adorned-end) > input {
|
|
3899
|
+
padding-right: calc(var(--space-10) + var(--space-1));
|
|
3900
|
+
}
|
|
3901
|
+
|
|
3902
|
+
/* Sized from its glyph, not `.icon-btn`'s 34px tile, which would be taller
|
|
3903
|
+
than a small input -- the note above `.secret-eye` in full. */
|
|
3904
|
+
.adorned-clear {
|
|
3905
|
+
width: auto; height: auto;
|
|
3906
|
+
padding: var(--space-1);
|
|
3907
|
+
opacity: 1;
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
.adorned-lg .adorned-clear { padding: var(--space-2); }
|
|
3911
|
+
|
|
3912
|
+
/* The eye and the clear button stop borrowing `ghost`.
|
|
3913
|
+
*
|
|
3914
|
+
* Both were `className="icon-btn ghost …"` -- reaching into `Button`'s class
|
|
3915
|
+
* vocabulary from another component, which worked only because `.ghost` was
|
|
3916
|
+
* written as `button.ghost` and they happen to be `<button>`s. It is `.btn.ghost`
|
|
3917
|
+
* now, so the borrowing stopped matching and `.icon-btn`'s panel background
|
|
3918
|
+
* came through: the baselines showed a filled tile where there had been a bare
|
|
3919
|
+
* glyph.
|
|
3920
|
+
*
|
|
3921
|
+
* Stated here instead. What they actually wanted from `ghost` is two lines,
|
|
3922
|
+
* and saying them is cheaper than either component knowing what a button's
|
|
3923
|
+
* classes are called. */
|
|
3924
|
+
.secret-eye,
|
|
3925
|
+
.adorned-clear {
|
|
3926
|
+
background: transparent;
|
|
3927
|
+
border-color: transparent;
|
|
3928
|
+
color: var(--muted);
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3931
|
+
.secret-eye:hover:not(:disabled),
|
|
3932
|
+
.adorned-clear:hover:not(:disabled) {
|
|
3933
|
+
background: var(--panel-2);
|
|
3934
|
+
color: var(--text);
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3121
3937
|
/* ---- ./tour.css ---- */
|
|
3122
3938
|
/* tour ----------------------------------------------------------------- */
|
|
3123
3939
|
|
|
@@ -3185,72 +4001,46 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3185
4001
|
anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
|
|
3186
4002
|
rule of equal specificity that came earlier would lose to whatever the
|
|
3187
4003
|
sheets they cover happen to set. */
|
|
3188
|
-
/* ---- ./kbd.css ---- */
|
|
3189
|
-
/* One rule where there were two identical ones, in `menu.css` and
|
|
3190
|
-
`command.css`. Both keep their class as well, so `Menu` and `Command` are
|
|
3191
|
-
`.kbd .menu-key` and `.kbd .cmd-key` now: the declarations are the same, so
|
|
3192
|
-
nothing moves, and the context classes stay available for a rule that ever
|
|
3193
|
-
needs to tell the two apart. */
|
|
3194
|
-
.kbd {
|
|
3195
|
-
flex: none;
|
|
3196
|
-
font-family: var(--font-mono);
|
|
3197
|
-
font-size: var(--text-2xs);
|
|
3198
|
-
color: var(--muted);
|
|
3199
|
-
letter-spacing: var(--tracking);
|
|
3200
|
-
}
|
|
3201
|
-
|
|
3202
4004
|
/* ---- ./stat.css ---- */
|
|
3203
|
-
/*
|
|
3204
|
-
|
|
3205
|
-
.
|
|
3206
|
-
display: grid;
|
|
3207
|
-
gap: var(--space-1);
|
|
3208
|
-
padding: var(--space-4);
|
|
3209
|
-
border: var(--border-width) solid var(--border);
|
|
3210
|
-
border-radius: var(--radius-md);
|
|
3211
|
-
background: var(--panel);
|
|
3212
|
-
}
|
|
4005
|
+
/* What the utilities on `Stat` cannot say: a tone on the tile colouring the
|
|
4006
|
+
figure inside it. An attribute on the parent selecting a child is a
|
|
4007
|
+
relationship; a utility is a property on one element.
|
|
3213
4008
|
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
.stat-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
background: none;
|
|
3221
|
-
gap: 0;
|
|
3222
|
-
line-height: 1.25;
|
|
3223
|
-
}
|
|
3224
|
-
|
|
3225
|
-
.stat > p { margin: 0; }
|
|
3226
|
-
|
|
3227
|
-
.stat-label {
|
|
3228
|
-
color: var(--muted);
|
|
3229
|
-
font-size: var(--text-xs);
|
|
3230
|
-
}
|
|
4009
|
+
Only the figure takes the colour. Colouring the label too makes the tile a
|
|
4010
|
+
status box, where a tone here is a remark about the number. */
|
|
4011
|
+
.stat[data-tone='info'] .stat-value { color: var(--info); }
|
|
4012
|
+
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
4013
|
+
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
4014
|
+
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
3231
4015
|
|
|
3232
|
-
/*
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
4016
|
+
/* ---- ./shell.css ---- */
|
|
4017
|
+
/* The measure, and only the measure.
|
|
4018
|
+
*
|
|
4019
|
+
* `Shell` draws itself with utilities -- it is layout and nothing else. What
|
|
4020
|
+
* stays here is the one value the header band, the nav band and the main band
|
|
4021
|
+
* all have to agree on: a custom property, so an app changes it in one place
|
|
4022
|
+
* rather than overriding three rules and missing the fourth. That is how
|
|
4023
|
+
* manage ended up carrying `head-inner-wide` and `main-wide` as separate
|
|
4024
|
+
* classes it had to remember together. */
|
|
4025
|
+
.shell {
|
|
4026
|
+
--shell-measure: 64rem;
|
|
4027
|
+
--shell-measure-wide: 90rem;
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
/* The label beside the theme control, when it is drawn. */
|
|
4031
|
+
.theme-switch {
|
|
4032
|
+
display: flex;
|
|
4033
|
+
align-items: center;
|
|
4034
|
+
gap: var(--space-2);
|
|
4035
|
+
min-width: 0;
|
|
3238
4036
|
}
|
|
3239
4037
|
|
|
3240
|
-
.
|
|
3241
|
-
|
|
3242
|
-
.stat-note {
|
|
4038
|
+
.theme-switch-label {
|
|
3243
4039
|
color: var(--muted);
|
|
3244
|
-
font-size: var(--text-
|
|
4040
|
+
font-size: var(--text-sm);
|
|
4041
|
+
white-space: nowrap;
|
|
3245
4042
|
}
|
|
3246
4043
|
|
|
3247
|
-
/* Only the figure takes the colour. Colouring the label too makes the tile a
|
|
3248
|
-
status box, and a tone here is a remark about the number. */
|
|
3249
|
-
.stat[data-tone='info'] .stat-value { color: var(--info); }
|
|
3250
|
-
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
3251
|
-
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
3252
|
-
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
3253
|
-
|
|
3254
4044
|
/* ---- ./scrollarea.css ---- */
|
|
3255
4045
|
/* A box that scrolls, with its edges drawn.
|
|
3256
4046
|
|
|
@@ -3502,27 +4292,13 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3502
4292
|
}
|
|
3503
4293
|
|
|
3504
4294
|
/* ---- ./menu.css ---- */
|
|
3505
|
-
/*
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
box-shadow: var(--shadow-2);
|
|
3511
|
-
min-width: 12rem;
|
|
3512
|
-
max-width: min(20rem, calc(100vw - var(--space-6)));
|
|
3513
|
-
max-height: 24rem;
|
|
3514
|
-
overflow: auto;
|
|
3515
|
-
overscroll-behavior: contain;
|
|
3516
|
-
z-index: 60;
|
|
3517
|
-
}
|
|
3518
|
-
|
|
3519
|
-
.menu-list {
|
|
3520
|
-
padding: var(--space-1);
|
|
3521
|
-
outline: none;
|
|
3522
|
-
display: grid;
|
|
3523
|
-
gap: var(--border-width);
|
|
3524
|
-
}
|
|
4295
|
+
/* What is left once `Menu` draws its sheet and its list: the rows, whose
|
|
4296
|
+
`data-focused`, `data-pressed` and danger states React Aria stamps on
|
|
4297
|
+
them, and the rules that reach from a row into what it holds. The
|
|
4298
|
+
`box-shadow` stays on the sheet too -- `--shadow-2` is a token, and a
|
|
4299
|
+
utility would have to inline it. */
|
|
3525
4300
|
|
|
4301
|
+
/* A list of verbs, on the same sheet as every other anchored surface. */
|
|
3526
4302
|
.menu-item {
|
|
3527
4303
|
display: flex;
|
|
3528
4304
|
align-items: center;
|
|
@@ -3561,14 +4337,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3561
4337
|
/* The binding, set in the mono face at the size of the small print. Right of
|
|
3562
4338
|
the row and never the reason the row is wide: `flex: none` with the label
|
|
3563
4339
|
taking the slack. */
|
|
3564
|
-
.menu-key {
|
|
3565
|
-
flex: none;
|
|
3566
|
-
font-family: var(--font-mono);
|
|
3567
|
-
font-size: var(--text-2xs);
|
|
3568
|
-
color: var(--muted);
|
|
3569
|
-
letter-spacing: var(--tracking);
|
|
3570
|
-
}
|
|
3571
|
-
|
|
3572
4340
|
.menu-more { flex: none; color: var(--muted); }
|
|
3573
4341
|
|
|
3574
4342
|
.menu-rule {
|
|
@@ -3604,6 +4372,8 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3604
4372
|
.menu-sheet[data-exiting] { animation: none; }
|
|
3605
4373
|
}
|
|
3606
4374
|
|
|
4375
|
+
.menu-sheet { box-shadow: var(--shadow-2); }
|
|
4376
|
+
|
|
3607
4377
|
/* ---- ./command.css ---- */
|
|
3608
4378
|
/* The command palette: a field over the app and a list under it. */
|
|
3609
4379
|
.cmd-scrim {
|
|
@@ -3721,14 +4491,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3721
4491
|
white-space: nowrap;
|
|
3722
4492
|
}
|
|
3723
4493
|
|
|
3724
|
-
.cmd-key {
|
|
3725
|
-
flex: none;
|
|
3726
|
-
font-family: var(--font-mono);
|
|
3727
|
-
font-size: var(--text-2xs);
|
|
3728
|
-
color: var(--muted);
|
|
3729
|
-
letter-spacing: var(--tracking);
|
|
3730
|
-
}
|
|
3731
|
-
|
|
3732
4494
|
.cmd-empty {
|
|
3733
4495
|
margin: 0;
|
|
3734
4496
|
padding: var(--space-6) var(--space-4);
|
|
@@ -3756,23 +4518,14 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3756
4518
|
}
|
|
3757
4519
|
|
|
3758
4520
|
/* ---- ./pagination.css ---- */
|
|
3759
|
-
/*
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
justify-content: space-between;
|
|
3764
|
-
gap: var(--space-4);
|
|
3765
|
-
flex-wrap: wrap;
|
|
3766
|
-
padding: var(--space-2) 0;
|
|
3767
|
-
font-size: var(--text-xs);
|
|
3768
|
-
color: var(--muted);
|
|
3769
|
-
}
|
|
4521
|
+
/* What is left once `Pagination` draws its own frame: the step and page
|
|
4522
|
+
buttons, whose hover, focus-visible and current states are pseudo-classes
|
|
4523
|
+
on two selectors at once, and `.pager-count strong`, which reaches into
|
|
4524
|
+
text the caller passed. */
|
|
3770
4525
|
|
|
3771
|
-
|
|
4526
|
+
/* Moving through a list that does not fit, and saying how far in you are. */
|
|
3772
4527
|
.pager-count strong { color: var(--text); font-weight: var(--weight-strong); }
|
|
3773
4528
|
|
|
3774
|
-
.pager-controls { display: flex; align-items: center; gap: var(--space-1); }
|
|
3775
|
-
|
|
3776
4529
|
.pager-step,
|
|
3777
4530
|
.pager-page {
|
|
3778
4531
|
display: inline-flex;
|
|
@@ -3964,6 +4717,8 @@ body.splitting * { cursor: inherit !important; }
|
|
|
3964
4717
|
}
|
|
3965
4718
|
|
|
3966
4719
|
.ident-remove {
|
|
4720
|
+
/* Stated rather than inherited. These came from the `button, input, textarea, select` reset, which applied control styling to everything that happened to be a `<button>` -- so this rule spent its opening lines undoing it, and would break silently if that rule ever moved. It did move, to `.btn`. */
|
|
4721
|
+
font: inherit;
|
|
3967
4722
|
flex: none;
|
|
3968
4723
|
display: inline-flex;
|
|
3969
4724
|
align-items: center;
|