@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/tf.css
CHANGED
|
@@ -287,12 +287,9 @@
|
|
|
287
287
|
--font-sans: var(--font-sans);
|
|
288
288
|
--font-mono: var(--font-mono);
|
|
289
289
|
--text-xs: var(--text-xs);
|
|
290
|
-
--text-xs--line-height: inherit;
|
|
291
290
|
--text-sm: var(--text-sm);
|
|
292
|
-
--text-sm--line-height: inherit;
|
|
293
291
|
--text-base: var(--text-base);
|
|
294
292
|
--text-lg: var(--text-lg);
|
|
295
|
-
--text-lg--line-height: inherit;
|
|
296
293
|
--text-xl: var(--text-xl);
|
|
297
294
|
--font-weight-normal: var(--weight);
|
|
298
295
|
--tracking-normal: var(--tracking);
|
|
@@ -307,19 +304,20 @@
|
|
|
307
304
|
--spacing-5: var(--space-5);
|
|
308
305
|
--spacing-6: var(--space-6);
|
|
309
306
|
--spacing-10: var(--space-10);
|
|
310
|
-
--text-2xs--line-height: inherit;
|
|
311
307
|
--text-2xs: var(--text-2xs);
|
|
312
308
|
--text-md: var(--text-md);
|
|
313
309
|
--font-weight-strong: var(--weight-strong);
|
|
314
310
|
--radius-pill: var(--radius-pill);
|
|
315
311
|
--color-text: var(--text);
|
|
316
312
|
--color-muted: var(--muted);
|
|
317
|
-
--color-accent: var(--accent);
|
|
318
313
|
--color-border: var(--border);
|
|
319
314
|
--color-border-strong: var(--border-strong);
|
|
320
315
|
}
|
|
321
316
|
}
|
|
322
317
|
@layer utilities {
|
|
318
|
+
.pointer-events-none {
|
|
319
|
+
pointer-events: none;
|
|
320
|
+
}
|
|
323
321
|
.collapse {
|
|
324
322
|
visibility: collapse;
|
|
325
323
|
}
|
|
@@ -352,6 +350,9 @@
|
|
|
352
350
|
.sticky {
|
|
353
351
|
position: sticky;
|
|
354
352
|
}
|
|
353
|
+
.inset-0 {
|
|
354
|
+
inset: 0px;
|
|
355
|
+
}
|
|
355
356
|
.z-\[60\] {
|
|
356
357
|
z-index: 60;
|
|
357
358
|
}
|
|
@@ -385,12 +386,21 @@
|
|
|
385
386
|
.mt-1 {
|
|
386
387
|
margin-top: var(--spacing-1);
|
|
387
388
|
}
|
|
389
|
+
.mt-2 {
|
|
390
|
+
margin-top: var(--spacing-2);
|
|
391
|
+
}
|
|
392
|
+
.mt-px {
|
|
393
|
+
margin-top: 1px;
|
|
394
|
+
}
|
|
388
395
|
.mb-3 {
|
|
389
396
|
margin-bottom: var(--spacing-3);
|
|
390
397
|
}
|
|
391
398
|
.ml-2 {
|
|
392
399
|
margin-left: var(--spacing-2);
|
|
393
400
|
}
|
|
401
|
+
.ml-auto {
|
|
402
|
+
margin-left: auto;
|
|
403
|
+
}
|
|
394
404
|
.block {
|
|
395
405
|
display: block;
|
|
396
406
|
}
|
|
@@ -415,6 +425,9 @@
|
|
|
415
425
|
.table {
|
|
416
426
|
display: table;
|
|
417
427
|
}
|
|
428
|
+
.h-4 {
|
|
429
|
+
height: var(--spacing-4);
|
|
430
|
+
}
|
|
418
431
|
.h-\[14px\] {
|
|
419
432
|
height: 14px;
|
|
420
433
|
}
|
|
@@ -433,6 +446,9 @@
|
|
|
433
446
|
.min-h-screen {
|
|
434
447
|
min-height: 100vh;
|
|
435
448
|
}
|
|
449
|
+
.w-4 {
|
|
450
|
+
width: var(--spacing-4);
|
|
451
|
+
}
|
|
436
452
|
.w-\[18px\] {
|
|
437
453
|
width: 18px;
|
|
438
454
|
}
|
|
@@ -460,6 +476,18 @@
|
|
|
460
476
|
.flex-1 {
|
|
461
477
|
flex: 1;
|
|
462
478
|
}
|
|
479
|
+
.flex-\[0_0_var\(--split\)\] {
|
|
480
|
+
flex: 0 0 var(--split);
|
|
481
|
+
}
|
|
482
|
+
.flex-\[1_1_0\] {
|
|
483
|
+
flex: 1 1 0;
|
|
484
|
+
}
|
|
485
|
+
.flex-\[1_1_260px\] {
|
|
486
|
+
flex: 1 1 260px;
|
|
487
|
+
}
|
|
488
|
+
.flex-\[1_1_auto\] {
|
|
489
|
+
flex: 1 1 auto;
|
|
490
|
+
}
|
|
463
491
|
.flex-none {
|
|
464
492
|
flex: none;
|
|
465
493
|
}
|
|
@@ -490,6 +518,9 @@
|
|
|
490
518
|
.flex-wrap {
|
|
491
519
|
flex-wrap: wrap;
|
|
492
520
|
}
|
|
521
|
+
.place-items-center {
|
|
522
|
+
place-items: center;
|
|
523
|
+
}
|
|
493
524
|
.items-baseline {
|
|
494
525
|
align-items: baseline;
|
|
495
526
|
}
|
|
@@ -523,6 +554,9 @@
|
|
|
523
554
|
.gap-\[var\(--border-width\)\] {
|
|
524
555
|
gap: var(--border-width);
|
|
525
556
|
}
|
|
557
|
+
.gap-px {
|
|
558
|
+
gap: 1px;
|
|
559
|
+
}
|
|
526
560
|
.self-center {
|
|
527
561
|
align-self: center;
|
|
528
562
|
}
|
|
@@ -570,9 +604,6 @@
|
|
|
570
604
|
--tw-border-style: dashed;
|
|
571
605
|
border-style: dashed;
|
|
572
606
|
}
|
|
573
|
-
.border-accent {
|
|
574
|
-
border-color: var(--color-accent);
|
|
575
|
-
}
|
|
576
607
|
.border-border {
|
|
577
608
|
border-color: var(--color-border);
|
|
578
609
|
}
|
|
@@ -588,9 +619,15 @@
|
|
|
588
619
|
.p-2 {
|
|
589
620
|
padding: var(--spacing-2);
|
|
590
621
|
}
|
|
622
|
+
.p-3 {
|
|
623
|
+
padding: var(--spacing-3);
|
|
624
|
+
}
|
|
591
625
|
.p-4 {
|
|
592
626
|
padding: var(--spacing-4);
|
|
593
627
|
}
|
|
628
|
+
.px-2 {
|
|
629
|
+
padding-inline: var(--spacing-2);
|
|
630
|
+
}
|
|
594
631
|
.px-4 {
|
|
595
632
|
padding-inline: var(--spacing-4);
|
|
596
633
|
}
|
|
@@ -609,6 +646,12 @@
|
|
|
609
646
|
.py-10 {
|
|
610
647
|
padding-block: var(--spacing-10);
|
|
611
648
|
}
|
|
649
|
+
.pt-2 {
|
|
650
|
+
padding-top: var(--spacing-2);
|
|
651
|
+
}
|
|
652
|
+
.pb-1 {
|
|
653
|
+
padding-bottom: var(--spacing-1);
|
|
654
|
+
}
|
|
612
655
|
.pb-2 {
|
|
613
656
|
padding-bottom: var(--spacing-2);
|
|
614
657
|
}
|
|
@@ -623,19 +666,18 @@
|
|
|
623
666
|
}
|
|
624
667
|
.text-2xs {
|
|
625
668
|
font-size: var(--text-2xs);
|
|
626
|
-
|
|
669
|
+
}
|
|
670
|
+
.text-base {
|
|
671
|
+
font-size: var(--text-base);
|
|
627
672
|
}
|
|
628
673
|
.text-lg {
|
|
629
674
|
font-size: var(--text-lg);
|
|
630
|
-
line-height: var(--tw-leading, var(--text-lg--line-height));
|
|
631
675
|
}
|
|
632
676
|
.text-sm {
|
|
633
677
|
font-size: var(--text-sm);
|
|
634
|
-
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
635
678
|
}
|
|
636
679
|
.text-xs {
|
|
637
680
|
font-size: var(--text-xs);
|
|
638
|
-
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
639
681
|
}
|
|
640
682
|
.leading-\[0\] {
|
|
641
683
|
--tw-leading: 0;
|
|
@@ -649,6 +691,10 @@
|
|
|
649
691
|
--tw-leading: 1.25;
|
|
650
692
|
line-height: 1.25;
|
|
651
693
|
}
|
|
694
|
+
.leading-\[1\.35\] {
|
|
695
|
+
--tw-leading: 1.35;
|
|
696
|
+
line-height: 1.35;
|
|
697
|
+
}
|
|
652
698
|
.leading-\[16px\] {
|
|
653
699
|
--tw-leading: 16px;
|
|
654
700
|
line-height: 16px;
|
|
@@ -690,12 +736,12 @@
|
|
|
690
736
|
--tw-numeric-spacing: tabular-nums;
|
|
691
737
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
692
738
|
}
|
|
693
|
-
.opacity-0 {
|
|
694
|
-
opacity: 0%;
|
|
695
|
-
}
|
|
696
739
|
.opacity-60 {
|
|
697
740
|
opacity: 60%;
|
|
698
741
|
}
|
|
742
|
+
.opacity-90 {
|
|
743
|
+
opacity: 90%;
|
|
744
|
+
}
|
|
699
745
|
.opacity-\[0\.55\] {
|
|
700
746
|
opacity: 0.55;
|
|
701
747
|
}
|
|
@@ -735,9 +781,6 @@
|
|
|
735
781
|
.surface-panel {
|
|
736
782
|
background: var(--panel);
|
|
737
783
|
}
|
|
738
|
-
.surface-panel-2 {
|
|
739
|
-
background: var(--panel-2);
|
|
740
|
-
}
|
|
741
784
|
.disabled\:cursor-default:disabled {
|
|
742
785
|
cursor: default;
|
|
743
786
|
}
|
|
@@ -977,7 +1020,19 @@
|
|
|
977
1020
|
}
|
|
978
1021
|
}
|
|
979
1022
|
|
|
980
|
-
/* ---- ./
|
|
1023
|
+
/* ---- ./_system-light.css ---- */
|
|
1024
|
+
/* The `system` theme's light half.
|
|
1025
|
+
*
|
|
1026
|
+
* Its own file, and outside the components layer, because it is a *theme*
|
|
1027
|
+
* rather than a component rule. `tokens.css` states the dark base on `:root`
|
|
1028
|
+
* and is unlayered; the moment this sat inside `@layer components` it lost to
|
|
1029
|
+
* that, and every `system` specimen rendered dark on a light-mode machine.
|
|
1030
|
+
* Unlayered beats layered whatever the selector says, which is exactly the
|
|
1031
|
+
* trap this repository keeps finding in different costumes.
|
|
1032
|
+
*
|
|
1033
|
+
* The underscore marks it the same way `_tailwind.built.css` is marked:
|
|
1034
|
+
* `copy-css.mjs` passes both through without wrapping them.
|
|
1035
|
+
*/
|
|
981
1036
|
/* Light, only under the `system` theme. This used to override `:root`
|
|
982
1037
|
unconditionally, so choosing a dark theme on a light-mode laptop got
|
|
983
1038
|
silently repainted. Every other theme states its own palette. */
|
|
@@ -1006,6 +1061,8 @@
|
|
|
1006
1061
|
}
|
|
1007
1062
|
}
|
|
1008
1063
|
|
|
1064
|
+
/* ---- ./base.css ---- */
|
|
1065
|
+
@layer components {
|
|
1009
1066
|
/* Derived from the two surfaces every theme already defines, so a theme gets a
|
|
1010
1067
|
control colour without knowing this exists. */
|
|
1011
1068
|
/* Pseudo-elements too. `*` does not match them, and `box-sizing` is not
|
|
@@ -1723,23 +1780,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1723
1780
|
template are allowed to diverge, and this is only saying that they have. */
|
|
1724
1781
|
.set-hint.drifted { color: var(--warn); }
|
|
1725
1782
|
|
|
1726
|
-
/* What an applet drew, read back. A tree rather than prose, so it is left as
|
|
1727
|
-
preformatted text and given a ceiling -- a busy applet is a hundred lines and
|
|
1728
|
-
this sits inside a settings pane. */
|
|
1729
|
-
.drawn {
|
|
1730
|
-
margin: var(--space-2) 0 0;
|
|
1731
|
-
padding: var(--space-2) var(--space-2);
|
|
1732
|
-
max-height: 220px;
|
|
1733
|
-
overflow: auto;
|
|
1734
|
-
font-size: var(--text-xs);
|
|
1735
|
-
line-height: 1.45;
|
|
1736
|
-
white-space: pre-wrap;
|
|
1737
|
-
overflow-wrap: anywhere;
|
|
1738
|
-
border: 1px solid var(--border);
|
|
1739
|
-
border-radius: var(--radius);
|
|
1740
|
-
background: var(--panel-2);
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
1783
|
/* One applet, alone on the page, at `/applet/<id>`. Fills the window: there is
|
|
1744
1784
|
no grid here to decide a height, and a screenshot of an applet letterboxed
|
|
1745
1785
|
inside a page is mostly not the applet. */
|
|
@@ -1786,11 +1826,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1786
1826
|
that belongs to a conversation lives here any more, so it can breathe. */
|
|
1787
1827
|
.topbar .ctl-grow { flex: 1; min-width: 0; }
|
|
1788
1828
|
|
|
1789
|
-
/* Back on the left, Next on the right, with the gap between them doing the
|
|
1790
|
-
separating -- so the button that goes forward is in the same place on both
|
|
1791
|
-
pages instead of sliding when Back appears. */
|
|
1792
|
-
.first-run-actions { align-items: center; }
|
|
1793
|
-
|
|
1794
1829
|
@keyframes listening-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }
|
|
1795
1830
|
|
|
1796
1831
|
/* table ---------------------------------------------------------------- */
|
|
@@ -1866,8 +1901,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1866
1901
|
color: var(--muted);
|
|
1867
1902
|
opacity: 1;
|
|
1868
1903
|
}
|
|
1904
|
+
}
|
|
1869
1905
|
|
|
1870
1906
|
/* ---- ./select.css ---- */
|
|
1907
|
+
@layer components {
|
|
1871
1908
|
/* How big a control is, asked for rather than inherited.
|
|
1872
1909
|
Four sizes existed and every one of them came from a descendant selector:
|
|
1873
1910
|
`.set-row button` was 11px in 3px of padding, `.approval-actions button` was
|
|
@@ -1962,16 +1999,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1962
1999
|
/* State is read off React Aria's attributes: `data-open` on the root,
|
|
1963
2000
|
`data-focused` / `data-selected` / `data-disabled` on an item, where
|
|
1964
2001
|
`.open`, `[data-active]`, `.on` and `.off` used to be. */
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2002
|
+
/* The list keeps two things the utilities on `Select` cannot say.
|
|
2003
|
+
*
|
|
2004
|
+
* `scroll-padding-block`: the same room while the list is scrolled as it has
|
|
2005
|
+
* at rest. Padding at the top of a scroll container scrolls away with the
|
|
2006
|
+
* content, so the row `scrollIntoView({block: 'nearest'})` brings up ended
|
|
2007
|
+
* flush against the border and read as clipped rather than as one of a set --
|
|
2008
|
+
* and this list opens scrolled to whatever is chosen, so that was the
|
|
2009
|
+
* ordinary state.
|
|
2010
|
+
*
|
|
2011
|
+
* `box-shadow`: `--shadow-2` is a token, and a utility would have to inline
|
|
2012
|
+
* the value, which is the one thing the vocabulary exists to stop. */
|
|
2013
|
+
.sel-list {
|
|
1970
2014
|
scroll-padding-block: var(--space-1);
|
|
1971
|
-
list-style: none;
|
|
1972
|
-
border: var(--border-width) solid var(--border-strong);
|
|
1973
|
-
border-radius: var(--radius-md);
|
|
1974
|
-
background: var(--panel);
|
|
1975
2015
|
box-shadow: var(--shadow-2);
|
|
1976
2016
|
}
|
|
1977
2017
|
|
|
@@ -1986,6 +2026,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1986
2026
|
|
|
1987
2027
|
/* The tick marks the chosen row. Colour alone would not: a list where the only
|
|
1988
2028
|
difference is a hue is a list you cannot read past. */
|
|
2029
|
+
/* The tick's resting state lives here, beside the state that overrides it.
|
|
2030
|
+
*
|
|
2031
|
+
* It was `opacity-0` on the element and `opacity: 1` here, which worked only
|
|
2032
|
+
* while this sheet was unlayered. A utility is in `@layer utilities` and
|
|
2033
|
+
* beats `@layer components` whatever the selector, so the moment the sheets
|
|
2034
|
+
* moved into a layer the tick stopped appearing on the selected row -- the
|
|
2035
|
+
* resting state won permanently.
|
|
2036
|
+
*
|
|
2037
|
+
* The rule generalises: a utility for a resting state whose active state is a
|
|
2038
|
+
* relationship between elements will always beat that active state. The pair
|
|
2039
|
+
* has to sit in the same layer. */
|
|
2040
|
+
.sel-tick { opacity: 0; }
|
|
2041
|
+
|
|
1989
2042
|
.sel-item[data-selected] .sel-tick { opacity: 1; }
|
|
1990
2043
|
|
|
1991
2044
|
/* The icon on a speaker's row in the open list -- `Select`'s `aside`. Last in
|
|
@@ -2020,8 +2073,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2020
2073
|
.field > input,
|
|
2021
2074
|
.field > textarea,
|
|
2022
2075
|
.field > .sel { width: 100%; }
|
|
2076
|
+
}
|
|
2023
2077
|
|
|
2024
2078
|
/* ---- ./dangerzone.css ---- */
|
|
2079
|
+
@layer components {
|
|
2025
2080
|
/* Destructive, and legible as such standing still. */
|
|
2026
2081
|
.btn.danger {
|
|
2027
2082
|
color: var(--bad);
|
|
@@ -2111,8 +2166,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2111
2166
|
border-radius: 4px;
|
|
2112
2167
|
}
|
|
2113
2168
|
|
|
2114
|
-
.danger-unavailable { margin-top: var(--space-2); opacity: 0.85; }
|
|
2115
|
-
|
|
2116
2169
|
/* Label beside the control, for a settings pane: a column of names on the left
|
|
2117
2170
|
and their controls on the right reads as a list of what is set, where the
|
|
2118
2171
|
same rows stacked read as a form waiting to be filled in. The description
|
|
@@ -2133,8 +2186,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2133
2186
|
controls in the same column at the same indent that do not line up read as
|
|
2134
2187
|
an accident rather than as a pair. */
|
|
2135
2188
|
.field-row > button { min-width: 9ch; }
|
|
2189
|
+
}
|
|
2136
2190
|
|
|
2137
2191
|
/* ---- ./callout.css ---- */
|
|
2192
|
+
@layer components {
|
|
2138
2193
|
/* One shape for everything that tells you something.
|
|
2139
2194
|
`.banner` and `.callout` were the same box drawn twice: a bordered, rounded,
|
|
2140
2195
|
12px panel with a tint. They differed in padding by a pixel in each direction
|
|
@@ -2188,8 +2243,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2188
2243
|
/* A callout that leaves on its own.
|
|
2189
2244
|
Room at the bottom for the bar, and `position: relative` so the bar can sit
|
|
2190
2245
|
on the border rather than inside the text. */
|
|
2191
|
-
.callout-timed { position: relative; padding-bottom: var(--space-5); overflow: hidden; }
|
|
2192
|
-
|
|
2193
2246
|
/* The countdown. Drawn as a shrinking bar rather than a number: nobody wants to
|
|
2194
2247
|
read a clock, they want to know whether they have time. Animated width rather
|
|
2195
2248
|
than a transition, so it starts the moment it is painted. */
|
|
@@ -2250,14 +2303,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2250
2303
|
is the operating system's font drawing a glyph beside an app that has an icon
|
|
2251
2304
|
set for exactly this. The ring went with it: a circle around a warning
|
|
2252
2305
|
triangle is two shapes saying one thing. */
|
|
2253
|
-
.callout-mark {
|
|
2254
|
-
flex: none;
|
|
2255
|
-
display: grid;
|
|
2256
|
-
place-items: center;
|
|
2257
|
-
margin-top: 1px;
|
|
2258
|
-
opacity: 0.9;
|
|
2259
|
-
}
|
|
2260
|
-
|
|
2261
2306
|
/* Held-back history when a local conversation would cross to a hosted model.
|
|
2262
2307
|
Deliberately loud: the cost of missing it is uploading work that was kept
|
|
2263
2308
|
local on purpose. */
|
|
@@ -2273,8 +2318,23 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2273
2318
|
}
|
|
2274
2319
|
|
|
2275
2320
|
.callout button { flex: none; }
|
|
2321
|
+
/* A state, so it stays a class.
|
|
2322
|
+
*
|
|
2323
|
+
* `Callout` applies this as `running ? ' callout-timed' : ''` inside a
|
|
2324
|
+
* template literal -- which is not a class list a rewrite can read, and the
|
|
2325
|
+
* first pass at converting it deleted the rule while leaving the usage. The
|
|
2326
|
+
* box lost five spacing steps of padding and the countdown bar had nothing
|
|
2327
|
+
* to sit in. A class that appears only inside a conditional is a state; the
|
|
2328
|
+
* sheet is where those belong. */
|
|
2329
|
+
.callout-timed {
|
|
2330
|
+
position: relative;
|
|
2331
|
+
padding-bottom: var(--space-5);
|
|
2332
|
+
overflow: hidden;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2276
2335
|
|
|
2277
2336
|
/* ---- ./card.css ---- */
|
|
2337
|
+
@layer components {
|
|
2278
2338
|
/* `.card` is public API, not this component's private styling.
|
|
2279
2339
|
*
|
|
2280
2340
|
* Consumers apply it to their own markup -- the gallery's skeleton specimen
|
|
@@ -2329,16 +2389,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2329
2389
|
which reads as a different column of content. */
|
|
2330
2390
|
.card:has(.card-icon) .card-inline { padding-left: calc(var(--card-icon) + var(--space-3)); }
|
|
2331
2391
|
|
|
2332
|
-
/* Its own line, above the sentence it introduces. */
|
|
2333
|
-
.card-inline-label {
|
|
2334
|
-
display: block;
|
|
2335
|
-
font-size: var(--text-xs);
|
|
2336
|
-
text-transform: uppercase;
|
|
2337
|
-
letter-spacing: 0.04em;
|
|
2338
|
-
color: var(--muted);
|
|
2339
|
-
margin-bottom: 2px;
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
2392
|
.card-title { display: block; font-size: var(--text-base); }
|
|
2343
2393
|
|
|
2344
2394
|
.card-desc { margin-top: var(--space-1); color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
@@ -2416,8 +2466,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2416
2466
|
}
|
|
2417
2467
|
|
|
2418
2468
|
.card[aria-pressed='true']:hover { border-color: var(--accent); }
|
|
2469
|
+
}
|
|
2419
2470
|
|
|
2420
2471
|
/* ---- ./toggle.css ---- */
|
|
2472
|
+
@layer components {
|
|
2421
2473
|
.card-action .switch-row { padding: 0; gap: var(--space-2); }
|
|
2422
2474
|
|
|
2423
2475
|
.card-action .switch-row .switch-body { flex: none; }
|
|
@@ -2474,12 +2526,8 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2474
2526
|
tooltip ended up orphaned under it. */
|
|
2475
2527
|
.set-row > .switch-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
2476
2528
|
|
|
2477
|
-
.switch-label { color: var(--text); }
|
|
2478
|
-
|
|
2479
2529
|
.switch-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
2480
2530
|
|
|
2481
|
-
.switch-said { flex: none; font-size: var(--text-xs); color: var(--muted); }
|
|
2482
|
-
|
|
2483
2531
|
/* Three sizes, the same names every other control uses. The switch scales with
|
|
2484
2532
|
the row: a 30x18 track beside 12px text is a different control from the same
|
|
2485
2533
|
track beside 16px text. */
|
|
@@ -2648,19 +2696,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2648
2696
|
@media (prefers-reduced-motion: reduce) {
|
|
2649
2697
|
.toggle-sweep::before { animation: none; background: color-mix(in oklab, var(--accent) 45%, transparent); }
|
|
2650
2698
|
}
|
|
2651
|
-
|
|
2652
|
-
/* ---- ./skeleton.css ---- */
|
|
2653
|
-
.muted { color: var(--muted); }
|
|
2654
|
-
|
|
2655
|
-
.pulse-block {
|
|
2656
|
-
display: inline-block;
|
|
2657
|
-
height: 8px;
|
|
2658
|
-
border-radius: var(--radius-sm);
|
|
2659
|
-
background: var(--muted);
|
|
2660
|
-
animation: ds-pulse 1.4s ease-in-out infinite;
|
|
2661
|
-
vertical-align: middle;
|
|
2662
2699
|
}
|
|
2663
2700
|
|
|
2701
|
+
/* ---- ./skeleton.css ---- */
|
|
2702
|
+
@layer components {
|
|
2664
2703
|
/* skeletons ------------------------------------------------------------ */
|
|
2665
2704
|
|
|
2666
2705
|
/* Ink at low alpha, not a named surface.
|
|
@@ -2704,8 +2743,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2704
2743
|
/* Still distinguishable from a real block of colour, and still still. */
|
|
2705
2744
|
.skel-pulse { animation: none; opacity: 0.8; }
|
|
2706
2745
|
}
|
|
2746
|
+
}
|
|
2707
2747
|
|
|
2708
2748
|
/* ---- ./rows.css ---- */
|
|
2749
|
+
@layer components {
|
|
2709
2750
|
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2710
2751
|
|
|
2711
2752
|
/* A name and the pills that qualify it, on one line, where the name is the only
|
|
@@ -2917,8 +2958,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2917
2958
|
|
|
2918
2959
|
.rows-split:first-of-type { margin-top: var(--space-2); }
|
|
2919
2960
|
|
|
2920
|
-
.rows-empty { padding: var(--space-3) 0; }
|
|
2921
|
-
|
|
2922
2961
|
/* The name, the pills and the line underneath. `min-width: 0` is the whole
|
|
2923
2962
|
reason this is a class: a flex item will not shrink below its content, so
|
|
2924
2963
|
without it the name pushes the pills off the end -- and the pills are the
|
|
@@ -2935,8 +2974,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2935
2974
|
|
|
2936
2975
|
/* The aligned column. `margin-left: auto` rather than a grid, because the rows
|
|
2937
2976
|
are flex and a size that varies by two characters does not need a track. */
|
|
2938
|
-
.row-trail { flex: none; margin-left: auto; white-space: nowrap; }
|
|
2939
|
-
|
|
2940
2977
|
.rows-row.rows-top { align-items: flex-start; }
|
|
2941
2978
|
|
|
2942
2979
|
.rows-row.rows-bad .truncate { color: var(--bad); }
|
|
@@ -2966,8 +3003,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2966
3003
|
.row-hit:hover .truncate { color: var(--accent); }
|
|
2967
3004
|
|
|
2968
3005
|
.row-hit:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
3006
|
+
}
|
|
2969
3007
|
|
|
2970
3008
|
/* ---- ./progress.css ---- */
|
|
3009
|
+
@layer components {
|
|
2971
3010
|
/* progress ----------------------------------------------------------- */
|
|
2972
3011
|
|
|
2973
3012
|
/* The bar itself: a track with a child it fills, an animation and a
|
|
@@ -3009,8 +3048,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3009
3048
|
/* Still distinguishable from empty, and from full. */
|
|
3010
3049
|
.bar-indeterminate > i { animation: none; width: 100%; opacity: 0.35; }
|
|
3011
3050
|
}
|
|
3051
|
+
}
|
|
3012
3052
|
|
|
3013
3053
|
/* ---- ./tabs.css ---- */
|
|
3054
|
+
@layer components {
|
|
3014
3055
|
/* ---------------------------------------------------------------- tabs */
|
|
3015
3056
|
.tabs { position: relative; display: flex; gap: var(--space-1); }
|
|
3016
3057
|
|
|
@@ -3078,14 +3119,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3078
3119
|
|
|
3079
3120
|
.tabs-vertical .tab.on .tab-label { color: var(--accent); }
|
|
3080
3121
|
|
|
3081
|
-
.tab-hint {
|
|
3082
|
-
display: block;
|
|
3083
|
-
margin-top: 1px;
|
|
3084
|
-
font-size: var(--text-xs);
|
|
3085
|
-
color: var(--muted);
|
|
3086
|
-
line-height: 1.35;
|
|
3087
|
-
}
|
|
3088
|
-
|
|
3089
3122
|
/* A heading above a run of tabs. Set apart from the run above by space, not
|
|
3090
3123
|
a rule -- the rail already has one edge -- and the tabs under it step in
|
|
3091
3124
|
by the label's own padding so the label reads as theirs. */
|
|
@@ -3096,8 +3129,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3096
3129
|
|
|
3097
3130
|
.tabs-vertical .tab-group:first-child { padding-top: var(--space-2); }
|
|
3098
3131
|
|
|
3099
|
-
.tab-group-label { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--text); }
|
|
3100
|
-
|
|
3101
3132
|
.tabs-vertical .tab.in-group { padding-left: var(--space-5); }
|
|
3102
3133
|
|
|
3103
3134
|
/* No line under a vertical strip -- its edge is the border on the right. */
|
|
@@ -3111,8 +3142,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3111
3142
|
}
|
|
3112
3143
|
|
|
3113
3144
|
.tabs-vertical .tab:active:not(:disabled) { border-color: transparent; }
|
|
3145
|
+
}
|
|
3114
3146
|
|
|
3115
3147
|
/* ---- ./toast.css ---- */
|
|
3148
|
+
@layer components {
|
|
3116
3149
|
/* ---------------------------------------------------------------- toasts */
|
|
3117
3150
|
.toasts {
|
|
3118
3151
|
position: fixed;
|
|
@@ -3210,8 +3243,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3210
3243
|
outline: 2px solid var(--accent);
|
|
3211
3244
|
outline-offset: 2px;
|
|
3212
3245
|
}
|
|
3246
|
+
}
|
|
3213
3247
|
|
|
3214
3248
|
/* ---- ./modal.css ---- */
|
|
3249
|
+
@layer components {
|
|
3215
3250
|
/* modal --------------------------------------------------------------- */
|
|
3216
3251
|
|
|
3217
3252
|
/* `hidden` needs saying out loud here. The browser's own `[hidden]` rule is a
|
|
@@ -3303,8 +3338,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3303
3338
|
`<strong>` rule above is the one that sets the size. */
|
|
3304
3339
|
/* Under the title, on the header's padding rather than the body's, so it reads
|
|
3305
3340
|
as part of the heading rather than as the first line of content. */
|
|
3306
|
-
.modal-desc { line-height: 1.5; }
|
|
3307
|
-
|
|
3308
3341
|
.modal-body { padding: var(--space-2) var(--space-4) var(--space-3); overflow-y: auto; }
|
|
3309
3342
|
|
|
3310
3343
|
/* The close cross. Its rule stayed behind in tf's stylesheet when the split
|
|
@@ -3442,8 +3475,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3442
3475
|
.modal.sheet[data-entering],
|
|
3443
3476
|
.modal.sheet[data-exiting] { animation: none; }
|
|
3444
3477
|
}
|
|
3478
|
+
}
|
|
3445
3479
|
|
|
3446
3480
|
/* ---- ./slider.css ---- */
|
|
3481
|
+
@layer components {
|
|
3447
3482
|
/* slider ----------------------------------------------------------------- */
|
|
3448
3483
|
/* A number from a range -- `Slider.tsx` says when one is the right control.
|
|
3449
3484
|
The row is laid out like a switch row: words on the left, the control on the
|
|
@@ -3470,12 +3505,8 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3470
3505
|
|
|
3471
3506
|
.slider-row.is-disabled { opacity: 0.55; }
|
|
3472
3507
|
|
|
3473
|
-
.slider-body { flex: 1 1 260px; min-width: 0; display: grid; gap: 1px; }
|
|
3474
|
-
|
|
3475
3508
|
.set-row > .slider-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
3476
3509
|
|
|
3477
|
-
.slider-label { color: var(--text); }
|
|
3478
|
-
|
|
3479
3510
|
.slider-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
3480
3511
|
|
|
3481
3512
|
/* The box, with the value printed inside it at the right where a select
|
|
@@ -3665,8 +3696,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3665
3696
|
the scale, and the two line up; an explicit `size-*` still wins. */
|
|
3666
3697
|
:where(.set-row) button,
|
|
3667
3698
|
:where(.set-row) .slider-box { font-size: var(--text-xs); }
|
|
3699
|
+
}
|
|
3668
3700
|
|
|
3669
3701
|
/* ---- ./checkbox.css ---- */
|
|
3702
|
+
@layer components {
|
|
3670
3703
|
/* A row you choose. There is no checkbox in it.
|
|
3671
3704
|
Every one of the fourteen in this app sits beside a name and a line of
|
|
3672
3705
|
explanation, so the row was always the thing being designed and the 17px
|
|
@@ -3699,8 +3732,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3699
3732
|
/* A run of checkboxes is one choice, not several settings that happen to be
|
|
3700
3733
|
adjacent. Tight enough that the group reads as a block -- at the spacing a
|
|
3701
3734
|
form field wants, four tools look like four unrelated questions. */
|
|
3702
|
-
.choice-group { display: grid; gap: var(--space-1); }
|
|
3703
|
-
|
|
3704
3735
|
/* The same choice, laid out as tiles instead of a column.
|
|
3705
3736
|
|
|
3706
3737
|
Four short names down the full width of a card is four wide bands for four
|
|
@@ -3824,8 +3855,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3824
3855
|
second line is what the first line is actually asking for. */
|
|
3825
3856
|
.choice-why { display: block; color: var(--muted); font-size: var(--text-sm); margin-top: 1px; }
|
|
3826
3857
|
|
|
3827
|
-
.choice-meta { color: var(--muted); font-size: var(--text-xs); font-family: var(--font-mono); }
|
|
3828
|
-
|
|
3829
3858
|
.choice[data-disabled] {
|
|
3830
3859
|
cursor: not-allowed;
|
|
3831
3860
|
border-color: var(--border);
|
|
@@ -3836,8 +3865,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3836
3865
|
.choice[data-disabled] .choice-why { opacity: 0.5; }
|
|
3837
3866
|
|
|
3838
3867
|
.choice[data-disabled]::after { opacity: 0.4; }
|
|
3868
|
+
}
|
|
3839
3869
|
|
|
3840
3870
|
/* ---- ./table.css ---- */
|
|
3871
|
+
@layer components {
|
|
3841
3872
|
/* A second line under a row's name, inside the `<th scope="row">` that makes it
|
|
3842
3873
|
one. The cell is bold because it is a heading; what hangs under it is not,
|
|
3843
3874
|
and inherited the weight -- so a pinned version read as loud as the thing it
|
|
@@ -3885,27 +3916,48 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3885
3916
|
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3886
3917
|
|
|
3887
3918
|
.data-table thead th[style*='right'] { text-align: right; }
|
|
3919
|
+
}
|
|
3888
3920
|
|
|
3889
3921
|
/* ---- ./sizegrid.css ---- */
|
|
3890
|
-
|
|
3922
|
+
@layer components {
|
|
3923
|
+
/* The cell's colour, all of it, in one place.
|
|
3924
|
+
*
|
|
3925
|
+
* `SizeGrid` draws the cell's geometry with utilities and leaves every colour
|
|
3926
|
+
* here, because `on` and `chosen` override the resting state -- and a utility
|
|
3927
|
+
* is in `@layer utilities`, which beats `@layer components` whatever the
|
|
3928
|
+
* selector. Stated as `surface-panel-2` and `border-border` on the element,
|
|
3929
|
+
* the resting state won permanently and no cell ever lit up.
|
|
3891
3930
|
*
|
|
3892
|
-
*
|
|
3893
|
-
*
|
|
3894
|
-
*
|
|
3895
|
-
|
|
3896
|
-
|
|
3931
|
+
* That is the third time this pattern has bitten: `Select`'s tick and
|
|
3932
|
+
* `Empty`'s figure were the other two. The rule: a resting state whose
|
|
3933
|
+
* active state is a CSS rule has to be a CSS rule too. */
|
|
3934
|
+
.size-cell {
|
|
3935
|
+
border: var(--border-width) solid var(--border);
|
|
3936
|
+
background: var(--panel-2);
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
/* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3940
|
+
when nothing is hovered so the two can never contradict each other. */
|
|
3897
3941
|
.size-cell.on {
|
|
3898
3942
|
border-color: var(--accent);
|
|
3899
3943
|
background: color-mix(in srgb, var(--accent) 45%, transparent);
|
|
3900
3944
|
}
|
|
3901
3945
|
|
|
3946
|
+
.size-cell.chosen { border-color: var(--accent); }
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3902
3949
|
/* ---- ./tooltip.css ---- */
|
|
3950
|
+
@layer components {
|
|
3903
3951
|
/* A callout: something worth knowing, with nothing to answer. Distinct from a
|
|
3904
3952
|
`?`, which is an offer to read more, and from a banner, which is a problem.
|
|
3905
3953
|
The mark is a round `i` rather than an emoji so it takes the theme's colours
|
|
3906
3954
|
and stays the same size as the text beside it. */
|
|
3907
|
-
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3908
|
-
nearly identical to it, which is the whole point of the consolidation
|
|
3955
|
+
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3956
|
+
than nearly identical to it, which is the whole point of the consolidation.
|
|
3957
|
+
(This comment has been unterminated since before the Tailwind branch -- it
|
|
3958
|
+
stops mid-sentence and never closes, so the CSS parser merged it with the
|
|
3959
|
+
one below and recovered. Nothing was lost from the stylesheet; the rest of
|
|
3960
|
+
the sentence was. Closed here rather than guessed at.) */
|
|
3909
3961
|
|
|
3910
3962
|
/* What is left once `Tooltip` draws its own mark: the hover and focus that
|
|
3911
3963
|
reach the mark from its parent, and the tip -- whose closed and open
|
|
@@ -3988,8 +4040,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3988
4040
|
}
|
|
3989
4041
|
|
|
3990
4042
|
.explain-tip strong { color: var(--text); font-weight: 600; }
|
|
4043
|
+
}
|
|
3991
4044
|
|
|
3992
4045
|
/* ---- ./illustration.css ---- */
|
|
4046
|
+
@layer components {
|
|
3993
4047
|
/* illustrations -------------------------------------------------------- */
|
|
3994
4048
|
|
|
3995
4049
|
/* Open Peeps, two colours, wearing whatever the theme is.
|
|
@@ -3997,8 +4051,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3997
4051
|
reason they can live in an app with four palettes: `ink` becomes the current
|
|
3998
4052
|
text colour and `paper` becomes the surface behind it, so one file covers
|
|
3999
4053
|
Night, Paper and both halves of System. Give the wrapper a `color` and
|
|
4000
|
-
the figure follows it
|
|
4001
|
-
one thing on screen worth looking at.
|
|
4054
|
+
the figure follows it: `--muted` for a quiet empty state, `--accent` for the
|
|
4055
|
+
one thing on screen worth looking at. Set that colour on the wrapper --
|
|
4056
|
+
`Empty` reaches for `text-muted`, and any token works. */
|
|
4002
4057
|
.illo {
|
|
4003
4058
|
display: inline-block;
|
|
4004
4059
|
/* Height is the given dimension and the width comes from the drawing, so a
|
|
@@ -4015,20 +4070,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4015
4070
|
caller says otherwise. Not `transparent`: these have overlapping shapes, and
|
|
4016
4071
|
a shirt that lets the arm behind it show through reads as a hole. */
|
|
4017
4072
|
.illo .paper { fill: var(--illo-paper); }
|
|
4018
|
-
|
|
4019
|
-
/* The figure in a whole-surface `Empty`, drawn in the muted grey of the
|
|
4020
|
-
sentence under it.
|
|
4021
|
-
*
|
|
4022
|
-
* A utility cannot do this, and the reason is worth keeping: `.illo` sets
|
|
4023
|
-
* `color: inherit` and is unlayered, while every Tailwind utility lives in
|
|
4024
|
-
* `@layer utilities` -- and an unlayered declaration beats a layered one
|
|
4025
|
-
* whatever the specificity. So `text-muted` on the figure lost, silently,
|
|
4026
|
-
* and the shirt came out full text black beside a muted sentence. The
|
|
4027
|
-
* original rule already carried a note about needing two classes to beat
|
|
4028
|
-
* `.illo`; layers make that impossible rather than merely fiddly. */
|
|
4029
|
-
.nothing-figure { color: var(--muted); }
|
|
4073
|
+
}
|
|
4030
4074
|
|
|
4031
4075
|
/* ---- ./field.css ---- */
|
|
4076
|
+
@layer components {
|
|
4032
4077
|
/* fields --------------------------------------------------------------- */
|
|
4033
4078
|
|
|
4034
4079
|
/* Label, description, input, error -- in the order they are wanted. The
|
|
@@ -4036,7 +4081,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4036
4081
|
to what was typed, so it goes after. */
|
|
4037
4082
|
.field { display: grid; gap: var(--space-1); }
|
|
4038
4083
|
|
|
4039
|
-
|
|
4084
|
+
/* `.field-stack-layout` carries no rules: stacking is what `.field` already
|
|
4085
|
+
does, and the class is emitted only so that both layouts name themselves
|
|
4086
|
+
the same way (`field-${layout}-layout`). Only the row layout overrides. */
|
|
4040
4087
|
|
|
4041
4088
|
.field-row-layout > .field-label { grid-column: 1; }
|
|
4042
4089
|
|
|
@@ -4057,8 +4104,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4057
4104
|
|
|
4058
4105
|
/* Not red. The asterisk marks which fields are required; colouring it the same
|
|
4059
4106
|
as a failure says something has already gone wrong with every one of them. */
|
|
4060
|
-
.field-required { color: var(--muted); }
|
|
4061
|
-
|
|
4062
4107
|
.field-hint,
|
|
4063
4108
|
.field-error { margin: 0; font-size: var(--text-sm); line-height: 1.45; }
|
|
4064
4109
|
|
|
@@ -4080,8 +4125,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4080
4125
|
/* Fields stacked down a form. Wider than the gap inside one field, so the
|
|
4081
4126
|
label of the next belongs to the input under it rather than to the error
|
|
4082
4127
|
above it. */
|
|
4083
|
-
.field-stack { display: grid; gap: var(--space-4); }
|
|
4084
|
-
|
|
4085
4128
|
.field-row > .field { flex: 1; min-width: 0; }
|
|
4086
4129
|
|
|
4087
4130
|
/* A password with an eye -- `Input type="password"`.
|
|
@@ -4203,14 +4246,12 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4203
4246
|
background: var(--panel-2);
|
|
4204
4247
|
color: var(--text);
|
|
4205
4248
|
}
|
|
4249
|
+
}
|
|
4206
4250
|
|
|
4207
4251
|
/* ---- ./tour.css ---- */
|
|
4252
|
+
@layer components {
|
|
4208
4253
|
/* tour ----------------------------------------------------------------- */
|
|
4209
4254
|
|
|
4210
|
-
/* The layer sits over everything and catches nothing: the scrim is painted by
|
|
4211
|
-
the hole's shadow, so there is no full-screen element to swallow a click. */
|
|
4212
|
-
.tour { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
|
|
4213
|
-
|
|
4214
4255
|
/* The control the tour is currently pointing at.
|
|
4215
4256
|
|
|
4216
4257
|
Much of this chrome is invisible until you touch it -- `.view-add` lives at
|
|
@@ -4221,11 +4262,14 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4221
4262
|
what every control does at rest, and the alternative is naming each one here
|
|
4222
4263
|
and watching that list drift from the rules that hide them. One declaration
|
|
4223
4264
|
that outranks whatever the resting state is beats an enumeration that goes
|
|
4224
|
-
stale. It is scoped to a class only ever present on one element at a time.
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4265
|
+
stale. It is scoped to a class only ever present on one element at a time.
|
|
4266
|
+
|
|
4267
|
+
Opacity and nothing else. This forced `color: var(--text)` too, from the
|
|
4268
|
+
original port, with no case on record that needed it -- and it broke the
|
|
4269
|
+
first target that painted its own background, turning a primary button's
|
|
4270
|
+
label dark on accent at 2.2:1. The spotlight makes a control visible; what
|
|
4271
|
+
colour it is at rest is the control's business. */
|
|
4272
|
+
.tour-target { opacity: 1 !important; }
|
|
4229
4273
|
|
|
4230
4274
|
/* The spotlight. An enormous spread shadow dims the whole window except the
|
|
4231
4275
|
rectangle it is drawn on, which needs no clip path and no arithmetic. */
|
|
@@ -4259,19 +4303,19 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4259
4303
|
|
|
4260
4304
|
.tour-card:focus { outline: none; }
|
|
4261
4305
|
|
|
4262
|
-
.tour-title { font-size: var(--text-base); }
|
|
4263
|
-
|
|
4264
4306
|
.tour-body { margin: 0; color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
4265
4307
|
|
|
4266
4308
|
.tour-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
|
|
4267
4309
|
|
|
4268
4310
|
.tour-count { color: var(--muted); font-size: var(--text-xs); }
|
|
4311
|
+
}
|
|
4269
4312
|
|
|
4270
4313
|
/* The mail and forum shell, added in 0.4.0. After the rest, because the
|
|
4271
4314
|
anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
|
|
4272
4315
|
rule of equal specificity that came earlier would lose to whatever the
|
|
4273
4316
|
sheets they cover happen to set. */
|
|
4274
4317
|
/* ---- ./stat.css ---- */
|
|
4318
|
+
@layer components {
|
|
4275
4319
|
/* What the utilities on `Stat` cannot say: a tone on the tile colouring the
|
|
4276
4320
|
figure inside it. An attribute on the parent selecting a child is a
|
|
4277
4321
|
relationship; a utility is a property on one element.
|
|
@@ -4282,8 +4326,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4282
4326
|
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
4283
4327
|
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
4284
4328
|
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
4329
|
+
}
|
|
4285
4330
|
|
|
4286
4331
|
/* ---- ./shell.css ---- */
|
|
4332
|
+
@layer components {
|
|
4287
4333
|
/* The measure, and only the measure.
|
|
4288
4334
|
*
|
|
4289
4335
|
* `Shell` draws itself with utilities -- it is layout and nothing else. What
|
|
@@ -4310,8 +4356,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4310
4356
|
font-size: var(--text-sm);
|
|
4311
4357
|
white-space: nowrap;
|
|
4312
4358
|
}
|
|
4359
|
+
}
|
|
4313
4360
|
|
|
4314
4361
|
/* ---- ./scrollarea.css ---- */
|
|
4362
|
+
@layer components {
|
|
4315
4363
|
/* A box that scrolls, with its edges drawn.
|
|
4316
4364
|
|
|
4317
4365
|
The fades are `::before`/`::after` on the scroller itself, pinned with
|
|
@@ -4404,8 +4452,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4404
4452
|
.scroller.faded::before,
|
|
4405
4453
|
.scroller.faded::after { transition: none; }
|
|
4406
4454
|
}
|
|
4455
|
+
}
|
|
4407
4456
|
|
|
4408
4457
|
/* ---- ./splitpane.css ---- */
|
|
4458
|
+
@layer components {
|
|
4409
4459
|
/* Two panes and the handle between them. */
|
|
4410
4460
|
.split {
|
|
4411
4461
|
display: flex;
|
|
@@ -4424,17 +4474,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4424
4474
|
the intrinsic width of a mail list is the longest unbroken subject line in
|
|
4425
4475
|
it. Without this the handle stops partway across and nothing on screen says
|
|
4426
4476
|
why -- it just refuses, differently for every mailbox. */
|
|
4427
|
-
.split-pane {
|
|
4428
|
-
min-width: 0;
|
|
4429
|
-
min-height: 0;
|
|
4430
|
-
overflow: hidden;
|
|
4431
|
-
display: flex;
|
|
4432
|
-
flex-direction: column;
|
|
4433
|
-
}
|
|
4434
|
-
|
|
4435
|
-
.split-first { flex: 0 0 var(--split); }
|
|
4436
|
-
.split-second { flex: 1 1 0; }
|
|
4437
|
-
|
|
4438
4477
|
/* The handle is wider than it looks: a hairline is a correct-looking divider
|
|
4439
4478
|
and an impossible pointer target. The grip is the line, drawn at
|
|
4440
4479
|
`--border-width` down the middle of a `--space-3` strip, and the strip is
|
|
@@ -4505,8 +4544,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4505
4544
|
@media (prefers-reduced-motion: reduce) {
|
|
4506
4545
|
.split-grip { transition: none; }
|
|
4507
4546
|
}
|
|
4547
|
+
}
|
|
4508
4548
|
|
|
4509
4549
|
/* ---- ./popover.css ---- */
|
|
4550
|
+
@layer components {
|
|
4510
4551
|
/* A small surface anchored to what opened it. Same sheet as the select's list,
|
|
4511
4552
|
because they are the same object -- something that appeared over the page,
|
|
4512
4553
|
attached to a control. */
|
|
@@ -4529,13 +4570,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4529
4570
|
z-index: 60;
|
|
4530
4571
|
}
|
|
4531
4572
|
|
|
4532
|
-
.pop-body {
|
|
4533
|
-
padding: var(--space-3);
|
|
4534
|
-
outline: none;
|
|
4535
|
-
color: var(--text);
|
|
4536
|
-
font-size: var(--text-sm);
|
|
4537
|
-
}
|
|
4538
|
-
|
|
4539
4573
|
/* Entry, and the direction it comes from. `data-placement` is React Aria's,
|
|
4540
4574
|
set to where the surface actually went rather than where it was asked to go,
|
|
4541
4575
|
so the movement agrees with the flip. */
|
|
@@ -4560,8 +4594,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4560
4594
|
.pop[data-entering],
|
|
4561
4595
|
.pop[data-exiting] { animation: none; }
|
|
4562
4596
|
}
|
|
4597
|
+
}
|
|
4563
4598
|
|
|
4564
4599
|
/* ---- ./menu.css ---- */
|
|
4600
|
+
@layer components {
|
|
4565
4601
|
/* What is left once `Menu` draws its sheet and its list: the rows, whose
|
|
4566
4602
|
`data-focused`, `data-pressed` and danger states React Aria stamps on
|
|
4567
4603
|
them, and the rules that reach from a row into what it holds. The
|
|
@@ -4594,8 +4630,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4594
4630
|
.menu-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4595
4631
|
.menu-item[data-focused] .menu-icon { color: var(--text); }
|
|
4596
4632
|
|
|
4597
|
-
.menu-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4598
|
-
.menu-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4599
4633
|
.menu-desc {
|
|
4600
4634
|
font-size: var(--text-xs);
|
|
4601
4635
|
color: var(--muted);
|
|
@@ -4643,8 +4677,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4643
4677
|
}
|
|
4644
4678
|
|
|
4645
4679
|
.menu-sheet { box-shadow: var(--shadow-2); }
|
|
4680
|
+
}
|
|
4646
4681
|
|
|
4647
4682
|
/* ---- ./command.css ---- */
|
|
4683
|
+
@layer components {
|
|
4648
4684
|
/* The command palette: a field over the app and a list under it. */
|
|
4649
4685
|
.cmd-scrim {
|
|
4650
4686
|
position: fixed;
|
|
@@ -4672,18 +4708,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4672
4708
|
flex-direction: column;
|
|
4673
4709
|
}
|
|
4674
4710
|
|
|
4675
|
-
.cmd-body { outline: none; display: flex; flex-direction: column; min-height: 0; }
|
|
4676
|
-
|
|
4677
|
-
.cmd-field {
|
|
4678
|
-
display: flex;
|
|
4679
|
-
align-items: center;
|
|
4680
|
-
gap: var(--space-2);
|
|
4681
|
-
padding: var(--space-3) var(--space-4);
|
|
4682
|
-
border-bottom: var(--border-width) solid var(--border);
|
|
4683
|
-
}
|
|
4684
|
-
|
|
4685
|
-
.cmd-mark { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4686
|
-
|
|
4687
4711
|
/* No border, no focus ring on the input itself: the whole surface is the
|
|
4688
4712
|
field, focus is already in it when it opens, and a ring around a box that
|
|
4689
4713
|
fills the top of the palette is a ring around the palette. */
|
|
@@ -4700,22 +4724,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4700
4724
|
|
|
4701
4725
|
.cmd-input::placeholder { color: var(--muted); }
|
|
4702
4726
|
|
|
4703
|
-
.cmd-list {
|
|
4704
|
-
padding: var(--space-2);
|
|
4705
|
-
overflow: auto;
|
|
4706
|
-
overscroll-behavior: contain;
|
|
4707
|
-
outline: none;
|
|
4708
|
-
min-height: 0;
|
|
4709
|
-
}
|
|
4710
|
-
|
|
4711
|
-
.cmd-group-title {
|
|
4712
|
-
padding: var(--space-2) var(--space-2) var(--space-1);
|
|
4713
|
-
font-size: var(--text-2xs);
|
|
4714
|
-
text-transform: uppercase;
|
|
4715
|
-
letter-spacing: var(--tracking);
|
|
4716
|
-
color: var(--muted);
|
|
4717
|
-
}
|
|
4718
|
-
|
|
4719
4727
|
.cmd-item {
|
|
4720
4728
|
display: flex;
|
|
4721
4729
|
align-items: center;
|
|
@@ -4751,8 +4759,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4751
4759
|
.cmd-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4752
4760
|
.cmd-item[data-focused] .cmd-icon { color: var(--text); }
|
|
4753
4761
|
|
|
4754
|
-
.cmd-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4755
|
-
.cmd-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4756
4762
|
.cmd-desc {
|
|
4757
4763
|
font-size: var(--text-xs);
|
|
4758
4764
|
color: var(--muted);
|
|
@@ -4786,8 +4792,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4786
4792
|
.cmd-scrim[data-exiting],
|
|
4787
4793
|
.cmd[data-entering] { animation: none; }
|
|
4788
4794
|
}
|
|
4795
|
+
}
|
|
4789
4796
|
|
|
4790
4797
|
/* ---- ./pagination.css ---- */
|
|
4798
|
+
@layer components {
|
|
4791
4799
|
/* What is left once `Pagination` draws its own frame: the step and page
|
|
4792
4800
|
buttons, whose hover, focus-visible and current states are pseudo-classes
|
|
4793
4801
|
on two selectors at once, and `.pager-count strong`, which reaches into
|
|
@@ -4906,8 +4914,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4906
4914
|
.pager-page,
|
|
4907
4915
|
.pager-jump { transition: none; }
|
|
4908
4916
|
}
|
|
4917
|
+
}
|
|
4909
4918
|
|
|
4910
4919
|
/* ---- ./identity.css ---- */
|
|
4920
|
+
@layer components {
|
|
4911
4921
|
/* A person, said in one line: initials, name, sometimes the address. */
|
|
4912
4922
|
.ident {
|
|
4913
4923
|
display: inline-flex;
|
|
@@ -4950,25 +4960,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4950
4960
|
font-size: var(--text-2xs);
|
|
4951
4961
|
}
|
|
4952
4962
|
|
|
4953
|
-
.ident-text { display: grid; min-width: 0; }
|
|
4954
|
-
|
|
4955
|
-
.ident-name {
|
|
4956
|
-
overflow: hidden;
|
|
4957
|
-
text-overflow: ellipsis;
|
|
4958
|
-
white-space: nowrap;
|
|
4959
|
-
font-weight: var(--weight);
|
|
4960
|
-
}
|
|
4961
|
-
|
|
4962
|
-
.ident-address {
|
|
4963
|
-
overflow: hidden;
|
|
4964
|
-
text-overflow: ellipsis;
|
|
4965
|
-
white-space: nowrap;
|
|
4966
|
-
font-size: var(--text-xs);
|
|
4967
|
-
color: var(--muted);
|
|
4968
|
-
}
|
|
4969
|
-
|
|
4970
|
-
.ident-aside { flex: none; color: var(--muted); font-size: var(--text-xs); }
|
|
4971
|
-
|
|
4972
4963
|
/* A chip in a composer's To field: boxed, tighter, removable. */
|
|
4973
4964
|
.ident.kind-chip {
|
|
4974
4965
|
gap: var(--space-1);
|
|
@@ -5008,6 +4999,7 @@ body.splitting * { cursor: inherit !important; }
|
|
|
5008
4999
|
|
|
5009
5000
|
.ident-remove:hover { background: var(--panel); color: var(--text); }
|
|
5010
5001
|
.ident-remove:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
5002
|
+
}
|
|
5011
5003
|
/* ---- tf: the themes ---- */
|
|
5012
5004
|
:root[data-theme='night']{--bg:#0f1115;--panel:#161a21;--panel-2:#1c222b;--border:#262d38;--text:#e6e9ef;--muted:#8b94a4;--accent:#5b9dff;--accent-dim:#2a4877;--app-bg:#0f1115;color-scheme:dark}
|
|
5013
5005
|
:root[data-theme='paper']{--bg:#f6f7f9;--panel:#ffffff;--panel-2:#f0f2f5;--border:#e4e8ec;--border-strong:#8792a1;--text:#191d23;--muted:#5d6773;--accent:#0e7872;--accent-dim:#7fbdb8;--on-accent:#ffffff;--good:#1c7a4a;--warn:#8a6216;--bad:#b3312c;--info:#216bc9;--shadow-1:0 4px 14px rgba(16, 24, 40, 0.08);--shadow-2:0 8px 24px rgba(16, 24, 40, 0.10);--shadow-3:0 12px 32px rgba(16, 24, 40, 0.12);--scrim:rgba(16, 24, 40, 0.32);color-scheme:light}
|