@wtfalch/design 0.9.0 → 0.10.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 +6 -3
- package/dist/components/Callout.js +1 -1
- package/dist/components/Checkbox.js +1 -1
- package/dist/components/Command.js +3 -3
- package/dist/components/DangerZone.js +1 -1
- package/dist/components/Empty.js +10 -3
- package/dist/components/Field.js +1 -1
- package/dist/components/Identity.js +1 -1
- package/dist/components/Menu.js +1 -1
- package/dist/components/Pill.d.ts +1 -2
- package/dist/components/Pill.js +1 -2
- package/dist/components/Popover.js +1 -1
- package/dist/components/Rows.js +2 -2
- package/dist/components/Select.js +1 -1
- package/dist/components/SizeGrid.js +6 -2
- package/dist/components/Slider.js +1 -1
- package/dist/components/SplitPane.js +2 -2
- package/dist/components/Table.js +1 -1
- package/dist/components/Tabs.js +2 -2
- package/dist/components/Toggle.js +1 -1
- package/dist/components/Tour.js +6 -2
- package/dist/styles/index.css +210 -218
- package/dist/tf.css +210 -218
- package/dist/valet.css +210 -218
- package/package.json +1 -1
package/dist/styles/index.css
CHANGED
|
@@ -17,12 +17,9 @@
|
|
|
17
17
|
--font-sans: var(--font-sans);
|
|
18
18
|
--font-mono: var(--font-mono);
|
|
19
19
|
--text-xs: var(--text-xs);
|
|
20
|
-
--text-xs--line-height: inherit;
|
|
21
20
|
--text-sm: var(--text-sm);
|
|
22
|
-
--text-sm--line-height: inherit;
|
|
23
21
|
--text-base: var(--text-base);
|
|
24
22
|
--text-lg: var(--text-lg);
|
|
25
|
-
--text-lg--line-height: inherit;
|
|
26
23
|
--text-xl: var(--text-xl);
|
|
27
24
|
--font-weight-normal: var(--weight);
|
|
28
25
|
--tracking-normal: var(--tracking);
|
|
@@ -37,19 +34,20 @@
|
|
|
37
34
|
--spacing-5: var(--space-5);
|
|
38
35
|
--spacing-6: var(--space-6);
|
|
39
36
|
--spacing-10: var(--space-10);
|
|
40
|
-
--text-2xs--line-height: inherit;
|
|
41
37
|
--text-2xs: var(--text-2xs);
|
|
42
38
|
--text-md: var(--text-md);
|
|
43
39
|
--font-weight-strong: var(--weight-strong);
|
|
44
40
|
--radius-pill: var(--radius-pill);
|
|
45
41
|
--color-text: var(--text);
|
|
46
42
|
--color-muted: var(--muted);
|
|
47
|
-
--color-accent: var(--accent);
|
|
48
43
|
--color-border: var(--border);
|
|
49
44
|
--color-border-strong: var(--border-strong);
|
|
50
45
|
}
|
|
51
46
|
}
|
|
52
47
|
@layer utilities {
|
|
48
|
+
.pointer-events-none {
|
|
49
|
+
pointer-events: none;
|
|
50
|
+
}
|
|
53
51
|
.collapse {
|
|
54
52
|
visibility: collapse;
|
|
55
53
|
}
|
|
@@ -82,6 +80,9 @@
|
|
|
82
80
|
.sticky {
|
|
83
81
|
position: sticky;
|
|
84
82
|
}
|
|
83
|
+
.inset-0 {
|
|
84
|
+
inset: 0px;
|
|
85
|
+
}
|
|
85
86
|
.z-\[60\] {
|
|
86
87
|
z-index: 60;
|
|
87
88
|
}
|
|
@@ -115,12 +116,21 @@
|
|
|
115
116
|
.mt-1 {
|
|
116
117
|
margin-top: var(--spacing-1);
|
|
117
118
|
}
|
|
119
|
+
.mt-2 {
|
|
120
|
+
margin-top: var(--spacing-2);
|
|
121
|
+
}
|
|
122
|
+
.mt-px {
|
|
123
|
+
margin-top: 1px;
|
|
124
|
+
}
|
|
118
125
|
.mb-3 {
|
|
119
126
|
margin-bottom: var(--spacing-3);
|
|
120
127
|
}
|
|
121
128
|
.ml-2 {
|
|
122
129
|
margin-left: var(--spacing-2);
|
|
123
130
|
}
|
|
131
|
+
.ml-auto {
|
|
132
|
+
margin-left: auto;
|
|
133
|
+
}
|
|
124
134
|
.block {
|
|
125
135
|
display: block;
|
|
126
136
|
}
|
|
@@ -145,6 +155,9 @@
|
|
|
145
155
|
.table {
|
|
146
156
|
display: table;
|
|
147
157
|
}
|
|
158
|
+
.h-4 {
|
|
159
|
+
height: var(--spacing-4);
|
|
160
|
+
}
|
|
148
161
|
.h-\[14px\] {
|
|
149
162
|
height: 14px;
|
|
150
163
|
}
|
|
@@ -163,6 +176,9 @@
|
|
|
163
176
|
.min-h-screen {
|
|
164
177
|
min-height: 100vh;
|
|
165
178
|
}
|
|
179
|
+
.w-4 {
|
|
180
|
+
width: var(--spacing-4);
|
|
181
|
+
}
|
|
166
182
|
.w-\[18px\] {
|
|
167
183
|
width: 18px;
|
|
168
184
|
}
|
|
@@ -190,6 +206,18 @@
|
|
|
190
206
|
.flex-1 {
|
|
191
207
|
flex: 1;
|
|
192
208
|
}
|
|
209
|
+
.flex-\[0_0_var\(--split\)\] {
|
|
210
|
+
flex: 0 0 var(--split);
|
|
211
|
+
}
|
|
212
|
+
.flex-\[1_1_0\] {
|
|
213
|
+
flex: 1 1 0;
|
|
214
|
+
}
|
|
215
|
+
.flex-\[1_1_260px\] {
|
|
216
|
+
flex: 1 1 260px;
|
|
217
|
+
}
|
|
218
|
+
.flex-\[1_1_auto\] {
|
|
219
|
+
flex: 1 1 auto;
|
|
220
|
+
}
|
|
193
221
|
.flex-none {
|
|
194
222
|
flex: none;
|
|
195
223
|
}
|
|
@@ -220,6 +248,9 @@
|
|
|
220
248
|
.flex-wrap {
|
|
221
249
|
flex-wrap: wrap;
|
|
222
250
|
}
|
|
251
|
+
.place-items-center {
|
|
252
|
+
place-items: center;
|
|
253
|
+
}
|
|
223
254
|
.items-baseline {
|
|
224
255
|
align-items: baseline;
|
|
225
256
|
}
|
|
@@ -253,6 +284,9 @@
|
|
|
253
284
|
.gap-\[var\(--border-width\)\] {
|
|
254
285
|
gap: var(--border-width);
|
|
255
286
|
}
|
|
287
|
+
.gap-px {
|
|
288
|
+
gap: 1px;
|
|
289
|
+
}
|
|
256
290
|
.self-center {
|
|
257
291
|
align-self: center;
|
|
258
292
|
}
|
|
@@ -300,9 +334,6 @@
|
|
|
300
334
|
--tw-border-style: dashed;
|
|
301
335
|
border-style: dashed;
|
|
302
336
|
}
|
|
303
|
-
.border-accent {
|
|
304
|
-
border-color: var(--color-accent);
|
|
305
|
-
}
|
|
306
337
|
.border-border {
|
|
307
338
|
border-color: var(--color-border);
|
|
308
339
|
}
|
|
@@ -318,9 +349,15 @@
|
|
|
318
349
|
.p-2 {
|
|
319
350
|
padding: var(--spacing-2);
|
|
320
351
|
}
|
|
352
|
+
.p-3 {
|
|
353
|
+
padding: var(--spacing-3);
|
|
354
|
+
}
|
|
321
355
|
.p-4 {
|
|
322
356
|
padding: var(--spacing-4);
|
|
323
357
|
}
|
|
358
|
+
.px-2 {
|
|
359
|
+
padding-inline: var(--spacing-2);
|
|
360
|
+
}
|
|
324
361
|
.px-4 {
|
|
325
362
|
padding-inline: var(--spacing-4);
|
|
326
363
|
}
|
|
@@ -339,6 +376,12 @@
|
|
|
339
376
|
.py-10 {
|
|
340
377
|
padding-block: var(--spacing-10);
|
|
341
378
|
}
|
|
379
|
+
.pt-2 {
|
|
380
|
+
padding-top: var(--spacing-2);
|
|
381
|
+
}
|
|
382
|
+
.pb-1 {
|
|
383
|
+
padding-bottom: var(--spacing-1);
|
|
384
|
+
}
|
|
342
385
|
.pb-2 {
|
|
343
386
|
padding-bottom: var(--spacing-2);
|
|
344
387
|
}
|
|
@@ -353,19 +396,18 @@
|
|
|
353
396
|
}
|
|
354
397
|
.text-2xs {
|
|
355
398
|
font-size: var(--text-2xs);
|
|
356
|
-
|
|
399
|
+
}
|
|
400
|
+
.text-base {
|
|
401
|
+
font-size: var(--text-base);
|
|
357
402
|
}
|
|
358
403
|
.text-lg {
|
|
359
404
|
font-size: var(--text-lg);
|
|
360
|
-
line-height: var(--tw-leading, var(--text-lg--line-height));
|
|
361
405
|
}
|
|
362
406
|
.text-sm {
|
|
363
407
|
font-size: var(--text-sm);
|
|
364
|
-
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
365
408
|
}
|
|
366
409
|
.text-xs {
|
|
367
410
|
font-size: var(--text-xs);
|
|
368
|
-
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
369
411
|
}
|
|
370
412
|
.leading-\[0\] {
|
|
371
413
|
--tw-leading: 0;
|
|
@@ -379,6 +421,10 @@
|
|
|
379
421
|
--tw-leading: 1.25;
|
|
380
422
|
line-height: 1.25;
|
|
381
423
|
}
|
|
424
|
+
.leading-\[1\.35\] {
|
|
425
|
+
--tw-leading: 1.35;
|
|
426
|
+
line-height: 1.35;
|
|
427
|
+
}
|
|
382
428
|
.leading-\[16px\] {
|
|
383
429
|
--tw-leading: 16px;
|
|
384
430
|
line-height: 16px;
|
|
@@ -420,12 +466,12 @@
|
|
|
420
466
|
--tw-numeric-spacing: tabular-nums;
|
|
421
467
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
422
468
|
}
|
|
423
|
-
.opacity-0 {
|
|
424
|
-
opacity: 0%;
|
|
425
|
-
}
|
|
426
469
|
.opacity-60 {
|
|
427
470
|
opacity: 60%;
|
|
428
471
|
}
|
|
472
|
+
.opacity-90 {
|
|
473
|
+
opacity: 90%;
|
|
474
|
+
}
|
|
429
475
|
.opacity-\[0\.55\] {
|
|
430
476
|
opacity: 0.55;
|
|
431
477
|
}
|
|
@@ -465,9 +511,6 @@
|
|
|
465
511
|
.surface-panel {
|
|
466
512
|
background: var(--panel);
|
|
467
513
|
}
|
|
468
|
-
.surface-panel-2 {
|
|
469
|
-
background: var(--panel-2);
|
|
470
|
-
}
|
|
471
514
|
.disabled\:cursor-default:disabled {
|
|
472
515
|
cursor: default;
|
|
473
516
|
}
|
|
@@ -707,7 +750,19 @@
|
|
|
707
750
|
}
|
|
708
751
|
}
|
|
709
752
|
|
|
710
|
-
/* ---- ./
|
|
753
|
+
/* ---- ./_system-light.css ---- */
|
|
754
|
+
/* The `system` theme's light half.
|
|
755
|
+
*
|
|
756
|
+
* Its own file, and outside the components layer, because it is a *theme*
|
|
757
|
+
* rather than a component rule. `tokens.css` states the dark base on `:root`
|
|
758
|
+
* and is unlayered; the moment this sat inside `@layer components` it lost to
|
|
759
|
+
* that, and every `system` specimen rendered dark on a light-mode machine.
|
|
760
|
+
* Unlayered beats layered whatever the selector says, which is exactly the
|
|
761
|
+
* trap this repository keeps finding in different costumes.
|
|
762
|
+
*
|
|
763
|
+
* The underscore marks it the same way `_tailwind.built.css` is marked:
|
|
764
|
+
* `copy-css.mjs` passes both through without wrapping them.
|
|
765
|
+
*/
|
|
711
766
|
/* Light, only under the `system` theme. This used to override `:root`
|
|
712
767
|
unconditionally, so choosing a dark theme on a light-mode laptop got
|
|
713
768
|
silently repainted. Every other theme states its own palette. */
|
|
@@ -736,6 +791,8 @@
|
|
|
736
791
|
}
|
|
737
792
|
}
|
|
738
793
|
|
|
794
|
+
/* ---- ./base.css ---- */
|
|
795
|
+
@layer components {
|
|
739
796
|
/* Derived from the two surfaces every theme already defines, so a theme gets a
|
|
740
797
|
control colour without knowing this exists. */
|
|
741
798
|
/* Pseudo-elements too. `*` does not match them, and `box-sizing` is not
|
|
@@ -1453,23 +1510,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1453
1510
|
template are allowed to diverge, and this is only saying that they have. */
|
|
1454
1511
|
.set-hint.drifted { color: var(--warn); }
|
|
1455
1512
|
|
|
1456
|
-
/* What an applet drew, read back. A tree rather than prose, so it is left as
|
|
1457
|
-
preformatted text and given a ceiling -- a busy applet is a hundred lines and
|
|
1458
|
-
this sits inside a settings pane. */
|
|
1459
|
-
.drawn {
|
|
1460
|
-
margin: var(--space-2) 0 0;
|
|
1461
|
-
padding: var(--space-2) var(--space-2);
|
|
1462
|
-
max-height: 220px;
|
|
1463
|
-
overflow: auto;
|
|
1464
|
-
font-size: var(--text-xs);
|
|
1465
|
-
line-height: 1.45;
|
|
1466
|
-
white-space: pre-wrap;
|
|
1467
|
-
overflow-wrap: anywhere;
|
|
1468
|
-
border: 1px solid var(--border);
|
|
1469
|
-
border-radius: var(--radius);
|
|
1470
|
-
background: var(--panel-2);
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
1513
|
/* One applet, alone on the page, at `/applet/<id>`. Fills the window: there is
|
|
1474
1514
|
no grid here to decide a height, and a screenshot of an applet letterboxed
|
|
1475
1515
|
inside a page is mostly not the applet. */
|
|
@@ -1516,11 +1556,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1516
1556
|
that belongs to a conversation lives here any more, so it can breathe. */
|
|
1517
1557
|
.topbar .ctl-grow { flex: 1; min-width: 0; }
|
|
1518
1558
|
|
|
1519
|
-
/* Back on the left, Next on the right, with the gap between them doing the
|
|
1520
|
-
separating -- so the button that goes forward is in the same place on both
|
|
1521
|
-
pages instead of sliding when Back appears. */
|
|
1522
|
-
.first-run-actions { align-items: center; }
|
|
1523
|
-
|
|
1524
1559
|
@keyframes listening-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }
|
|
1525
1560
|
|
|
1526
1561
|
/* table ---------------------------------------------------------------- */
|
|
@@ -1596,8 +1631,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1596
1631
|
color: var(--muted);
|
|
1597
1632
|
opacity: 1;
|
|
1598
1633
|
}
|
|
1634
|
+
}
|
|
1599
1635
|
|
|
1600
1636
|
/* ---- ./select.css ---- */
|
|
1637
|
+
@layer components {
|
|
1601
1638
|
/* How big a control is, asked for rather than inherited.
|
|
1602
1639
|
Four sizes existed and every one of them came from a descendant selector:
|
|
1603
1640
|
`.set-row button` was 11px in 3px of padding, `.approval-actions button` was
|
|
@@ -1692,16 +1729,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1692
1729
|
/* State is read off React Aria's attributes: `data-open` on the root,
|
|
1693
1730
|
`data-focused` / `data-selected` / `data-disabled` on an item, where
|
|
1694
1731
|
`.open`, `[data-active]`, `.on` and `.off` used to be. */
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1732
|
+
/* The list keeps two things the utilities on `Select` cannot say.
|
|
1733
|
+
*
|
|
1734
|
+
* `scroll-padding-block`: the same room while the list is scrolled as it has
|
|
1735
|
+
* at rest. Padding at the top of a scroll container scrolls away with the
|
|
1736
|
+
* content, so the row `scrollIntoView({block: 'nearest'})` brings up ended
|
|
1737
|
+
* flush against the border and read as clipped rather than as one of a set --
|
|
1738
|
+
* and this list opens scrolled to whatever is chosen, so that was the
|
|
1739
|
+
* ordinary state.
|
|
1740
|
+
*
|
|
1741
|
+
* `box-shadow`: `--shadow-2` is a token, and a utility would have to inline
|
|
1742
|
+
* the value, which is the one thing the vocabulary exists to stop. */
|
|
1743
|
+
.sel-list {
|
|
1700
1744
|
scroll-padding-block: var(--space-1);
|
|
1701
|
-
list-style: none;
|
|
1702
|
-
border: var(--border-width) solid var(--border-strong);
|
|
1703
|
-
border-radius: var(--radius-md);
|
|
1704
|
-
background: var(--panel);
|
|
1705
1745
|
box-shadow: var(--shadow-2);
|
|
1706
1746
|
}
|
|
1707
1747
|
|
|
@@ -1716,6 +1756,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1716
1756
|
|
|
1717
1757
|
/* The tick marks the chosen row. Colour alone would not: a list where the only
|
|
1718
1758
|
difference is a hue is a list you cannot read past. */
|
|
1759
|
+
/* The tick's resting state lives here, beside the state that overrides it.
|
|
1760
|
+
*
|
|
1761
|
+
* It was `opacity-0` on the element and `opacity: 1` here, which worked only
|
|
1762
|
+
* while this sheet was unlayered. A utility is in `@layer utilities` and
|
|
1763
|
+
* beats `@layer components` whatever the selector, so the moment the sheets
|
|
1764
|
+
* moved into a layer the tick stopped appearing on the selected row -- the
|
|
1765
|
+
* resting state won permanently.
|
|
1766
|
+
*
|
|
1767
|
+
* The rule generalises: a utility for a resting state whose active state is a
|
|
1768
|
+
* relationship between elements will always beat that active state. The pair
|
|
1769
|
+
* has to sit in the same layer. */
|
|
1770
|
+
.sel-tick { opacity: 0; }
|
|
1771
|
+
|
|
1719
1772
|
.sel-item[data-selected] .sel-tick { opacity: 1; }
|
|
1720
1773
|
|
|
1721
1774
|
/* The icon on a speaker's row in the open list -- `Select`'s `aside`. Last in
|
|
@@ -1750,8 +1803,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1750
1803
|
.field > input,
|
|
1751
1804
|
.field > textarea,
|
|
1752
1805
|
.field > .sel { width: 100%; }
|
|
1806
|
+
}
|
|
1753
1807
|
|
|
1754
1808
|
/* ---- ./dangerzone.css ---- */
|
|
1809
|
+
@layer components {
|
|
1755
1810
|
/* Destructive, and legible as such standing still. */
|
|
1756
1811
|
.btn.danger {
|
|
1757
1812
|
color: var(--bad);
|
|
@@ -1841,8 +1896,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1841
1896
|
border-radius: 4px;
|
|
1842
1897
|
}
|
|
1843
1898
|
|
|
1844
|
-
.danger-unavailable { margin-top: var(--space-2); opacity: 0.85; }
|
|
1845
|
-
|
|
1846
1899
|
/* Label beside the control, for a settings pane: a column of names on the left
|
|
1847
1900
|
and their controls on the right reads as a list of what is set, where the
|
|
1848
1901
|
same rows stacked read as a form waiting to be filled in. The description
|
|
@@ -1863,8 +1916,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1863
1916
|
controls in the same column at the same indent that do not line up read as
|
|
1864
1917
|
an accident rather than as a pair. */
|
|
1865
1918
|
.field-row > button { min-width: 9ch; }
|
|
1919
|
+
}
|
|
1866
1920
|
|
|
1867
1921
|
/* ---- ./callout.css ---- */
|
|
1922
|
+
@layer components {
|
|
1868
1923
|
/* One shape for everything that tells you something.
|
|
1869
1924
|
`.banner` and `.callout` were the same box drawn twice: a bordered, rounded,
|
|
1870
1925
|
12px panel with a tint. They differed in padding by a pixel in each direction
|
|
@@ -1918,8 +1973,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1918
1973
|
/* A callout that leaves on its own.
|
|
1919
1974
|
Room at the bottom for the bar, and `position: relative` so the bar can sit
|
|
1920
1975
|
on the border rather than inside the text. */
|
|
1921
|
-
.callout-timed { position: relative; padding-bottom: var(--space-5); overflow: hidden; }
|
|
1922
|
-
|
|
1923
1976
|
/* The countdown. Drawn as a shrinking bar rather than a number: nobody wants to
|
|
1924
1977
|
read a clock, they want to know whether they have time. Animated width rather
|
|
1925
1978
|
than a transition, so it starts the moment it is painted. */
|
|
@@ -1980,14 +2033,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1980
2033
|
is the operating system's font drawing a glyph beside an app that has an icon
|
|
1981
2034
|
set for exactly this. The ring went with it: a circle around a warning
|
|
1982
2035
|
triangle is two shapes saying one thing. */
|
|
1983
|
-
.callout-mark {
|
|
1984
|
-
flex: none;
|
|
1985
|
-
display: grid;
|
|
1986
|
-
place-items: center;
|
|
1987
|
-
margin-top: 1px;
|
|
1988
|
-
opacity: 0.9;
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
2036
|
/* Held-back history when a local conversation would cross to a hosted model.
|
|
1992
2037
|
Deliberately loud: the cost of missing it is uploading work that was kept
|
|
1993
2038
|
local on purpose. */
|
|
@@ -2003,8 +2048,23 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2003
2048
|
}
|
|
2004
2049
|
|
|
2005
2050
|
.callout button { flex: none; }
|
|
2051
|
+
/* A state, so it stays a class.
|
|
2052
|
+
*
|
|
2053
|
+
* `Callout` applies this as `running ? ' callout-timed' : ''` inside a
|
|
2054
|
+
* template literal -- which is not a class list a rewrite can read, and the
|
|
2055
|
+
* first pass at converting it deleted the rule while leaving the usage. The
|
|
2056
|
+
* box lost five spacing steps of padding and the countdown bar had nothing
|
|
2057
|
+
* to sit in. A class that appears only inside a conditional is a state; the
|
|
2058
|
+
* sheet is where those belong. */
|
|
2059
|
+
.callout-timed {
|
|
2060
|
+
position: relative;
|
|
2061
|
+
padding-bottom: var(--space-5);
|
|
2062
|
+
overflow: hidden;
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2006
2065
|
|
|
2007
2066
|
/* ---- ./card.css ---- */
|
|
2067
|
+
@layer components {
|
|
2008
2068
|
/* `.card` is public API, not this component's private styling.
|
|
2009
2069
|
*
|
|
2010
2070
|
* Consumers apply it to their own markup -- the gallery's skeleton specimen
|
|
@@ -2059,16 +2119,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2059
2119
|
which reads as a different column of content. */
|
|
2060
2120
|
.card:has(.card-icon) .card-inline { padding-left: calc(var(--card-icon) + var(--space-3)); }
|
|
2061
2121
|
|
|
2062
|
-
/* Its own line, above the sentence it introduces. */
|
|
2063
|
-
.card-inline-label {
|
|
2064
|
-
display: block;
|
|
2065
|
-
font-size: var(--text-xs);
|
|
2066
|
-
text-transform: uppercase;
|
|
2067
|
-
letter-spacing: 0.04em;
|
|
2068
|
-
color: var(--muted);
|
|
2069
|
-
margin-bottom: 2px;
|
|
2070
|
-
}
|
|
2071
|
-
|
|
2072
2122
|
.card-title { display: block; font-size: var(--text-base); }
|
|
2073
2123
|
|
|
2074
2124
|
.card-desc { margin-top: var(--space-1); color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
@@ -2146,8 +2196,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2146
2196
|
}
|
|
2147
2197
|
|
|
2148
2198
|
.card[aria-pressed='true']:hover { border-color: var(--accent); }
|
|
2199
|
+
}
|
|
2149
2200
|
|
|
2150
2201
|
/* ---- ./toggle.css ---- */
|
|
2202
|
+
@layer components {
|
|
2151
2203
|
.card-action .switch-row { padding: 0; gap: var(--space-2); }
|
|
2152
2204
|
|
|
2153
2205
|
.card-action .switch-row .switch-body { flex: none; }
|
|
@@ -2204,12 +2256,8 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2204
2256
|
tooltip ended up orphaned under it. */
|
|
2205
2257
|
.set-row > .switch-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
2206
2258
|
|
|
2207
|
-
.switch-label { color: var(--text); }
|
|
2208
|
-
|
|
2209
2259
|
.switch-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
2210
2260
|
|
|
2211
|
-
.switch-said { flex: none; font-size: var(--text-xs); color: var(--muted); }
|
|
2212
|
-
|
|
2213
2261
|
/* Three sizes, the same names every other control uses. The switch scales with
|
|
2214
2262
|
the row: a 30x18 track beside 12px text is a different control from the same
|
|
2215
2263
|
track beside 16px text. */
|
|
@@ -2378,19 +2426,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2378
2426
|
@media (prefers-reduced-motion: reduce) {
|
|
2379
2427
|
.toggle-sweep::before { animation: none; background: color-mix(in oklab, var(--accent) 45%, transparent); }
|
|
2380
2428
|
}
|
|
2381
|
-
|
|
2382
|
-
/* ---- ./skeleton.css ---- */
|
|
2383
|
-
.muted { color: var(--muted); }
|
|
2384
|
-
|
|
2385
|
-
.pulse-block {
|
|
2386
|
-
display: inline-block;
|
|
2387
|
-
height: 8px;
|
|
2388
|
-
border-radius: var(--radius-sm);
|
|
2389
|
-
background: var(--muted);
|
|
2390
|
-
animation: ds-pulse 1.4s ease-in-out infinite;
|
|
2391
|
-
vertical-align: middle;
|
|
2392
2429
|
}
|
|
2393
2430
|
|
|
2431
|
+
/* ---- ./skeleton.css ---- */
|
|
2432
|
+
@layer components {
|
|
2394
2433
|
/* skeletons ------------------------------------------------------------ */
|
|
2395
2434
|
|
|
2396
2435
|
/* Ink at low alpha, not a named surface.
|
|
@@ -2434,8 +2473,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2434
2473
|
/* Still distinguishable from a real block of colour, and still still. */
|
|
2435
2474
|
.skel-pulse { animation: none; opacity: 0.8; }
|
|
2436
2475
|
}
|
|
2476
|
+
}
|
|
2437
2477
|
|
|
2438
2478
|
/* ---- ./rows.css ---- */
|
|
2479
|
+
@layer components {
|
|
2439
2480
|
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2440
2481
|
|
|
2441
2482
|
/* A name and the pills that qualify it, on one line, where the name is the only
|
|
@@ -2647,8 +2688,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2647
2688
|
|
|
2648
2689
|
.rows-split:first-of-type { margin-top: var(--space-2); }
|
|
2649
2690
|
|
|
2650
|
-
.rows-empty { padding: var(--space-3) 0; }
|
|
2651
|
-
|
|
2652
2691
|
/* The name, the pills and the line underneath. `min-width: 0` is the whole
|
|
2653
2692
|
reason this is a class: a flex item will not shrink below its content, so
|
|
2654
2693
|
without it the name pushes the pills off the end -- and the pills are the
|
|
@@ -2665,8 +2704,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2665
2704
|
|
|
2666
2705
|
/* The aligned column. `margin-left: auto` rather than a grid, because the rows
|
|
2667
2706
|
are flex and a size that varies by two characters does not need a track. */
|
|
2668
|
-
.row-trail { flex: none; margin-left: auto; white-space: nowrap; }
|
|
2669
|
-
|
|
2670
2707
|
.rows-row.rows-top { align-items: flex-start; }
|
|
2671
2708
|
|
|
2672
2709
|
.rows-row.rows-bad .truncate { color: var(--bad); }
|
|
@@ -2696,8 +2733,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2696
2733
|
.row-hit:hover .truncate { color: var(--accent); }
|
|
2697
2734
|
|
|
2698
2735
|
.row-hit:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
2736
|
+
}
|
|
2699
2737
|
|
|
2700
2738
|
/* ---- ./progress.css ---- */
|
|
2739
|
+
@layer components {
|
|
2701
2740
|
/* progress ----------------------------------------------------------- */
|
|
2702
2741
|
|
|
2703
2742
|
/* The bar itself: a track with a child it fills, an animation and a
|
|
@@ -2739,8 +2778,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2739
2778
|
/* Still distinguishable from empty, and from full. */
|
|
2740
2779
|
.bar-indeterminate > i { animation: none; width: 100%; opacity: 0.35; }
|
|
2741
2780
|
}
|
|
2781
|
+
}
|
|
2742
2782
|
|
|
2743
2783
|
/* ---- ./tabs.css ---- */
|
|
2784
|
+
@layer components {
|
|
2744
2785
|
/* ---------------------------------------------------------------- tabs */
|
|
2745
2786
|
.tabs { position: relative; display: flex; gap: var(--space-1); }
|
|
2746
2787
|
|
|
@@ -2808,14 +2849,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2808
2849
|
|
|
2809
2850
|
.tabs-vertical .tab.on .tab-label { color: var(--accent); }
|
|
2810
2851
|
|
|
2811
|
-
.tab-hint {
|
|
2812
|
-
display: block;
|
|
2813
|
-
margin-top: 1px;
|
|
2814
|
-
font-size: var(--text-xs);
|
|
2815
|
-
color: var(--muted);
|
|
2816
|
-
line-height: 1.35;
|
|
2817
|
-
}
|
|
2818
|
-
|
|
2819
2852
|
/* A heading above a run of tabs. Set apart from the run above by space, not
|
|
2820
2853
|
a rule -- the rail already has one edge -- and the tabs under it step in
|
|
2821
2854
|
by the label's own padding so the label reads as theirs. */
|
|
@@ -2826,8 +2859,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2826
2859
|
|
|
2827
2860
|
.tabs-vertical .tab-group:first-child { padding-top: var(--space-2); }
|
|
2828
2861
|
|
|
2829
|
-
.tab-group-label { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--text); }
|
|
2830
|
-
|
|
2831
2862
|
.tabs-vertical .tab.in-group { padding-left: var(--space-5); }
|
|
2832
2863
|
|
|
2833
2864
|
/* No line under a vertical strip -- its edge is the border on the right. */
|
|
@@ -2841,8 +2872,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2841
2872
|
}
|
|
2842
2873
|
|
|
2843
2874
|
.tabs-vertical .tab:active:not(:disabled) { border-color: transparent; }
|
|
2875
|
+
}
|
|
2844
2876
|
|
|
2845
2877
|
/* ---- ./toast.css ---- */
|
|
2878
|
+
@layer components {
|
|
2846
2879
|
/* ---------------------------------------------------------------- toasts */
|
|
2847
2880
|
.toasts {
|
|
2848
2881
|
position: fixed;
|
|
@@ -2940,8 +2973,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2940
2973
|
outline: 2px solid var(--accent);
|
|
2941
2974
|
outline-offset: 2px;
|
|
2942
2975
|
}
|
|
2976
|
+
}
|
|
2943
2977
|
|
|
2944
2978
|
/* ---- ./modal.css ---- */
|
|
2979
|
+
@layer components {
|
|
2945
2980
|
/* modal --------------------------------------------------------------- */
|
|
2946
2981
|
|
|
2947
2982
|
/* `hidden` needs saying out loud here. The browser's own `[hidden]` rule is a
|
|
@@ -3033,8 +3068,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3033
3068
|
`<strong>` rule above is the one that sets the size. */
|
|
3034
3069
|
/* Under the title, on the header's padding rather than the body's, so it reads
|
|
3035
3070
|
as part of the heading rather than as the first line of content. */
|
|
3036
|
-
.modal-desc { line-height: 1.5; }
|
|
3037
|
-
|
|
3038
3071
|
.modal-body { padding: var(--space-2) var(--space-4) var(--space-3); overflow-y: auto; }
|
|
3039
3072
|
|
|
3040
3073
|
/* The close cross. Its rule stayed behind in tf's stylesheet when the split
|
|
@@ -3172,8 +3205,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3172
3205
|
.modal.sheet[data-entering],
|
|
3173
3206
|
.modal.sheet[data-exiting] { animation: none; }
|
|
3174
3207
|
}
|
|
3208
|
+
}
|
|
3175
3209
|
|
|
3176
3210
|
/* ---- ./slider.css ---- */
|
|
3211
|
+
@layer components {
|
|
3177
3212
|
/* slider ----------------------------------------------------------------- */
|
|
3178
3213
|
/* A number from a range -- `Slider.tsx` says when one is the right control.
|
|
3179
3214
|
The row is laid out like a switch row: words on the left, the control on the
|
|
@@ -3200,12 +3235,8 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3200
3235
|
|
|
3201
3236
|
.slider-row.is-disabled { opacity: 0.55; }
|
|
3202
3237
|
|
|
3203
|
-
.slider-body { flex: 1 1 260px; min-width: 0; display: grid; gap: 1px; }
|
|
3204
|
-
|
|
3205
3238
|
.set-row > .slider-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
3206
3239
|
|
|
3207
|
-
.slider-label { color: var(--text); }
|
|
3208
|
-
|
|
3209
3240
|
.slider-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
3210
3241
|
|
|
3211
3242
|
/* The box, with the value printed inside it at the right where a select
|
|
@@ -3395,8 +3426,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3395
3426
|
the scale, and the two line up; an explicit `size-*` still wins. */
|
|
3396
3427
|
:where(.set-row) button,
|
|
3397
3428
|
:where(.set-row) .slider-box { font-size: var(--text-xs); }
|
|
3429
|
+
}
|
|
3398
3430
|
|
|
3399
3431
|
/* ---- ./checkbox.css ---- */
|
|
3432
|
+
@layer components {
|
|
3400
3433
|
/* A row you choose. There is no checkbox in it.
|
|
3401
3434
|
Every one of the fourteen in this app sits beside a name and a line of
|
|
3402
3435
|
explanation, so the row was always the thing being designed and the 17px
|
|
@@ -3429,8 +3462,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3429
3462
|
/* A run of checkboxes is one choice, not several settings that happen to be
|
|
3430
3463
|
adjacent. Tight enough that the group reads as a block -- at the spacing a
|
|
3431
3464
|
form field wants, four tools look like four unrelated questions. */
|
|
3432
|
-
.choice-group { display: grid; gap: var(--space-1); }
|
|
3433
|
-
|
|
3434
3465
|
/* The same choice, laid out as tiles instead of a column.
|
|
3435
3466
|
|
|
3436
3467
|
Four short names down the full width of a card is four wide bands for four
|
|
@@ -3554,8 +3585,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3554
3585
|
second line is what the first line is actually asking for. */
|
|
3555
3586
|
.choice-why { display: block; color: var(--muted); font-size: var(--text-sm); margin-top: 1px; }
|
|
3556
3587
|
|
|
3557
|
-
.choice-meta { color: var(--muted); font-size: var(--text-xs); font-family: var(--font-mono); }
|
|
3558
|
-
|
|
3559
3588
|
.choice[data-disabled] {
|
|
3560
3589
|
cursor: not-allowed;
|
|
3561
3590
|
border-color: var(--border);
|
|
@@ -3566,8 +3595,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3566
3595
|
.choice[data-disabled] .choice-why { opacity: 0.5; }
|
|
3567
3596
|
|
|
3568
3597
|
.choice[data-disabled]::after { opacity: 0.4; }
|
|
3598
|
+
}
|
|
3569
3599
|
|
|
3570
3600
|
/* ---- ./table.css ---- */
|
|
3601
|
+
@layer components {
|
|
3571
3602
|
/* A second line under a row's name, inside the `<th scope="row">` that makes it
|
|
3572
3603
|
one. The cell is bold because it is a heading; what hangs under it is not,
|
|
3573
3604
|
and inherited the weight -- so a pinned version read as loud as the thing it
|
|
@@ -3615,27 +3646,48 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3615
3646
|
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3616
3647
|
|
|
3617
3648
|
.data-table thead th[style*='right'] { text-align: right; }
|
|
3649
|
+
}
|
|
3618
3650
|
|
|
3619
3651
|
/* ---- ./sizegrid.css ---- */
|
|
3620
|
-
|
|
3652
|
+
@layer components {
|
|
3653
|
+
/* The cell's colour, all of it, in one place.
|
|
3654
|
+
*
|
|
3655
|
+
* `SizeGrid` draws the cell's geometry with utilities and leaves every colour
|
|
3656
|
+
* here, because `on` and `chosen` override the resting state -- and a utility
|
|
3657
|
+
* is in `@layer utilities`, which beats `@layer components` whatever the
|
|
3658
|
+
* selector. Stated as `surface-panel-2` and `border-border` on the element,
|
|
3659
|
+
* the resting state won permanently and no cell ever lit up.
|
|
3621
3660
|
*
|
|
3622
|
-
*
|
|
3623
|
-
*
|
|
3624
|
-
*
|
|
3625
|
-
|
|
3626
|
-
|
|
3661
|
+
* That is the third time this pattern has bitten: `Select`'s tick and
|
|
3662
|
+
* `Empty`'s figure were the other two. The rule: a resting state whose
|
|
3663
|
+
* active state is a CSS rule has to be a CSS rule too. */
|
|
3664
|
+
.size-cell {
|
|
3665
|
+
border: var(--border-width) solid var(--border);
|
|
3666
|
+
background: var(--panel-2);
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
/* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3670
|
+
when nothing is hovered so the two can never contradict each other. */
|
|
3627
3671
|
.size-cell.on {
|
|
3628
3672
|
border-color: var(--accent);
|
|
3629
3673
|
background: color-mix(in srgb, var(--accent) 45%, transparent);
|
|
3630
3674
|
}
|
|
3631
3675
|
|
|
3676
|
+
.size-cell.chosen { border-color: var(--accent); }
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3632
3679
|
/* ---- ./tooltip.css ---- */
|
|
3680
|
+
@layer components {
|
|
3633
3681
|
/* A callout: something worth knowing, with nothing to answer. Distinct from a
|
|
3634
3682
|
`?`, which is an offer to read more, and from a banner, which is a problem.
|
|
3635
3683
|
The mark is a round `i` rather than an emoji so it takes the theme's colours
|
|
3636
3684
|
and stays the same size as the text beside it. */
|
|
3637
|
-
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3638
|
-
nearly identical to it, which is the whole point of the consolidation
|
|
3685
|
+
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3686
|
+
than nearly identical to it, which is the whole point of the consolidation.
|
|
3687
|
+
(This comment has been unterminated since before the Tailwind branch -- it
|
|
3688
|
+
stops mid-sentence and never closes, so the CSS parser merged it with the
|
|
3689
|
+
one below and recovered. Nothing was lost from the stylesheet; the rest of
|
|
3690
|
+
the sentence was. Closed here rather than guessed at.) */
|
|
3639
3691
|
|
|
3640
3692
|
/* What is left once `Tooltip` draws its own mark: the hover and focus that
|
|
3641
3693
|
reach the mark from its parent, and the tip -- whose closed and open
|
|
@@ -3718,8 +3770,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3718
3770
|
}
|
|
3719
3771
|
|
|
3720
3772
|
.explain-tip strong { color: var(--text); font-weight: 600; }
|
|
3773
|
+
}
|
|
3721
3774
|
|
|
3722
3775
|
/* ---- ./illustration.css ---- */
|
|
3776
|
+
@layer components {
|
|
3723
3777
|
/* illustrations -------------------------------------------------------- */
|
|
3724
3778
|
|
|
3725
3779
|
/* Open Peeps, two colours, wearing whatever the theme is.
|
|
@@ -3727,8 +3781,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3727
3781
|
reason they can live in an app with four palettes: `ink` becomes the current
|
|
3728
3782
|
text colour and `paper` becomes the surface behind it, so one file covers
|
|
3729
3783
|
Night, Paper and both halves of System. Give the wrapper a `color` and
|
|
3730
|
-
the figure follows it
|
|
3731
|
-
one thing on screen worth looking at.
|
|
3784
|
+
the figure follows it: `--muted` for a quiet empty state, `--accent` for the
|
|
3785
|
+
one thing on screen worth looking at. Set that colour on the wrapper --
|
|
3786
|
+
`Empty` reaches for `text-muted`, and any token works. */
|
|
3732
3787
|
.illo {
|
|
3733
3788
|
display: inline-block;
|
|
3734
3789
|
/* Height is the given dimension and the width comes from the drawing, so a
|
|
@@ -3745,20 +3800,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3745
3800
|
caller says otherwise. Not `transparent`: these have overlapping shapes, and
|
|
3746
3801
|
a shirt that lets the arm behind it show through reads as a hole. */
|
|
3747
3802
|
.illo .paper { fill: var(--illo-paper); }
|
|
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); }
|
|
3803
|
+
}
|
|
3760
3804
|
|
|
3761
3805
|
/* ---- ./field.css ---- */
|
|
3806
|
+
@layer components {
|
|
3762
3807
|
/* fields --------------------------------------------------------------- */
|
|
3763
3808
|
|
|
3764
3809
|
/* Label, description, input, error -- in the order they are wanted. The
|
|
@@ -3766,7 +3811,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3766
3811
|
to what was typed, so it goes after. */
|
|
3767
3812
|
.field { display: grid; gap: var(--space-1); }
|
|
3768
3813
|
|
|
3769
|
-
|
|
3814
|
+
/* `.field-stack-layout` carries no rules: stacking is what `.field` already
|
|
3815
|
+
does, and the class is emitted only so that both layouts name themselves
|
|
3816
|
+
the same way (`field-${layout}-layout`). Only the row layout overrides. */
|
|
3770
3817
|
|
|
3771
3818
|
.field-row-layout > .field-label { grid-column: 1; }
|
|
3772
3819
|
|
|
@@ -3787,8 +3834,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3787
3834
|
|
|
3788
3835
|
/* Not red. The asterisk marks which fields are required; colouring it the same
|
|
3789
3836
|
as a failure says something has already gone wrong with every one of them. */
|
|
3790
|
-
.field-required { color: var(--muted); }
|
|
3791
|
-
|
|
3792
3837
|
.field-hint,
|
|
3793
3838
|
.field-error { margin: 0; font-size: var(--text-sm); line-height: 1.45; }
|
|
3794
3839
|
|
|
@@ -3810,8 +3855,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3810
3855
|
/* Fields stacked down a form. Wider than the gap inside one field, so the
|
|
3811
3856
|
label of the next belongs to the input under it rather than to the error
|
|
3812
3857
|
above it. */
|
|
3813
|
-
.field-stack { display: grid; gap: var(--space-4); }
|
|
3814
|
-
|
|
3815
3858
|
.field-row > .field { flex: 1; min-width: 0; }
|
|
3816
3859
|
|
|
3817
3860
|
/* A password with an eye -- `Input type="password"`.
|
|
@@ -3933,14 +3976,12 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3933
3976
|
background: var(--panel-2);
|
|
3934
3977
|
color: var(--text);
|
|
3935
3978
|
}
|
|
3979
|
+
}
|
|
3936
3980
|
|
|
3937
3981
|
/* ---- ./tour.css ---- */
|
|
3982
|
+
@layer components {
|
|
3938
3983
|
/* tour ----------------------------------------------------------------- */
|
|
3939
3984
|
|
|
3940
|
-
/* The layer sits over everything and catches nothing: the scrim is painted by
|
|
3941
|
-
the hole's shadow, so there is no full-screen element to swallow a click. */
|
|
3942
|
-
.tour { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
|
|
3943
|
-
|
|
3944
3985
|
/* The control the tour is currently pointing at.
|
|
3945
3986
|
|
|
3946
3987
|
Much of this chrome is invisible until you touch it -- `.view-add` lives at
|
|
@@ -3951,11 +3992,14 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3951
3992
|
what every control does at rest, and the alternative is naming each one here
|
|
3952
3993
|
and watching that list drift from the rules that hide them. One declaration
|
|
3953
3994
|
that outranks whatever the resting state is beats an enumeration that goes
|
|
3954
|
-
stale. It is scoped to a class only ever present on one element at a time.
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3995
|
+
stale. It is scoped to a class only ever present on one element at a time.
|
|
3996
|
+
|
|
3997
|
+
Opacity and nothing else. This forced `color: var(--text)` too, from the
|
|
3998
|
+
original port, with no case on record that needed it -- and it broke the
|
|
3999
|
+
first target that painted its own background, turning a primary button's
|
|
4000
|
+
label dark on accent at 2.2:1. The spotlight makes a control visible; what
|
|
4001
|
+
colour it is at rest is the control's business. */
|
|
4002
|
+
.tour-target { opacity: 1 !important; }
|
|
3959
4003
|
|
|
3960
4004
|
/* The spotlight. An enormous spread shadow dims the whole window except the
|
|
3961
4005
|
rectangle it is drawn on, which needs no clip path and no arithmetic. */
|
|
@@ -3989,19 +4033,19 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3989
4033
|
|
|
3990
4034
|
.tour-card:focus { outline: none; }
|
|
3991
4035
|
|
|
3992
|
-
.tour-title { font-size: var(--text-base); }
|
|
3993
|
-
|
|
3994
4036
|
.tour-body { margin: 0; color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
3995
4037
|
|
|
3996
4038
|
.tour-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
|
|
3997
4039
|
|
|
3998
4040
|
.tour-count { color: var(--muted); font-size: var(--text-xs); }
|
|
4041
|
+
}
|
|
3999
4042
|
|
|
4000
4043
|
/* The mail and forum shell, added in 0.4.0. After the rest, because the
|
|
4001
4044
|
anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
|
|
4002
4045
|
rule of equal specificity that came earlier would lose to whatever the
|
|
4003
4046
|
sheets they cover happen to set. */
|
|
4004
4047
|
/* ---- ./stat.css ---- */
|
|
4048
|
+
@layer components {
|
|
4005
4049
|
/* What the utilities on `Stat` cannot say: a tone on the tile colouring the
|
|
4006
4050
|
figure inside it. An attribute on the parent selecting a child is a
|
|
4007
4051
|
relationship; a utility is a property on one element.
|
|
@@ -4012,8 +4056,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4012
4056
|
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
4013
4057
|
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
4014
4058
|
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
4059
|
+
}
|
|
4015
4060
|
|
|
4016
4061
|
/* ---- ./shell.css ---- */
|
|
4062
|
+
@layer components {
|
|
4017
4063
|
/* The measure, and only the measure.
|
|
4018
4064
|
*
|
|
4019
4065
|
* `Shell` draws itself with utilities -- it is layout and nothing else. What
|
|
@@ -4040,8 +4086,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4040
4086
|
font-size: var(--text-sm);
|
|
4041
4087
|
white-space: nowrap;
|
|
4042
4088
|
}
|
|
4089
|
+
}
|
|
4043
4090
|
|
|
4044
4091
|
/* ---- ./scrollarea.css ---- */
|
|
4092
|
+
@layer components {
|
|
4045
4093
|
/* A box that scrolls, with its edges drawn.
|
|
4046
4094
|
|
|
4047
4095
|
The fades are `::before`/`::after` on the scroller itself, pinned with
|
|
@@ -4134,8 +4182,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4134
4182
|
.scroller.faded::before,
|
|
4135
4183
|
.scroller.faded::after { transition: none; }
|
|
4136
4184
|
}
|
|
4185
|
+
}
|
|
4137
4186
|
|
|
4138
4187
|
/* ---- ./splitpane.css ---- */
|
|
4188
|
+
@layer components {
|
|
4139
4189
|
/* Two panes and the handle between them. */
|
|
4140
4190
|
.split {
|
|
4141
4191
|
display: flex;
|
|
@@ -4154,17 +4204,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4154
4204
|
the intrinsic width of a mail list is the longest unbroken subject line in
|
|
4155
4205
|
it. Without this the handle stops partway across and nothing on screen says
|
|
4156
4206
|
why -- it just refuses, differently for every mailbox. */
|
|
4157
|
-
.split-pane {
|
|
4158
|
-
min-width: 0;
|
|
4159
|
-
min-height: 0;
|
|
4160
|
-
overflow: hidden;
|
|
4161
|
-
display: flex;
|
|
4162
|
-
flex-direction: column;
|
|
4163
|
-
}
|
|
4164
|
-
|
|
4165
|
-
.split-first { flex: 0 0 var(--split); }
|
|
4166
|
-
.split-second { flex: 1 1 0; }
|
|
4167
|
-
|
|
4168
4207
|
/* The handle is wider than it looks: a hairline is a correct-looking divider
|
|
4169
4208
|
and an impossible pointer target. The grip is the line, drawn at
|
|
4170
4209
|
`--border-width` down the middle of a `--space-3` strip, and the strip is
|
|
@@ -4235,8 +4274,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4235
4274
|
@media (prefers-reduced-motion: reduce) {
|
|
4236
4275
|
.split-grip { transition: none; }
|
|
4237
4276
|
}
|
|
4277
|
+
}
|
|
4238
4278
|
|
|
4239
4279
|
/* ---- ./popover.css ---- */
|
|
4280
|
+
@layer components {
|
|
4240
4281
|
/* A small surface anchored to what opened it. Same sheet as the select's list,
|
|
4241
4282
|
because they are the same object -- something that appeared over the page,
|
|
4242
4283
|
attached to a control. */
|
|
@@ -4259,13 +4300,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4259
4300
|
z-index: 60;
|
|
4260
4301
|
}
|
|
4261
4302
|
|
|
4262
|
-
.pop-body {
|
|
4263
|
-
padding: var(--space-3);
|
|
4264
|
-
outline: none;
|
|
4265
|
-
color: var(--text);
|
|
4266
|
-
font-size: var(--text-sm);
|
|
4267
|
-
}
|
|
4268
|
-
|
|
4269
4303
|
/* Entry, and the direction it comes from. `data-placement` is React Aria's,
|
|
4270
4304
|
set to where the surface actually went rather than where it was asked to go,
|
|
4271
4305
|
so the movement agrees with the flip. */
|
|
@@ -4290,8 +4324,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4290
4324
|
.pop[data-entering],
|
|
4291
4325
|
.pop[data-exiting] { animation: none; }
|
|
4292
4326
|
}
|
|
4327
|
+
}
|
|
4293
4328
|
|
|
4294
4329
|
/* ---- ./menu.css ---- */
|
|
4330
|
+
@layer components {
|
|
4295
4331
|
/* What is left once `Menu` draws its sheet and its list: the rows, whose
|
|
4296
4332
|
`data-focused`, `data-pressed` and danger states React Aria stamps on
|
|
4297
4333
|
them, and the rules that reach from a row into what it holds. The
|
|
@@ -4324,8 +4360,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4324
4360
|
.menu-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4325
4361
|
.menu-item[data-focused] .menu-icon { color: var(--text); }
|
|
4326
4362
|
|
|
4327
|
-
.menu-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4328
|
-
.menu-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4329
4363
|
.menu-desc {
|
|
4330
4364
|
font-size: var(--text-xs);
|
|
4331
4365
|
color: var(--muted);
|
|
@@ -4373,8 +4407,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4373
4407
|
}
|
|
4374
4408
|
|
|
4375
4409
|
.menu-sheet { box-shadow: var(--shadow-2); }
|
|
4410
|
+
}
|
|
4376
4411
|
|
|
4377
4412
|
/* ---- ./command.css ---- */
|
|
4413
|
+
@layer components {
|
|
4378
4414
|
/* The command palette: a field over the app and a list under it. */
|
|
4379
4415
|
.cmd-scrim {
|
|
4380
4416
|
position: fixed;
|
|
@@ -4402,18 +4438,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4402
4438
|
flex-direction: column;
|
|
4403
4439
|
}
|
|
4404
4440
|
|
|
4405
|
-
.cmd-body { outline: none; display: flex; flex-direction: column; min-height: 0; }
|
|
4406
|
-
|
|
4407
|
-
.cmd-field {
|
|
4408
|
-
display: flex;
|
|
4409
|
-
align-items: center;
|
|
4410
|
-
gap: var(--space-2);
|
|
4411
|
-
padding: var(--space-3) var(--space-4);
|
|
4412
|
-
border-bottom: var(--border-width) solid var(--border);
|
|
4413
|
-
}
|
|
4414
|
-
|
|
4415
|
-
.cmd-mark { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4416
|
-
|
|
4417
4441
|
/* No border, no focus ring on the input itself: the whole surface is the
|
|
4418
4442
|
field, focus is already in it when it opens, and a ring around a box that
|
|
4419
4443
|
fills the top of the palette is a ring around the palette. */
|
|
@@ -4430,22 +4454,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4430
4454
|
|
|
4431
4455
|
.cmd-input::placeholder { color: var(--muted); }
|
|
4432
4456
|
|
|
4433
|
-
.cmd-list {
|
|
4434
|
-
padding: var(--space-2);
|
|
4435
|
-
overflow: auto;
|
|
4436
|
-
overscroll-behavior: contain;
|
|
4437
|
-
outline: none;
|
|
4438
|
-
min-height: 0;
|
|
4439
|
-
}
|
|
4440
|
-
|
|
4441
|
-
.cmd-group-title {
|
|
4442
|
-
padding: var(--space-2) var(--space-2) var(--space-1);
|
|
4443
|
-
font-size: var(--text-2xs);
|
|
4444
|
-
text-transform: uppercase;
|
|
4445
|
-
letter-spacing: var(--tracking);
|
|
4446
|
-
color: var(--muted);
|
|
4447
|
-
}
|
|
4448
|
-
|
|
4449
4457
|
.cmd-item {
|
|
4450
4458
|
display: flex;
|
|
4451
4459
|
align-items: center;
|
|
@@ -4481,8 +4489,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4481
4489
|
.cmd-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4482
4490
|
.cmd-item[data-focused] .cmd-icon { color: var(--text); }
|
|
4483
4491
|
|
|
4484
|
-
.cmd-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4485
|
-
.cmd-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4486
4492
|
.cmd-desc {
|
|
4487
4493
|
font-size: var(--text-xs);
|
|
4488
4494
|
color: var(--muted);
|
|
@@ -4516,8 +4522,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4516
4522
|
.cmd-scrim[data-exiting],
|
|
4517
4523
|
.cmd[data-entering] { animation: none; }
|
|
4518
4524
|
}
|
|
4525
|
+
}
|
|
4519
4526
|
|
|
4520
4527
|
/* ---- ./pagination.css ---- */
|
|
4528
|
+
@layer components {
|
|
4521
4529
|
/* What is left once `Pagination` draws its own frame: the step and page
|
|
4522
4530
|
buttons, whose hover, focus-visible and current states are pseudo-classes
|
|
4523
4531
|
on two selectors at once, and `.pager-count strong`, which reaches into
|
|
@@ -4636,8 +4644,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4636
4644
|
.pager-page,
|
|
4637
4645
|
.pager-jump { transition: none; }
|
|
4638
4646
|
}
|
|
4647
|
+
}
|
|
4639
4648
|
|
|
4640
4649
|
/* ---- ./identity.css ---- */
|
|
4650
|
+
@layer components {
|
|
4641
4651
|
/* A person, said in one line: initials, name, sometimes the address. */
|
|
4642
4652
|
.ident {
|
|
4643
4653
|
display: inline-flex;
|
|
@@ -4680,25 +4690,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4680
4690
|
font-size: var(--text-2xs);
|
|
4681
4691
|
}
|
|
4682
4692
|
|
|
4683
|
-
.ident-text { display: grid; min-width: 0; }
|
|
4684
|
-
|
|
4685
|
-
.ident-name {
|
|
4686
|
-
overflow: hidden;
|
|
4687
|
-
text-overflow: ellipsis;
|
|
4688
|
-
white-space: nowrap;
|
|
4689
|
-
font-weight: var(--weight);
|
|
4690
|
-
}
|
|
4691
|
-
|
|
4692
|
-
.ident-address {
|
|
4693
|
-
overflow: hidden;
|
|
4694
|
-
text-overflow: ellipsis;
|
|
4695
|
-
white-space: nowrap;
|
|
4696
|
-
font-size: var(--text-xs);
|
|
4697
|
-
color: var(--muted);
|
|
4698
|
-
}
|
|
4699
|
-
|
|
4700
|
-
.ident-aside { flex: none; color: var(--muted); font-size: var(--text-xs); }
|
|
4701
|
-
|
|
4702
4693
|
/* A chip in a composer's To field: boxed, tighter, removable. */
|
|
4703
4694
|
.ident.kind-chip {
|
|
4704
4695
|
gap: var(--space-1);
|
|
@@ -4738,4 +4729,5 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4738
4729
|
|
|
4739
4730
|
.ident-remove:hover { background: var(--panel); color: var(--text); }
|
|
4740
4731
|
.ident-remove:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
4732
|
+
}
|
|
4741
4733
|
|