@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/valet.css
CHANGED
|
@@ -291,12 +291,9 @@
|
|
|
291
291
|
--font-sans: var(--font-sans);
|
|
292
292
|
--font-mono: var(--font-mono);
|
|
293
293
|
--text-xs: var(--text-xs);
|
|
294
|
-
--text-xs--line-height: inherit;
|
|
295
294
|
--text-sm: var(--text-sm);
|
|
296
|
-
--text-sm--line-height: inherit;
|
|
297
295
|
--text-base: var(--text-base);
|
|
298
296
|
--text-lg: var(--text-lg);
|
|
299
|
-
--text-lg--line-height: inherit;
|
|
300
297
|
--text-xl: var(--text-xl);
|
|
301
298
|
--font-weight-normal: var(--weight);
|
|
302
299
|
--tracking-normal: var(--tracking);
|
|
@@ -311,19 +308,20 @@
|
|
|
311
308
|
--spacing-5: var(--space-5);
|
|
312
309
|
--spacing-6: var(--space-6);
|
|
313
310
|
--spacing-10: var(--space-10);
|
|
314
|
-
--text-2xs--line-height: inherit;
|
|
315
311
|
--text-2xs: var(--text-2xs);
|
|
316
312
|
--text-md: var(--text-md);
|
|
317
313
|
--font-weight-strong: var(--weight-strong);
|
|
318
314
|
--radius-pill: var(--radius-pill);
|
|
319
315
|
--color-text: var(--text);
|
|
320
316
|
--color-muted: var(--muted);
|
|
321
|
-
--color-accent: var(--accent);
|
|
322
317
|
--color-border: var(--border);
|
|
323
318
|
--color-border-strong: var(--border-strong);
|
|
324
319
|
}
|
|
325
320
|
}
|
|
326
321
|
@layer utilities {
|
|
322
|
+
.pointer-events-none {
|
|
323
|
+
pointer-events: none;
|
|
324
|
+
}
|
|
327
325
|
.collapse {
|
|
328
326
|
visibility: collapse;
|
|
329
327
|
}
|
|
@@ -356,6 +354,9 @@
|
|
|
356
354
|
.sticky {
|
|
357
355
|
position: sticky;
|
|
358
356
|
}
|
|
357
|
+
.inset-0 {
|
|
358
|
+
inset: 0px;
|
|
359
|
+
}
|
|
359
360
|
.z-\[60\] {
|
|
360
361
|
z-index: 60;
|
|
361
362
|
}
|
|
@@ -389,12 +390,21 @@
|
|
|
389
390
|
.mt-1 {
|
|
390
391
|
margin-top: var(--spacing-1);
|
|
391
392
|
}
|
|
393
|
+
.mt-2 {
|
|
394
|
+
margin-top: var(--spacing-2);
|
|
395
|
+
}
|
|
396
|
+
.mt-px {
|
|
397
|
+
margin-top: 1px;
|
|
398
|
+
}
|
|
392
399
|
.mb-3 {
|
|
393
400
|
margin-bottom: var(--spacing-3);
|
|
394
401
|
}
|
|
395
402
|
.ml-2 {
|
|
396
403
|
margin-left: var(--spacing-2);
|
|
397
404
|
}
|
|
405
|
+
.ml-auto {
|
|
406
|
+
margin-left: auto;
|
|
407
|
+
}
|
|
398
408
|
.block {
|
|
399
409
|
display: block;
|
|
400
410
|
}
|
|
@@ -419,6 +429,9 @@
|
|
|
419
429
|
.table {
|
|
420
430
|
display: table;
|
|
421
431
|
}
|
|
432
|
+
.h-4 {
|
|
433
|
+
height: var(--spacing-4);
|
|
434
|
+
}
|
|
422
435
|
.h-\[14px\] {
|
|
423
436
|
height: 14px;
|
|
424
437
|
}
|
|
@@ -437,6 +450,9 @@
|
|
|
437
450
|
.min-h-screen {
|
|
438
451
|
min-height: 100vh;
|
|
439
452
|
}
|
|
453
|
+
.w-4 {
|
|
454
|
+
width: var(--spacing-4);
|
|
455
|
+
}
|
|
440
456
|
.w-\[18px\] {
|
|
441
457
|
width: 18px;
|
|
442
458
|
}
|
|
@@ -464,6 +480,18 @@
|
|
|
464
480
|
.flex-1 {
|
|
465
481
|
flex: 1;
|
|
466
482
|
}
|
|
483
|
+
.flex-\[0_0_var\(--split\)\] {
|
|
484
|
+
flex: 0 0 var(--split);
|
|
485
|
+
}
|
|
486
|
+
.flex-\[1_1_0\] {
|
|
487
|
+
flex: 1 1 0;
|
|
488
|
+
}
|
|
489
|
+
.flex-\[1_1_260px\] {
|
|
490
|
+
flex: 1 1 260px;
|
|
491
|
+
}
|
|
492
|
+
.flex-\[1_1_auto\] {
|
|
493
|
+
flex: 1 1 auto;
|
|
494
|
+
}
|
|
467
495
|
.flex-none {
|
|
468
496
|
flex: none;
|
|
469
497
|
}
|
|
@@ -494,6 +522,9 @@
|
|
|
494
522
|
.flex-wrap {
|
|
495
523
|
flex-wrap: wrap;
|
|
496
524
|
}
|
|
525
|
+
.place-items-center {
|
|
526
|
+
place-items: center;
|
|
527
|
+
}
|
|
497
528
|
.items-baseline {
|
|
498
529
|
align-items: baseline;
|
|
499
530
|
}
|
|
@@ -527,6 +558,9 @@
|
|
|
527
558
|
.gap-\[var\(--border-width\)\] {
|
|
528
559
|
gap: var(--border-width);
|
|
529
560
|
}
|
|
561
|
+
.gap-px {
|
|
562
|
+
gap: 1px;
|
|
563
|
+
}
|
|
530
564
|
.self-center {
|
|
531
565
|
align-self: center;
|
|
532
566
|
}
|
|
@@ -574,9 +608,6 @@
|
|
|
574
608
|
--tw-border-style: dashed;
|
|
575
609
|
border-style: dashed;
|
|
576
610
|
}
|
|
577
|
-
.border-accent {
|
|
578
|
-
border-color: var(--color-accent);
|
|
579
|
-
}
|
|
580
611
|
.border-border {
|
|
581
612
|
border-color: var(--color-border);
|
|
582
613
|
}
|
|
@@ -592,9 +623,15 @@
|
|
|
592
623
|
.p-2 {
|
|
593
624
|
padding: var(--spacing-2);
|
|
594
625
|
}
|
|
626
|
+
.p-3 {
|
|
627
|
+
padding: var(--spacing-3);
|
|
628
|
+
}
|
|
595
629
|
.p-4 {
|
|
596
630
|
padding: var(--spacing-4);
|
|
597
631
|
}
|
|
632
|
+
.px-2 {
|
|
633
|
+
padding-inline: var(--spacing-2);
|
|
634
|
+
}
|
|
598
635
|
.px-4 {
|
|
599
636
|
padding-inline: var(--spacing-4);
|
|
600
637
|
}
|
|
@@ -613,6 +650,12 @@
|
|
|
613
650
|
.py-10 {
|
|
614
651
|
padding-block: var(--spacing-10);
|
|
615
652
|
}
|
|
653
|
+
.pt-2 {
|
|
654
|
+
padding-top: var(--spacing-2);
|
|
655
|
+
}
|
|
656
|
+
.pb-1 {
|
|
657
|
+
padding-bottom: var(--spacing-1);
|
|
658
|
+
}
|
|
616
659
|
.pb-2 {
|
|
617
660
|
padding-bottom: var(--spacing-2);
|
|
618
661
|
}
|
|
@@ -627,19 +670,18 @@
|
|
|
627
670
|
}
|
|
628
671
|
.text-2xs {
|
|
629
672
|
font-size: var(--text-2xs);
|
|
630
|
-
|
|
673
|
+
}
|
|
674
|
+
.text-base {
|
|
675
|
+
font-size: var(--text-base);
|
|
631
676
|
}
|
|
632
677
|
.text-lg {
|
|
633
678
|
font-size: var(--text-lg);
|
|
634
|
-
line-height: var(--tw-leading, var(--text-lg--line-height));
|
|
635
679
|
}
|
|
636
680
|
.text-sm {
|
|
637
681
|
font-size: var(--text-sm);
|
|
638
|
-
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
639
682
|
}
|
|
640
683
|
.text-xs {
|
|
641
684
|
font-size: var(--text-xs);
|
|
642
|
-
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
643
685
|
}
|
|
644
686
|
.leading-\[0\] {
|
|
645
687
|
--tw-leading: 0;
|
|
@@ -653,6 +695,10 @@
|
|
|
653
695
|
--tw-leading: 1.25;
|
|
654
696
|
line-height: 1.25;
|
|
655
697
|
}
|
|
698
|
+
.leading-\[1\.35\] {
|
|
699
|
+
--tw-leading: 1.35;
|
|
700
|
+
line-height: 1.35;
|
|
701
|
+
}
|
|
656
702
|
.leading-\[16px\] {
|
|
657
703
|
--tw-leading: 16px;
|
|
658
704
|
line-height: 16px;
|
|
@@ -694,12 +740,12 @@
|
|
|
694
740
|
--tw-numeric-spacing: tabular-nums;
|
|
695
741
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
696
742
|
}
|
|
697
|
-
.opacity-0 {
|
|
698
|
-
opacity: 0%;
|
|
699
|
-
}
|
|
700
743
|
.opacity-60 {
|
|
701
744
|
opacity: 60%;
|
|
702
745
|
}
|
|
746
|
+
.opacity-90 {
|
|
747
|
+
opacity: 90%;
|
|
748
|
+
}
|
|
703
749
|
.opacity-\[0\.55\] {
|
|
704
750
|
opacity: 0.55;
|
|
705
751
|
}
|
|
@@ -739,9 +785,6 @@
|
|
|
739
785
|
.surface-panel {
|
|
740
786
|
background: var(--panel);
|
|
741
787
|
}
|
|
742
|
-
.surface-panel-2 {
|
|
743
|
-
background: var(--panel-2);
|
|
744
|
-
}
|
|
745
788
|
.disabled\:cursor-default:disabled {
|
|
746
789
|
cursor: default;
|
|
747
790
|
}
|
|
@@ -981,7 +1024,19 @@
|
|
|
981
1024
|
}
|
|
982
1025
|
}
|
|
983
1026
|
|
|
984
|
-
/* ---- ./
|
|
1027
|
+
/* ---- ./_system-light.css ---- */
|
|
1028
|
+
/* The `system` theme's light half.
|
|
1029
|
+
*
|
|
1030
|
+
* Its own file, and outside the components layer, because it is a *theme*
|
|
1031
|
+
* rather than a component rule. `tokens.css` states the dark base on `:root`
|
|
1032
|
+
* and is unlayered; the moment this sat inside `@layer components` it lost to
|
|
1033
|
+
* that, and every `system` specimen rendered dark on a light-mode machine.
|
|
1034
|
+
* Unlayered beats layered whatever the selector says, which is exactly the
|
|
1035
|
+
* trap this repository keeps finding in different costumes.
|
|
1036
|
+
*
|
|
1037
|
+
* The underscore marks it the same way `_tailwind.built.css` is marked:
|
|
1038
|
+
* `copy-css.mjs` passes both through without wrapping them.
|
|
1039
|
+
*/
|
|
985
1040
|
/* Light, only under the `system` theme. This used to override `:root`
|
|
986
1041
|
unconditionally, so choosing a dark theme on a light-mode laptop got
|
|
987
1042
|
silently repainted. Every other theme states its own palette. */
|
|
@@ -1010,6 +1065,8 @@
|
|
|
1010
1065
|
}
|
|
1011
1066
|
}
|
|
1012
1067
|
|
|
1068
|
+
/* ---- ./base.css ---- */
|
|
1069
|
+
@layer components {
|
|
1013
1070
|
/* Derived from the two surfaces every theme already defines, so a theme gets a
|
|
1014
1071
|
control colour without knowing this exists. */
|
|
1015
1072
|
/* Pseudo-elements too. `*` does not match them, and `box-sizing` is not
|
|
@@ -1727,23 +1784,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1727
1784
|
template are allowed to diverge, and this is only saying that they have. */
|
|
1728
1785
|
.set-hint.drifted { color: var(--warn); }
|
|
1729
1786
|
|
|
1730
|
-
/* What an applet drew, read back. A tree rather than prose, so it is left as
|
|
1731
|
-
preformatted text and given a ceiling -- a busy applet is a hundred lines and
|
|
1732
|
-
this sits inside a settings pane. */
|
|
1733
|
-
.drawn {
|
|
1734
|
-
margin: var(--space-2) 0 0;
|
|
1735
|
-
padding: var(--space-2) var(--space-2);
|
|
1736
|
-
max-height: 220px;
|
|
1737
|
-
overflow: auto;
|
|
1738
|
-
font-size: var(--text-xs);
|
|
1739
|
-
line-height: 1.45;
|
|
1740
|
-
white-space: pre-wrap;
|
|
1741
|
-
overflow-wrap: anywhere;
|
|
1742
|
-
border: 1px solid var(--border);
|
|
1743
|
-
border-radius: var(--radius);
|
|
1744
|
-
background: var(--panel-2);
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
1787
|
/* One applet, alone on the page, at `/applet/<id>`. Fills the window: there is
|
|
1748
1788
|
no grid here to decide a height, and a screenshot of an applet letterboxed
|
|
1749
1789
|
inside a page is mostly not the applet. */
|
|
@@ -1790,11 +1830,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1790
1830
|
that belongs to a conversation lives here any more, so it can breathe. */
|
|
1791
1831
|
.topbar .ctl-grow { flex: 1; min-width: 0; }
|
|
1792
1832
|
|
|
1793
|
-
/* Back on the left, Next on the right, with the gap between them doing the
|
|
1794
|
-
separating -- so the button that goes forward is in the same place on both
|
|
1795
|
-
pages instead of sliding when Back appears. */
|
|
1796
|
-
.first-run-actions { align-items: center; }
|
|
1797
|
-
|
|
1798
1833
|
@keyframes listening-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }
|
|
1799
1834
|
|
|
1800
1835
|
/* table ---------------------------------------------------------------- */
|
|
@@ -1870,8 +1905,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1870
1905
|
color: var(--muted);
|
|
1871
1906
|
opacity: 1;
|
|
1872
1907
|
}
|
|
1908
|
+
}
|
|
1873
1909
|
|
|
1874
1910
|
/* ---- ./select.css ---- */
|
|
1911
|
+
@layer components {
|
|
1875
1912
|
/* How big a control is, asked for rather than inherited.
|
|
1876
1913
|
Four sizes existed and every one of them came from a descendant selector:
|
|
1877
1914
|
`.set-row button` was 11px in 3px of padding, `.approval-actions button` was
|
|
@@ -1966,16 +2003,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1966
2003
|
/* State is read off React Aria's attributes: `data-open` on the root,
|
|
1967
2004
|
`data-focused` / `data-selected` / `data-disabled` on an item, where
|
|
1968
2005
|
`.open`, `[data-active]`, `.on` and `.off` used to be. */
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
2006
|
+
/* The list keeps two things the utilities on `Select` cannot say.
|
|
2007
|
+
*
|
|
2008
|
+
* `scroll-padding-block`: the same room while the list is scrolled as it has
|
|
2009
|
+
* at rest. Padding at the top of a scroll container scrolls away with the
|
|
2010
|
+
* content, so the row `scrollIntoView({block: 'nearest'})` brings up ended
|
|
2011
|
+
* flush against the border and read as clipped rather than as one of a set --
|
|
2012
|
+
* and this list opens scrolled to whatever is chosen, so that was the
|
|
2013
|
+
* ordinary state.
|
|
2014
|
+
*
|
|
2015
|
+
* `box-shadow`: `--shadow-2` is a token, and a utility would have to inline
|
|
2016
|
+
* the value, which is the one thing the vocabulary exists to stop. */
|
|
2017
|
+
.sel-list {
|
|
1974
2018
|
scroll-padding-block: var(--space-1);
|
|
1975
|
-
list-style: none;
|
|
1976
|
-
border: var(--border-width) solid var(--border-strong);
|
|
1977
|
-
border-radius: var(--radius-md);
|
|
1978
|
-
background: var(--panel);
|
|
1979
2019
|
box-shadow: var(--shadow-2);
|
|
1980
2020
|
}
|
|
1981
2021
|
|
|
@@ -1990,6 +2030,19 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
1990
2030
|
|
|
1991
2031
|
/* The tick marks the chosen row. Colour alone would not: a list where the only
|
|
1992
2032
|
difference is a hue is a list you cannot read past. */
|
|
2033
|
+
/* The tick's resting state lives here, beside the state that overrides it.
|
|
2034
|
+
*
|
|
2035
|
+
* It was `opacity-0` on the element and `opacity: 1` here, which worked only
|
|
2036
|
+
* while this sheet was unlayered. A utility is in `@layer utilities` and
|
|
2037
|
+
* beats `@layer components` whatever the selector, so the moment the sheets
|
|
2038
|
+
* moved into a layer the tick stopped appearing on the selected row -- the
|
|
2039
|
+
* resting state won permanently.
|
|
2040
|
+
*
|
|
2041
|
+
* The rule generalises: a utility for a resting state whose active state is a
|
|
2042
|
+
* relationship between elements will always beat that active state. The pair
|
|
2043
|
+
* has to sit in the same layer. */
|
|
2044
|
+
.sel-tick { opacity: 0; }
|
|
2045
|
+
|
|
1993
2046
|
.sel-item[data-selected] .sel-tick { opacity: 1; }
|
|
1994
2047
|
|
|
1995
2048
|
/* The icon on a speaker's row in the open list -- `Select`'s `aside`. Last in
|
|
@@ -2024,8 +2077,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2024
2077
|
.field > input,
|
|
2025
2078
|
.field > textarea,
|
|
2026
2079
|
.field > .sel { width: 100%; }
|
|
2080
|
+
}
|
|
2027
2081
|
|
|
2028
2082
|
/* ---- ./dangerzone.css ---- */
|
|
2083
|
+
@layer components {
|
|
2029
2084
|
/* Destructive, and legible as such standing still. */
|
|
2030
2085
|
.btn.danger {
|
|
2031
2086
|
color: var(--bad);
|
|
@@ -2115,8 +2170,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2115
2170
|
border-radius: 4px;
|
|
2116
2171
|
}
|
|
2117
2172
|
|
|
2118
|
-
.danger-unavailable { margin-top: var(--space-2); opacity: 0.85; }
|
|
2119
|
-
|
|
2120
2173
|
/* Label beside the control, for a settings pane: a column of names on the left
|
|
2121
2174
|
and their controls on the right reads as a list of what is set, where the
|
|
2122
2175
|
same rows stacked read as a form waiting to be filled in. The description
|
|
@@ -2137,8 +2190,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2137
2190
|
controls in the same column at the same indent that do not line up read as
|
|
2138
2191
|
an accident rather than as a pair. */
|
|
2139
2192
|
.field-row > button { min-width: 9ch; }
|
|
2193
|
+
}
|
|
2140
2194
|
|
|
2141
2195
|
/* ---- ./callout.css ---- */
|
|
2196
|
+
@layer components {
|
|
2142
2197
|
/* One shape for everything that tells you something.
|
|
2143
2198
|
`.banner` and `.callout` were the same box drawn twice: a bordered, rounded,
|
|
2144
2199
|
12px panel with a tint. They differed in padding by a pixel in each direction
|
|
@@ -2192,8 +2247,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2192
2247
|
/* A callout that leaves on its own.
|
|
2193
2248
|
Room at the bottom for the bar, and `position: relative` so the bar can sit
|
|
2194
2249
|
on the border rather than inside the text. */
|
|
2195
|
-
.callout-timed { position: relative; padding-bottom: var(--space-5); overflow: hidden; }
|
|
2196
|
-
|
|
2197
2250
|
/* The countdown. Drawn as a shrinking bar rather than a number: nobody wants to
|
|
2198
2251
|
read a clock, they want to know whether they have time. Animated width rather
|
|
2199
2252
|
than a transition, so it starts the moment it is painted. */
|
|
@@ -2254,14 +2307,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2254
2307
|
is the operating system's font drawing a glyph beside an app that has an icon
|
|
2255
2308
|
set for exactly this. The ring went with it: a circle around a warning
|
|
2256
2309
|
triangle is two shapes saying one thing. */
|
|
2257
|
-
.callout-mark {
|
|
2258
|
-
flex: none;
|
|
2259
|
-
display: grid;
|
|
2260
|
-
place-items: center;
|
|
2261
|
-
margin-top: 1px;
|
|
2262
|
-
opacity: 0.9;
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
2310
|
/* Held-back history when a local conversation would cross to a hosted model.
|
|
2266
2311
|
Deliberately loud: the cost of missing it is uploading work that was kept
|
|
2267
2312
|
local on purpose. */
|
|
@@ -2277,8 +2322,23 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2277
2322
|
}
|
|
2278
2323
|
|
|
2279
2324
|
.callout button { flex: none; }
|
|
2325
|
+
/* A state, so it stays a class.
|
|
2326
|
+
*
|
|
2327
|
+
* `Callout` applies this as `running ? ' callout-timed' : ''` inside a
|
|
2328
|
+
* template literal -- which is not a class list a rewrite can read, and the
|
|
2329
|
+
* first pass at converting it deleted the rule while leaving the usage. The
|
|
2330
|
+
* box lost five spacing steps of padding and the countdown bar had nothing
|
|
2331
|
+
* to sit in. A class that appears only inside a conditional is a state; the
|
|
2332
|
+
* sheet is where those belong. */
|
|
2333
|
+
.callout-timed {
|
|
2334
|
+
position: relative;
|
|
2335
|
+
padding-bottom: var(--space-5);
|
|
2336
|
+
overflow: hidden;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2280
2339
|
|
|
2281
2340
|
/* ---- ./card.css ---- */
|
|
2341
|
+
@layer components {
|
|
2282
2342
|
/* `.card` is public API, not this component's private styling.
|
|
2283
2343
|
*
|
|
2284
2344
|
* Consumers apply it to their own markup -- the gallery's skeleton specimen
|
|
@@ -2333,16 +2393,6 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2333
2393
|
which reads as a different column of content. */
|
|
2334
2394
|
.card:has(.card-icon) .card-inline { padding-left: calc(var(--card-icon) + var(--space-3)); }
|
|
2335
2395
|
|
|
2336
|
-
/* Its own line, above the sentence it introduces. */
|
|
2337
|
-
.card-inline-label {
|
|
2338
|
-
display: block;
|
|
2339
|
-
font-size: var(--text-xs);
|
|
2340
|
-
text-transform: uppercase;
|
|
2341
|
-
letter-spacing: 0.04em;
|
|
2342
|
-
color: var(--muted);
|
|
2343
|
-
margin-bottom: 2px;
|
|
2344
|
-
}
|
|
2345
|
-
|
|
2346
2396
|
.card-title { display: block; font-size: var(--text-base); }
|
|
2347
2397
|
|
|
2348
2398
|
.card-desc { margin-top: var(--space-1); color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
@@ -2420,8 +2470,10 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2420
2470
|
}
|
|
2421
2471
|
|
|
2422
2472
|
.card[aria-pressed='true']:hover { border-color: var(--accent); }
|
|
2473
|
+
}
|
|
2423
2474
|
|
|
2424
2475
|
/* ---- ./toggle.css ---- */
|
|
2476
|
+
@layer components {
|
|
2425
2477
|
.card-action .switch-row { padding: 0; gap: var(--space-2); }
|
|
2426
2478
|
|
|
2427
2479
|
.card-action .switch-row .switch-body { flex: none; }
|
|
@@ -2478,12 +2530,8 @@ input:active, textarea:active, select:active { transform: none; }
|
|
|
2478
2530
|
tooltip ended up orphaned under it. */
|
|
2479
2531
|
.set-row > .switch-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
2480
2532
|
|
|
2481
|
-
.switch-label { color: var(--text); }
|
|
2482
|
-
|
|
2483
2533
|
.switch-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
2484
2534
|
|
|
2485
|
-
.switch-said { flex: none; font-size: var(--text-xs); color: var(--muted); }
|
|
2486
|
-
|
|
2487
2535
|
/* Three sizes, the same names every other control uses. The switch scales with
|
|
2488
2536
|
the row: a 30x18 track beside 12px text is a different control from the same
|
|
2489
2537
|
track beside 16px text. */
|
|
@@ -2652,19 +2700,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2652
2700
|
@media (prefers-reduced-motion: reduce) {
|
|
2653
2701
|
.toggle-sweep::before { animation: none; background: color-mix(in oklab, var(--accent) 45%, transparent); }
|
|
2654
2702
|
}
|
|
2655
|
-
|
|
2656
|
-
/* ---- ./skeleton.css ---- */
|
|
2657
|
-
.muted { color: var(--muted); }
|
|
2658
|
-
|
|
2659
|
-
.pulse-block {
|
|
2660
|
-
display: inline-block;
|
|
2661
|
-
height: 8px;
|
|
2662
|
-
border-radius: var(--radius-sm);
|
|
2663
|
-
background: var(--muted);
|
|
2664
|
-
animation: ds-pulse 1.4s ease-in-out infinite;
|
|
2665
|
-
vertical-align: middle;
|
|
2666
2703
|
}
|
|
2667
2704
|
|
|
2705
|
+
/* ---- ./skeleton.css ---- */
|
|
2706
|
+
@layer components {
|
|
2668
2707
|
/* skeletons ------------------------------------------------------------ */
|
|
2669
2708
|
|
|
2670
2709
|
/* Ink at low alpha, not a named surface.
|
|
@@ -2708,8 +2747,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2708
2747
|
/* Still distinguishable from a real block of colour, and still still. */
|
|
2709
2748
|
.skel-pulse { animation: none; opacity: 0.8; }
|
|
2710
2749
|
}
|
|
2750
|
+
}
|
|
2711
2751
|
|
|
2712
2752
|
/* ---- ./rows.css ---- */
|
|
2753
|
+
@layer components {
|
|
2713
2754
|
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2714
2755
|
|
|
2715
2756
|
/* A name and the pills that qualify it, on one line, where the name is the only
|
|
@@ -2921,8 +2962,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2921
2962
|
|
|
2922
2963
|
.rows-split:first-of-type { margin-top: var(--space-2); }
|
|
2923
2964
|
|
|
2924
|
-
.rows-empty { padding: var(--space-3) 0; }
|
|
2925
|
-
|
|
2926
2965
|
/* The name, the pills and the line underneath. `min-width: 0` is the whole
|
|
2927
2966
|
reason this is a class: a flex item will not shrink below its content, so
|
|
2928
2967
|
without it the name pushes the pills off the end -- and the pills are the
|
|
@@ -2939,8 +2978,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2939
2978
|
|
|
2940
2979
|
/* The aligned column. `margin-left: auto` rather than a grid, because the rows
|
|
2941
2980
|
are flex and a size that varies by two characters does not need a track. */
|
|
2942
|
-
.row-trail { flex: none; margin-left: auto; white-space: nowrap; }
|
|
2943
|
-
|
|
2944
2981
|
.rows-row.rows-top { align-items: flex-start; }
|
|
2945
2982
|
|
|
2946
2983
|
.rows-row.rows-bad .truncate { color: var(--bad); }
|
|
@@ -2970,8 +3007,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
2970
3007
|
.row-hit:hover .truncate { color: var(--accent); }
|
|
2971
3008
|
|
|
2972
3009
|
.row-hit:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
3010
|
+
}
|
|
2973
3011
|
|
|
2974
3012
|
/* ---- ./progress.css ---- */
|
|
3013
|
+
@layer components {
|
|
2975
3014
|
/* progress ----------------------------------------------------------- */
|
|
2976
3015
|
|
|
2977
3016
|
/* The bar itself: a track with a child it fills, an animation and a
|
|
@@ -3013,8 +3052,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3013
3052
|
/* Still distinguishable from empty, and from full. */
|
|
3014
3053
|
.bar-indeterminate > i { animation: none; width: 100%; opacity: 0.35; }
|
|
3015
3054
|
}
|
|
3055
|
+
}
|
|
3016
3056
|
|
|
3017
3057
|
/* ---- ./tabs.css ---- */
|
|
3058
|
+
@layer components {
|
|
3018
3059
|
/* ---------------------------------------------------------------- tabs */
|
|
3019
3060
|
.tabs { position: relative; display: flex; gap: var(--space-1); }
|
|
3020
3061
|
|
|
@@ -3082,14 +3123,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3082
3123
|
|
|
3083
3124
|
.tabs-vertical .tab.on .tab-label { color: var(--accent); }
|
|
3084
3125
|
|
|
3085
|
-
.tab-hint {
|
|
3086
|
-
display: block;
|
|
3087
|
-
margin-top: 1px;
|
|
3088
|
-
font-size: var(--text-xs);
|
|
3089
|
-
color: var(--muted);
|
|
3090
|
-
line-height: 1.35;
|
|
3091
|
-
}
|
|
3092
|
-
|
|
3093
3126
|
/* A heading above a run of tabs. Set apart from the run above by space, not
|
|
3094
3127
|
a rule -- the rail already has one edge -- and the tabs under it step in
|
|
3095
3128
|
by the label's own padding so the label reads as theirs. */
|
|
@@ -3100,8 +3133,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3100
3133
|
|
|
3101
3134
|
.tabs-vertical .tab-group:first-child { padding-top: var(--space-2); }
|
|
3102
3135
|
|
|
3103
|
-
.tab-group-label { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--text); }
|
|
3104
|
-
|
|
3105
3136
|
.tabs-vertical .tab.in-group { padding-left: var(--space-5); }
|
|
3106
3137
|
|
|
3107
3138
|
/* No line under a vertical strip -- its edge is the border on the right. */
|
|
@@ -3115,8 +3146,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3115
3146
|
}
|
|
3116
3147
|
|
|
3117
3148
|
.tabs-vertical .tab:active:not(:disabled) { border-color: transparent; }
|
|
3149
|
+
}
|
|
3118
3150
|
|
|
3119
3151
|
/* ---- ./toast.css ---- */
|
|
3152
|
+
@layer components {
|
|
3120
3153
|
/* ---------------------------------------------------------------- toasts */
|
|
3121
3154
|
.toasts {
|
|
3122
3155
|
position: fixed;
|
|
@@ -3214,8 +3247,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3214
3247
|
outline: 2px solid var(--accent);
|
|
3215
3248
|
outline-offset: 2px;
|
|
3216
3249
|
}
|
|
3250
|
+
}
|
|
3217
3251
|
|
|
3218
3252
|
/* ---- ./modal.css ---- */
|
|
3253
|
+
@layer components {
|
|
3219
3254
|
/* modal --------------------------------------------------------------- */
|
|
3220
3255
|
|
|
3221
3256
|
/* `hidden` needs saying out loud here. The browser's own `[hidden]` rule is a
|
|
@@ -3307,8 +3342,6 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3307
3342
|
`<strong>` rule above is the one that sets the size. */
|
|
3308
3343
|
/* Under the title, on the header's padding rather than the body's, so it reads
|
|
3309
3344
|
as part of the heading rather than as the first line of content. */
|
|
3310
|
-
.modal-desc { line-height: 1.5; }
|
|
3311
|
-
|
|
3312
3345
|
.modal-body { padding: var(--space-2) var(--space-4) var(--space-3); overflow-y: auto; }
|
|
3313
3346
|
|
|
3314
3347
|
/* The close cross. Its rule stayed behind in tf's stylesheet when the split
|
|
@@ -3446,8 +3479,10 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3446
3479
|
.modal.sheet[data-entering],
|
|
3447
3480
|
.modal.sheet[data-exiting] { animation: none; }
|
|
3448
3481
|
}
|
|
3482
|
+
}
|
|
3449
3483
|
|
|
3450
3484
|
/* ---- ./slider.css ---- */
|
|
3485
|
+
@layer components {
|
|
3451
3486
|
/* slider ----------------------------------------------------------------- */
|
|
3452
3487
|
/* A number from a range -- `Slider.tsx` says when one is the right control.
|
|
3453
3488
|
The row is laid out like a switch row: words on the left, the control on the
|
|
@@ -3474,12 +3509,8 @@ input[type='radio']:active:not(:disabled) {
|
|
|
3474
3509
|
|
|
3475
3510
|
.slider-row.is-disabled { opacity: 0.55; }
|
|
3476
3511
|
|
|
3477
|
-
.slider-body { flex: 1 1 260px; min-width: 0; display: grid; gap: 1px; }
|
|
3478
|
-
|
|
3479
3512
|
.set-row > .slider-row { flex: 1; min-width: 0; padding-block: 0; }
|
|
3480
3513
|
|
|
3481
|
-
.slider-label { color: var(--text); }
|
|
3482
|
-
|
|
3483
3514
|
.slider-hint { font-size: var(--text-sm); color: var(--muted); }
|
|
3484
3515
|
|
|
3485
3516
|
/* The box, with the value printed inside it at the right where a select
|
|
@@ -3669,8 +3700,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3669
3700
|
the scale, and the two line up; an explicit `size-*` still wins. */
|
|
3670
3701
|
:where(.set-row) button,
|
|
3671
3702
|
:where(.set-row) .slider-box { font-size: var(--text-xs); }
|
|
3703
|
+
}
|
|
3672
3704
|
|
|
3673
3705
|
/* ---- ./checkbox.css ---- */
|
|
3706
|
+
@layer components {
|
|
3674
3707
|
/* A row you choose. There is no checkbox in it.
|
|
3675
3708
|
Every one of the fourteen in this app sits beside a name and a line of
|
|
3676
3709
|
explanation, so the row was always the thing being designed and the 17px
|
|
@@ -3703,8 +3736,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3703
3736
|
/* A run of checkboxes is one choice, not several settings that happen to be
|
|
3704
3737
|
adjacent. Tight enough that the group reads as a block -- at the spacing a
|
|
3705
3738
|
form field wants, four tools look like four unrelated questions. */
|
|
3706
|
-
.choice-group { display: grid; gap: var(--space-1); }
|
|
3707
|
-
|
|
3708
3739
|
/* The same choice, laid out as tiles instead of a column.
|
|
3709
3740
|
|
|
3710
3741
|
Four short names down the full width of a card is four wide bands for four
|
|
@@ -3828,8 +3859,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3828
3859
|
second line is what the first line is actually asking for. */
|
|
3829
3860
|
.choice-why { display: block; color: var(--muted); font-size: var(--text-sm); margin-top: 1px; }
|
|
3830
3861
|
|
|
3831
|
-
.choice-meta { color: var(--muted); font-size: var(--text-xs); font-family: var(--font-mono); }
|
|
3832
|
-
|
|
3833
3862
|
.choice[data-disabled] {
|
|
3834
3863
|
cursor: not-allowed;
|
|
3835
3864
|
border-color: var(--border);
|
|
@@ -3840,8 +3869,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3840
3869
|
.choice[data-disabled] .choice-why { opacity: 0.5; }
|
|
3841
3870
|
|
|
3842
3871
|
.choice[data-disabled]::after { opacity: 0.4; }
|
|
3872
|
+
}
|
|
3843
3873
|
|
|
3844
3874
|
/* ---- ./table.css ---- */
|
|
3875
|
+
@layer components {
|
|
3845
3876
|
/* A second line under a row's name, inside the `<th scope="row">` that makes it
|
|
3846
3877
|
one. The cell is bold because it is a heading; what hangs under it is not,
|
|
3847
3878
|
and inherited the weight -- so a pinned version read as loud as the thing it
|
|
@@ -3889,27 +3920,48 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3889
3920
|
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
3890
3921
|
|
|
3891
3922
|
.data-table thead th[style*='right'] { text-align: right; }
|
|
3923
|
+
}
|
|
3892
3924
|
|
|
3893
3925
|
/* ---- ./sizegrid.css ---- */
|
|
3894
|
-
|
|
3926
|
+
@layer components {
|
|
3927
|
+
/* The cell's colour, all of it, in one place.
|
|
3928
|
+
*
|
|
3929
|
+
* `SizeGrid` draws the cell's geometry with utilities and leaves every colour
|
|
3930
|
+
* here, because `on` and `chosen` override the resting state -- and a utility
|
|
3931
|
+
* is in `@layer utilities`, which beats `@layer components` whatever the
|
|
3932
|
+
* selector. Stated as `surface-panel-2` and `border-border` on the element,
|
|
3933
|
+
* the resting state won permanently and no cell ever lit up.
|
|
3895
3934
|
*
|
|
3896
|
-
*
|
|
3897
|
-
*
|
|
3898
|
-
*
|
|
3899
|
-
|
|
3900
|
-
|
|
3935
|
+
* That is the third time this pattern has bitten: `Select`'s tick and
|
|
3936
|
+
* `Empty`'s figure were the other two. The rule: a resting state whose
|
|
3937
|
+
* active state is a CSS rule has to be a CSS rule too. */
|
|
3938
|
+
.size-cell {
|
|
3939
|
+
border: var(--border-width) solid var(--border);
|
|
3940
|
+
background: var(--panel-2);
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
/* `on` follows the pointer; `chosen` is what is actually saved, shown only
|
|
3944
|
+
when nothing is hovered so the two can never contradict each other. */
|
|
3901
3945
|
.size-cell.on {
|
|
3902
3946
|
border-color: var(--accent);
|
|
3903
3947
|
background: color-mix(in srgb, var(--accent) 45%, transparent);
|
|
3904
3948
|
}
|
|
3905
3949
|
|
|
3950
|
+
.size-cell.chosen { border-color: var(--accent); }
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3906
3953
|
/* ---- ./tooltip.css ---- */
|
|
3954
|
+
@layer components {
|
|
3907
3955
|
/* A callout: something worth knowing, with nothing to answer. Distinct from a
|
|
3908
3956
|
`?`, which is an offer to read more, and from a banner, which is a problem.
|
|
3909
3957
|
The mark is a round `i` rather than an emoji so it takes the theme's colours
|
|
3910
3958
|
and stays the same size as the text beside it. */
|
|
3911
|
-
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3912
|
-
nearly identical to it, which is the whole point of the consolidation
|
|
3959
|
+
/* An info-toned `.callout`, spelled the old way. Identical to it now rather
|
|
3960
|
+
than nearly identical to it, which is the whole point of the consolidation.
|
|
3961
|
+
(This comment has been unterminated since before the Tailwind branch -- it
|
|
3962
|
+
stops mid-sentence and never closes, so the CSS parser merged it with the
|
|
3963
|
+
one below and recovered. Nothing was lost from the stylesheet; the rest of
|
|
3964
|
+
the sentence was. Closed here rather than guessed at.) */
|
|
3913
3965
|
|
|
3914
3966
|
/* What is left once `Tooltip` draws its own mark: the hover and focus that
|
|
3915
3967
|
reach the mark from its parent, and the tip -- whose closed and open
|
|
@@ -3992,8 +4044,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
3992
4044
|
}
|
|
3993
4045
|
|
|
3994
4046
|
.explain-tip strong { color: var(--text); font-weight: 600; }
|
|
4047
|
+
}
|
|
3995
4048
|
|
|
3996
4049
|
/* ---- ./illustration.css ---- */
|
|
4050
|
+
@layer components {
|
|
3997
4051
|
/* illustrations -------------------------------------------------------- */
|
|
3998
4052
|
|
|
3999
4053
|
/* Open Peeps, two colours, wearing whatever the theme is.
|
|
@@ -4001,8 +4055,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4001
4055
|
reason they can live in an app with four palettes: `ink` becomes the current
|
|
4002
4056
|
text colour and `paper` becomes the surface behind it, so one file covers
|
|
4003
4057
|
Night, Paper and both halves of System. Give the wrapper a `color` and
|
|
4004
|
-
the figure follows it
|
|
4005
|
-
one thing on screen worth looking at.
|
|
4058
|
+
the figure follows it: `--muted` for a quiet empty state, `--accent` for the
|
|
4059
|
+
one thing on screen worth looking at. Set that colour on the wrapper --
|
|
4060
|
+
`Empty` reaches for `text-muted`, and any token works. */
|
|
4006
4061
|
.illo {
|
|
4007
4062
|
display: inline-block;
|
|
4008
4063
|
/* Height is the given dimension and the width comes from the drawing, so a
|
|
@@ -4019,20 +4074,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4019
4074
|
caller says otherwise. Not `transparent`: these have overlapping shapes, and
|
|
4020
4075
|
a shirt that lets the arm behind it show through reads as a hole. */
|
|
4021
4076
|
.illo .paper { fill: var(--illo-paper); }
|
|
4022
|
-
|
|
4023
|
-
/* The figure in a whole-surface `Empty`, drawn in the muted grey of the
|
|
4024
|
-
sentence under it.
|
|
4025
|
-
*
|
|
4026
|
-
* A utility cannot do this, and the reason is worth keeping: `.illo` sets
|
|
4027
|
-
* `color: inherit` and is unlayered, while every Tailwind utility lives in
|
|
4028
|
-
* `@layer utilities` -- and an unlayered declaration beats a layered one
|
|
4029
|
-
* whatever the specificity. So `text-muted` on the figure lost, silently,
|
|
4030
|
-
* and the shirt came out full text black beside a muted sentence. The
|
|
4031
|
-
* original rule already carried a note about needing two classes to beat
|
|
4032
|
-
* `.illo`; layers make that impossible rather than merely fiddly. */
|
|
4033
|
-
.nothing-figure { color: var(--muted); }
|
|
4077
|
+
}
|
|
4034
4078
|
|
|
4035
4079
|
/* ---- ./field.css ---- */
|
|
4080
|
+
@layer components {
|
|
4036
4081
|
/* fields --------------------------------------------------------------- */
|
|
4037
4082
|
|
|
4038
4083
|
/* Label, description, input, error -- in the order they are wanted. The
|
|
@@ -4040,7 +4085,9 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4040
4085
|
to what was typed, so it goes after. */
|
|
4041
4086
|
.field { display: grid; gap: var(--space-1); }
|
|
4042
4087
|
|
|
4043
|
-
|
|
4088
|
+
/* `.field-stack-layout` carries no rules: stacking is what `.field` already
|
|
4089
|
+
does, and the class is emitted only so that both layouts name themselves
|
|
4090
|
+
the same way (`field-${layout}-layout`). Only the row layout overrides. */
|
|
4044
4091
|
|
|
4045
4092
|
.field-row-layout > .field-label { grid-column: 1; }
|
|
4046
4093
|
|
|
@@ -4061,8 +4108,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4061
4108
|
|
|
4062
4109
|
/* Not red. The asterisk marks which fields are required; colouring it the same
|
|
4063
4110
|
as a failure says something has already gone wrong with every one of them. */
|
|
4064
|
-
.field-required { color: var(--muted); }
|
|
4065
|
-
|
|
4066
4111
|
.field-hint,
|
|
4067
4112
|
.field-error { margin: 0; font-size: var(--text-sm); line-height: 1.45; }
|
|
4068
4113
|
|
|
@@ -4084,8 +4129,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4084
4129
|
/* Fields stacked down a form. Wider than the gap inside one field, so the
|
|
4085
4130
|
label of the next belongs to the input under it rather than to the error
|
|
4086
4131
|
above it. */
|
|
4087
|
-
.field-stack { display: grid; gap: var(--space-4); }
|
|
4088
|
-
|
|
4089
4132
|
.field-row > .field { flex: 1; min-width: 0; }
|
|
4090
4133
|
|
|
4091
4134
|
/* A password with an eye -- `Input type="password"`.
|
|
@@ -4207,14 +4250,12 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4207
4250
|
background: var(--panel-2);
|
|
4208
4251
|
color: var(--text);
|
|
4209
4252
|
}
|
|
4253
|
+
}
|
|
4210
4254
|
|
|
4211
4255
|
/* ---- ./tour.css ---- */
|
|
4256
|
+
@layer components {
|
|
4212
4257
|
/* tour ----------------------------------------------------------------- */
|
|
4213
4258
|
|
|
4214
|
-
/* The layer sits over everything and catches nothing: the scrim is painted by
|
|
4215
|
-
the hole's shadow, so there is no full-screen element to swallow a click. */
|
|
4216
|
-
.tour { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
|
|
4217
|
-
|
|
4218
4259
|
/* The control the tour is currently pointing at.
|
|
4219
4260
|
|
|
4220
4261
|
Much of this chrome is invisible until you touch it -- `.view-add` lives at
|
|
@@ -4225,11 +4266,14 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4225
4266
|
what every control does at rest, and the alternative is naming each one here
|
|
4226
4267
|
and watching that list drift from the rules that hide them. One declaration
|
|
4227
4268
|
that outranks whatever the resting state is beats an enumeration that goes
|
|
4228
|
-
stale. It is scoped to a class only ever present on one element at a time.
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4269
|
+
stale. It is scoped to a class only ever present on one element at a time.
|
|
4270
|
+
|
|
4271
|
+
Opacity and nothing else. This forced `color: var(--text)` too, from the
|
|
4272
|
+
original port, with no case on record that needed it -- and it broke the
|
|
4273
|
+
first target that painted its own background, turning a primary button's
|
|
4274
|
+
label dark on accent at 2.2:1. The spotlight makes a control visible; what
|
|
4275
|
+
colour it is at rest is the control's business. */
|
|
4276
|
+
.tour-target { opacity: 1 !important; }
|
|
4233
4277
|
|
|
4234
4278
|
/* The spotlight. An enormous spread shadow dims the whole window except the
|
|
4235
4279
|
rectangle it is drawn on, which needs no clip path and no arithmetic. */
|
|
@@ -4263,19 +4307,19 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4263
4307
|
|
|
4264
4308
|
.tour-card:focus { outline: none; }
|
|
4265
4309
|
|
|
4266
|
-
.tour-title { font-size: var(--text-base); }
|
|
4267
|
-
|
|
4268
4310
|
.tour-body { margin: 0; color: var(--muted); font-size: var(--text-sm); line-height: 1.5; }
|
|
4269
4311
|
|
|
4270
4312
|
.tour-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
|
|
4271
4313
|
|
|
4272
4314
|
.tour-count { color: var(--muted); font-size: var(--text-xs); }
|
|
4315
|
+
}
|
|
4273
4316
|
|
|
4274
4317
|
/* The mail and forum shell, added in 0.4.0. After the rest, because the
|
|
4275
4318
|
anchored surfaces (`.pop`, `.menu-sheet`, `.cmd`) sit over everything and a
|
|
4276
4319
|
rule of equal specificity that came earlier would lose to whatever the
|
|
4277
4320
|
sheets they cover happen to set. */
|
|
4278
4321
|
/* ---- ./stat.css ---- */
|
|
4322
|
+
@layer components {
|
|
4279
4323
|
/* What the utilities on `Stat` cannot say: a tone on the tile colouring the
|
|
4280
4324
|
figure inside it. An attribute on the parent selecting a child is a
|
|
4281
4325
|
relationship; a utility is a property on one element.
|
|
@@ -4286,8 +4330,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4286
4330
|
.stat[data-tone='good'] .stat-value { color: var(--good); }
|
|
4287
4331
|
.stat[data-tone='warn'] .stat-value { color: var(--warn); }
|
|
4288
4332
|
.stat[data-tone='bad'] .stat-value { color: var(--bad); }
|
|
4333
|
+
}
|
|
4289
4334
|
|
|
4290
4335
|
/* ---- ./shell.css ---- */
|
|
4336
|
+
@layer components {
|
|
4291
4337
|
/* The measure, and only the measure.
|
|
4292
4338
|
*
|
|
4293
4339
|
* `Shell` draws itself with utilities -- it is layout and nothing else. What
|
|
@@ -4314,8 +4360,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4314
4360
|
font-size: var(--text-sm);
|
|
4315
4361
|
white-space: nowrap;
|
|
4316
4362
|
}
|
|
4363
|
+
}
|
|
4317
4364
|
|
|
4318
4365
|
/* ---- ./scrollarea.css ---- */
|
|
4366
|
+
@layer components {
|
|
4319
4367
|
/* A box that scrolls, with its edges drawn.
|
|
4320
4368
|
|
|
4321
4369
|
The fades are `::before`/`::after` on the scroller itself, pinned with
|
|
@@ -4408,8 +4456,10 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4408
4456
|
.scroller.faded::before,
|
|
4409
4457
|
.scroller.faded::after { transition: none; }
|
|
4410
4458
|
}
|
|
4459
|
+
}
|
|
4411
4460
|
|
|
4412
4461
|
/* ---- ./splitpane.css ---- */
|
|
4462
|
+
@layer components {
|
|
4413
4463
|
/* Two panes and the handle between them. */
|
|
4414
4464
|
.split {
|
|
4415
4465
|
display: flex;
|
|
@@ -4428,17 +4478,6 @@ input[type='range'].slider:disabled::-moz-range-thumb { opacity: 0; }
|
|
|
4428
4478
|
the intrinsic width of a mail list is the longest unbroken subject line in
|
|
4429
4479
|
it. Without this the handle stops partway across and nothing on screen says
|
|
4430
4480
|
why -- it just refuses, differently for every mailbox. */
|
|
4431
|
-
.split-pane {
|
|
4432
|
-
min-width: 0;
|
|
4433
|
-
min-height: 0;
|
|
4434
|
-
overflow: hidden;
|
|
4435
|
-
display: flex;
|
|
4436
|
-
flex-direction: column;
|
|
4437
|
-
}
|
|
4438
|
-
|
|
4439
|
-
.split-first { flex: 0 0 var(--split); }
|
|
4440
|
-
.split-second { flex: 1 1 0; }
|
|
4441
|
-
|
|
4442
4481
|
/* The handle is wider than it looks: a hairline is a correct-looking divider
|
|
4443
4482
|
and an impossible pointer target. The grip is the line, drawn at
|
|
4444
4483
|
`--border-width` down the middle of a `--space-3` strip, and the strip is
|
|
@@ -4509,8 +4548,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4509
4548
|
@media (prefers-reduced-motion: reduce) {
|
|
4510
4549
|
.split-grip { transition: none; }
|
|
4511
4550
|
}
|
|
4551
|
+
}
|
|
4512
4552
|
|
|
4513
4553
|
/* ---- ./popover.css ---- */
|
|
4554
|
+
@layer components {
|
|
4514
4555
|
/* A small surface anchored to what opened it. Same sheet as the select's list,
|
|
4515
4556
|
because they are the same object -- something that appeared over the page,
|
|
4516
4557
|
attached to a control. */
|
|
@@ -4533,13 +4574,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4533
4574
|
z-index: 60;
|
|
4534
4575
|
}
|
|
4535
4576
|
|
|
4536
|
-
.pop-body {
|
|
4537
|
-
padding: var(--space-3);
|
|
4538
|
-
outline: none;
|
|
4539
|
-
color: var(--text);
|
|
4540
|
-
font-size: var(--text-sm);
|
|
4541
|
-
}
|
|
4542
|
-
|
|
4543
4577
|
/* Entry, and the direction it comes from. `data-placement` is React Aria's,
|
|
4544
4578
|
set to where the surface actually went rather than where it was asked to go,
|
|
4545
4579
|
so the movement agrees with the flip. */
|
|
@@ -4564,8 +4598,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4564
4598
|
.pop[data-entering],
|
|
4565
4599
|
.pop[data-exiting] { animation: none; }
|
|
4566
4600
|
}
|
|
4601
|
+
}
|
|
4567
4602
|
|
|
4568
4603
|
/* ---- ./menu.css ---- */
|
|
4604
|
+
@layer components {
|
|
4569
4605
|
/* What is left once `Menu` draws its sheet and its list: the rows, whose
|
|
4570
4606
|
`data-focused`, `data-pressed` and danger states React Aria stamps on
|
|
4571
4607
|
them, and the rules that reach from a row into what it holds. The
|
|
@@ -4598,8 +4634,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4598
4634
|
.menu-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4599
4635
|
.menu-item[data-focused] .menu-icon { color: var(--text); }
|
|
4600
4636
|
|
|
4601
|
-
.menu-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4602
|
-
.menu-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4603
4637
|
.menu-desc {
|
|
4604
4638
|
font-size: var(--text-xs);
|
|
4605
4639
|
color: var(--muted);
|
|
@@ -4647,8 +4681,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4647
4681
|
}
|
|
4648
4682
|
|
|
4649
4683
|
.menu-sheet { box-shadow: var(--shadow-2); }
|
|
4684
|
+
}
|
|
4650
4685
|
|
|
4651
4686
|
/* ---- ./command.css ---- */
|
|
4687
|
+
@layer components {
|
|
4652
4688
|
/* The command palette: a field over the app and a list under it. */
|
|
4653
4689
|
.cmd-scrim {
|
|
4654
4690
|
position: fixed;
|
|
@@ -4676,18 +4712,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4676
4712
|
flex-direction: column;
|
|
4677
4713
|
}
|
|
4678
4714
|
|
|
4679
|
-
.cmd-body { outline: none; display: flex; flex-direction: column; min-height: 0; }
|
|
4680
|
-
|
|
4681
|
-
.cmd-field {
|
|
4682
|
-
display: flex;
|
|
4683
|
-
align-items: center;
|
|
4684
|
-
gap: var(--space-2);
|
|
4685
|
-
padding: var(--space-3) var(--space-4);
|
|
4686
|
-
border-bottom: var(--border-width) solid var(--border);
|
|
4687
|
-
}
|
|
4688
|
-
|
|
4689
|
-
.cmd-mark { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4690
|
-
|
|
4691
4715
|
/* No border, no focus ring on the input itself: the whole surface is the
|
|
4692
4716
|
field, focus is already in it when it opens, and a ring around a box that
|
|
4693
4717
|
fills the top of the palette is a ring around the palette. */
|
|
@@ -4704,22 +4728,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4704
4728
|
|
|
4705
4729
|
.cmd-input::placeholder { color: var(--muted); }
|
|
4706
4730
|
|
|
4707
|
-
.cmd-list {
|
|
4708
|
-
padding: var(--space-2);
|
|
4709
|
-
overflow: auto;
|
|
4710
|
-
overscroll-behavior: contain;
|
|
4711
|
-
outline: none;
|
|
4712
|
-
min-height: 0;
|
|
4713
|
-
}
|
|
4714
|
-
|
|
4715
|
-
.cmd-group-title {
|
|
4716
|
-
padding: var(--space-2) var(--space-2) var(--space-1);
|
|
4717
|
-
font-size: var(--text-2xs);
|
|
4718
|
-
text-transform: uppercase;
|
|
4719
|
-
letter-spacing: var(--tracking);
|
|
4720
|
-
color: var(--muted);
|
|
4721
|
-
}
|
|
4722
|
-
|
|
4723
4731
|
.cmd-item {
|
|
4724
4732
|
display: flex;
|
|
4725
4733
|
align-items: center;
|
|
@@ -4755,8 +4763,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4755
4763
|
.cmd-icon { flex: none; width: var(--space-4); height: var(--space-4); color: var(--muted); }
|
|
4756
4764
|
.cmd-item[data-focused] .cmd-icon { color: var(--text); }
|
|
4757
4765
|
|
|
4758
|
-
.cmd-text { flex: 1 1 auto; min-width: 0; display: grid; }
|
|
4759
|
-
.cmd-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
4760
4766
|
.cmd-desc {
|
|
4761
4767
|
font-size: var(--text-xs);
|
|
4762
4768
|
color: var(--muted);
|
|
@@ -4790,8 +4796,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4790
4796
|
.cmd-scrim[data-exiting],
|
|
4791
4797
|
.cmd[data-entering] { animation: none; }
|
|
4792
4798
|
}
|
|
4799
|
+
}
|
|
4793
4800
|
|
|
4794
4801
|
/* ---- ./pagination.css ---- */
|
|
4802
|
+
@layer components {
|
|
4795
4803
|
/* What is left once `Pagination` draws its own frame: the step and page
|
|
4796
4804
|
buttons, whose hover, focus-visible and current states are pseudo-classes
|
|
4797
4805
|
on two selectors at once, and `.pager-count strong`, which reaches into
|
|
@@ -4910,8 +4918,10 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4910
4918
|
.pager-page,
|
|
4911
4919
|
.pager-jump { transition: none; }
|
|
4912
4920
|
}
|
|
4921
|
+
}
|
|
4913
4922
|
|
|
4914
4923
|
/* ---- ./identity.css ---- */
|
|
4924
|
+
@layer components {
|
|
4915
4925
|
/* A person, said in one line: initials, name, sometimes the address. */
|
|
4916
4926
|
.ident {
|
|
4917
4927
|
display: inline-flex;
|
|
@@ -4954,25 +4964,6 @@ body.splitting * { cursor: inherit !important; }
|
|
|
4954
4964
|
font-size: var(--text-2xs);
|
|
4955
4965
|
}
|
|
4956
4966
|
|
|
4957
|
-
.ident-text { display: grid; min-width: 0; }
|
|
4958
|
-
|
|
4959
|
-
.ident-name {
|
|
4960
|
-
overflow: hidden;
|
|
4961
|
-
text-overflow: ellipsis;
|
|
4962
|
-
white-space: nowrap;
|
|
4963
|
-
font-weight: var(--weight);
|
|
4964
|
-
}
|
|
4965
|
-
|
|
4966
|
-
.ident-address {
|
|
4967
|
-
overflow: hidden;
|
|
4968
|
-
text-overflow: ellipsis;
|
|
4969
|
-
white-space: nowrap;
|
|
4970
|
-
font-size: var(--text-xs);
|
|
4971
|
-
color: var(--muted);
|
|
4972
|
-
}
|
|
4973
|
-
|
|
4974
|
-
.ident-aside { flex: none; color: var(--muted); font-size: var(--text-xs); }
|
|
4975
|
-
|
|
4976
4967
|
/* A chip in a composer's To field: boxed, tighter, removable. */
|
|
4977
4968
|
.ident.kind-chip {
|
|
4978
4969
|
gap: var(--space-1);
|
|
@@ -5012,6 +5003,7 @@ body.splitting * { cursor: inherit !important; }
|
|
|
5012
5003
|
|
|
5013
5004
|
.ident-remove:hover { background: var(--panel); color: var(--text); }
|
|
5014
5005
|
.ident-remove:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
5006
|
+
}
|
|
5015
5007
|
/* ---- valet: the themes ---- */
|
|
5016
5008
|
:root[data-theme='valet']{--bg:#f4f5f8;--panel:#ffffff;--panel-2:#eceef3;--border:#dcdfe7;--border-strong:#7b8597;--text:#171a21;--muted:#5b6474;--accent:#4f46e5;--accent-dim:#a9a4f0;--on-accent:#ffffff;--good:#1b7f4b;--warn:#8a5f0a;--bad:#bf3a31;--info:#0e6f8e;--app-bg:#f4f5f8;--shadow-1:0 4px 14px rgba(23, 26, 33, 0.08);--shadow-2:0 8px 24px rgba(23, 26, 33, 0.10);--shadow-3:0 12px 32px rgba(23, 26, 33, 0.12);--scrim:rgba(23, 26, 33, 0.32);color-scheme:light}
|
|
5017
5009
|
:root[data-theme='valet-night']{--bg:#0c0f14;--panel:#141820;--panel-2:#1b2029;--border:#262c37;--border-strong:#616b7d;--text:#e8eaf0;--muted:#9ba4b5;--accent:#8f88ff;--accent-dim:#3f3a8f;--on-accent:#0d0b2e;--good:#5fcb8f;--warn:#e2ae58;--bad:#f28b84;--info:#57c4e8;--app-bg:#0c0f14;--shadow-1:0 6px 20px rgba(0, 0, 0, 0.28);--shadow-2:0 8px 28px rgba(0, 0, 0, 0.34);--shadow-3:0 10px 34px rgba(0, 0, 0, 0.38);--scrim:rgba(0, 0, 0, 0.5);color-scheme:dark}
|