@slotted/styles 0.1.0-beta.2 → 0.1.0-beta.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slotted/styles",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.0-beta.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -460,7 +460,18 @@
460
460
  * for fifty pixels stood at whatever the longest destination measured.
461
461
  */
462
462
  min-inline-size: 0;
463
- overflow: hidden;
463
+ /**
464
+ * The inline axis clips, which the width transition between open and rail
465
+ * needs. The block axis scrolls: a region holding one column taller than
466
+ * itself instead of `nav-header`, `nav-body` and `nav-footer` keeps its
467
+ * foot reachable. With the three parts the body scrolls and the region
468
+ * never overflows.
469
+ */
470
+ overflow-x: hidden;
471
+ overflow-y: auto;
472
+ overflow-inline: hidden;
473
+ overflow-block: auto;
474
+ overscroll-behavior: contain;
464
475
  transition:
465
476
  inline-size var(--_duration) var(--_easing),
466
477
  visibility var(--_duration) step-start;
@@ -158,6 +158,19 @@
158
158
  --_edge: var(--_solid-active);
159
159
  }
160
160
 
161
+ /**
162
+ * Ink: the theme's `neutral` tone fills with the inverse surface and labels
163
+ * with the inverse text. A product that keeps the accent for data draws its
164
+ * primary action in it.
165
+ */
166
+ [data-ui='button'][data-tone='neutral'] {
167
+ --_solid: var(--slotted-tone-neutral-solid);
168
+ --_solid-hover: var(--slotted-tone-neutral-solid-hover);
169
+ --_solid-active: var(--slotted-tone-neutral-solid-active);
170
+ --_on-solid: var(--slotted-tone-neutral-on-solid);
171
+ --_text: var(--slotted-tone-neutral-text);
172
+ }
173
+
161
174
  [data-ui='button'][data-tone='success'] {
162
175
  --_solid: var(--slotted-tone-success-solid);
163
176
  --_solid-hover: var(--slotted-tone-success-solid-hover);
@@ -681,6 +694,26 @@
681
694
  inline-size: 100%;
682
695
  }
683
696
 
697
+ /**
698
+ * A field trigger: the label at the start and `end` at the inline end. The
699
+ * label takes the free space, so `start` stays beside it and the end slot is
700
+ * pushed to the edge; flex follows the writing direction, so it mirrors.
701
+ */
702
+ [data-ui='button'][data-justify='between'] {
703
+ justify-content: space-between;
704
+ }
705
+
706
+ [data-ui='button'][data-justify='between'] > [data-part='label'] {
707
+ flex: 1 1 auto;
708
+ text-align: start;
709
+ }
710
+
711
+ /* What a trigger holds at its end — a shortcut, a count — is as wide as it is. */
712
+ [data-ui='button'][data-justify='between'] > [data-part='end'] {
713
+ inline-size: auto;
714
+ min-inline-size: var(--_icon-size);
715
+ }
716
+
684
717
  /**
685
718
  * An icon-only control is square from the control height, so its visual box
686
719
  * and its target are the same box. The two minimums are the WCAG 2.2 floor
@@ -52,6 +52,11 @@
52
52
  "--slotted-tone-danger-solid-active",
53
53
  "--slotted-tone-danger-solid-hover",
54
54
  "--slotted-tone-danger-text",
55
+ "--slotted-tone-neutral-on-solid",
56
+ "--slotted-tone-neutral-solid",
57
+ "--slotted-tone-neutral-solid-active",
58
+ "--slotted-tone-neutral-solid-hover",
59
+ "--slotted-tone-neutral-text",
55
60
  "--slotted-tone-secondary-on-solid",
56
61
  "--slotted-tone-secondary-solid",
57
62
  "--slotted-tone-secondary-solid-active",
@@ -341,6 +341,10 @@
341
341
  --_seam: var(--slotted-tone-secondary-solid-active);
342
342
  }
343
343
 
344
+ [data-ui='button-group'] > [data-tone='neutral'] {
345
+ --_seam: var(--slotted-tone-neutral-solid-active);
346
+ }
347
+
344
348
  [data-ui='button-group'] > [data-tone='success'] {
345
349
  --_seam: var(--slotted-tone-success-solid-active);
346
350
  }
@@ -5,6 +5,7 @@
5
5
  "--slotted-text-muted",
6
6
  "--slotted-tone-accent-solid-active",
7
7
  "--slotted-tone-danger-solid-active",
8
+ "--slotted-tone-neutral-solid-active",
8
9
  "--slotted-tone-secondary-solid-active",
9
10
  "--slotted-tone-success-solid-active",
10
11
  "--slotted-tone-warning-solid-active"
@@ -877,6 +877,13 @@
877
877
  overflow-wrap: anywhere;
878
878
  }
879
879
 
880
+ /* The label of a line on this category, the plot's own words for it. */
881
+ [data-ui='chart'] [data-part='tooltip-note'] {
882
+ color: var(--slotted-text-muted, GrayText);
883
+ grid-column: 1 / -1;
884
+ overflow-wrap: anywhere;
885
+ }
886
+
880
887
  [data-ui='chart'] :is([data-part='tooltip-item'], [data-part='tooltip-total']) {
881
888
  align-items: center;
882
889
  display: grid;
@@ -784,4 +784,128 @@
784
784
  [data-ui='currency-field'][data-part='root'][data-disabled] > [data-part='end'] {
785
785
  color: var(--slotted-disabled-foreground);
786
786
  }
787
+
788
+ /**
789
+ * ── The display step ───────────────────────────────────────────────────
790
+ *
791
+ * The headline amount of an entry sheet: the figure at the 4xl step in
792
+ * tabular figures with the tighter tracking large type takes, and the
793
+ * currency's mark apart from it, muted at the xl step and on the baseline
794
+ * of the digits. Where the platform sizes a field to its content the
795
+ * control is as wide as the amount it holds, so the mark stays beside the
796
+ * digits; elsewhere the control takes the line and `align` places the
797
+ * amount in it.
798
+ */
799
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] {
800
+ --_font-size: var(
801
+ --slotted-currency-field-display-font-size,
802
+ var(--slotted-font-size-4xl, 2rem)
803
+ );
804
+ --_height: calc(
805
+ var(--_font-size) * var(--slotted-line-height-4xl, 1.2) + 2 * var(--slotted-space-2, 0.25rem)
806
+ );
807
+ --_padding-inline: var(--slotted-control-padding-inline-lg, 16px);
808
+ --_gap: var(--slotted-space-3, 0.375rem);
809
+
810
+ align-items: baseline;
811
+ font-weight: var(--slotted-font-weight-medium, 500);
812
+ letter-spacing: var(--slotted-letter-spacing-tighter, -0.03em);
813
+ line-height: var(--slotted-line-height-4xl, 1.2);
814
+ }
815
+
816
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] > [data-part='symbol'] {
817
+ color: var(--slotted-currency-field-symbol-color, var(--slotted-text-muted, GrayText));
818
+ flex: none;
819
+ font-size: var(
820
+ --slotted-currency-field-symbol-font-size,
821
+ var(--slotted-font-size-xl, 1.125rem)
822
+ );
823
+ font-weight: var(--slotted-font-weight-regular, 400);
824
+ letter-spacing: 0;
825
+ }
826
+
827
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] > [data-part='input'] {
828
+ align-self: auto;
829
+ margin-block: 0;
830
+ }
831
+
832
+ @supports (field-sizing: content) {
833
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] {
834
+ inline-size: fit-content;
835
+ max-inline-size: 100%;
836
+ }
837
+
838
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] > [data-part='input'] {
839
+ field-sizing: content;
840
+ flex: 0 1 auto;
841
+ min-inline-size: 1ch;
842
+ }
843
+ }
844
+
845
+ /**
846
+ * No box: a rule under the amount. On focus the rule takes the text colour
847
+ * and doubles, which is the focus indicator; invalid, it takes the danger
848
+ * colour. No ground, no corner and no resting lift.
849
+ */
850
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] {
851
+ background-color: transparent;
852
+ border-color: transparent;
853
+ border-block-end-color: var(
854
+ --slotted-currency-field-underline-color,
855
+ var(--slotted-control-border-color, ButtonBorder)
856
+ );
857
+ border-radius: var(--slotted-radius-none, 0px);
858
+ box-shadow: none;
859
+ padding-inline: 0;
860
+ }
861
+
862
+ [data-ui='currency-field'][data-part='root'][data-appearance='display']:has(
863
+ > [data-part='input']:focus-visible
864
+ ) {
865
+ border-block-end-color: var(--slotted-text, CanvasText);
866
+ box-shadow: inset 0 calc(-1 * var(--slotted-border-width-thin, 1px)) 0
867
+ var(--slotted-text, CanvasText);
868
+ outline: none;
869
+ }
870
+
871
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'][data-invalid] {
872
+ border-block-end-color: var(--slotted-tone-danger-border, CanvasText);
873
+ box-shadow: none;
874
+ }
875
+
876
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'][data-invalid]:has(
877
+ > [data-part='input']:focus-visible
878
+ ) {
879
+ box-shadow: inset 0 calc(-1 * var(--_invalid-edge-width)) 0 var(--_invalid-edge-color);
880
+ }
881
+
882
+ [data-ui='currency-field'][data-part='root'][data-appearance='display']:has(
883
+ > [data-part='input']:disabled
884
+ ) {
885
+ border-block-end-color: var(--slotted-disabled-border, GrayText);
886
+ }
887
+
888
+ @media (forced-colors: active) {
889
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'] {
890
+ border-block-end-color: ButtonBorder;
891
+ }
892
+
893
+ /* A shadow is not painted under forced colours, so the doubled rule of
894
+ focus is a wider border there. */
895
+ [data-ui='currency-field'][data-part='root'][data-appearance='display']:has(
896
+ > [data-part='input']:focus-visible
897
+ ) {
898
+ border-block-end-color: Highlight;
899
+ border-block-end-width: calc(2 * var(--slotted-border-width-thin, 1px));
900
+ }
901
+
902
+ [data-ui='currency-field'][data-part='root'][data-appearance='display'][data-invalid]:has(
903
+ > [data-part='input']:focus-visible
904
+ ) {
905
+ border-block-end-color: Highlight;
906
+ border-block-end-width: calc(
907
+ var(--slotted-border-width-thin, 1px) + var(--_invalid-edge-width)
908
+ );
909
+ }
910
+ }
787
911
  }
@@ -1,5 +1,6 @@
1
1
  [
2
2
  "--slotted-border-subtle",
3
+ "--slotted-border-width-thin",
3
4
  "--slotted-control-border-color",
4
5
  "--slotted-control-border-width",
5
6
  "--slotted-control-font-family",
@@ -36,6 +37,7 @@
36
37
  "--slotted-currency-field-disabled-background",
37
38
  "--slotted-currency-field-disabled-border-color",
38
39
  "--slotted-currency-field-disabled-color",
40
+ "--slotted-currency-field-display-font-size",
39
41
  "--slotted-currency-field-hover-border-color",
40
42
  "--slotted-currency-field-icon-size-min",
41
43
  "--slotted-currency-field-invalid-border-color",
@@ -57,6 +59,9 @@
57
59
  "--slotted-currency-field-subtle-background",
58
60
  "--slotted-currency-field-subtle-border-color",
59
61
  "--slotted-currency-field-subtle-hover-background",
62
+ "--slotted-currency-field-symbol-color",
63
+ "--slotted-currency-field-symbol-font-size",
64
+ "--slotted-currency-field-underline-color",
60
65
  "--slotted-disabled-background",
61
66
  "--slotted-disabled-border",
62
67
  "--slotted-disabled-foreground",
@@ -64,10 +69,17 @@
64
69
  "--slotted-focus-ring-color-invalid",
65
70
  "--slotted-focus-ring-offset",
66
71
  "--slotted-focus-ring-width",
72
+ "--slotted-font-size-4xl",
73
+ "--slotted-font-size-xl",
74
+ "--slotted-font-weight-medium",
75
+ "--slotted-font-weight-regular",
76
+ "--slotted-letter-spacing-tighter",
77
+ "--slotted-line-height-4xl",
67
78
  "--slotted-radius-none",
68
79
  "--slotted-radius-xs",
69
80
  "--slotted-space-1",
70
81
  "--slotted-space-2",
82
+ "--slotted-space-3",
71
83
  "--slotted-surface-sunken",
72
84
  "--slotted-target-comfortable",
73
85
  "--slotted-target-min",
@@ -52,8 +52,12 @@
52
52
  --_measure: var(--slotted-dialog-measure, 32rem);
53
53
  /** The air between the panel and the edge of the layer. */
54
54
  --_layer-padding: var(--slotted-space-8, 1.5rem);
55
- /** The panel's own inset, which every row reads. */
56
- --_padding-inline: var(--slotted-space-8, 1.5rem);
55
+ /**
56
+ * The panel's own inset, which every row reads. The panel draws none of it
57
+ * itself: the header, the body and the footer carry it, and a layout of the
58
+ * consumer's own that skips them reads the same two public tokens.
59
+ */
60
+ --_padding-inline: var(--slotted-dialog-padding-inline, var(--slotted-space-8, 1.5rem));
57
61
  /**
58
62
  * Three insets, not one number used three times, because the three rows
59
63
  * hold three different things.
@@ -72,7 +76,7 @@
72
76
  * paragraph reads as a slab around a button: twenty above and below a
73
77
  * thirty-four pixel control is a seventy-four pixel bar for one line.
74
78
  */
75
- --_padding-block: var(--slotted-space-7, 1.25rem);
79
+ --_padding-block: var(--slotted-dialog-padding-block, var(--slotted-space-7, 1.25rem));
76
80
  --_header-padding-block: var(--slotted-space-6, 1rem);
77
81
  --_footer-padding-block: var(--slotted-space-5, 0.75rem);
78
82
  --_gap: var(--slotted-space-5, 0.75rem);
@@ -182,8 +186,8 @@
182
186
 
183
187
  [data-ui='dialog'][data-size='sm'] {
184
188
  --_measure: var(--slotted-dialog-measure, 24rem);
185
- --_padding-inline: var(--slotted-space-7, 1.25rem);
186
- --_padding-block: var(--slotted-space-6, 1rem);
189
+ --_padding-inline: var(--slotted-dialog-padding-inline-sm, var(--slotted-space-7, 1.25rem));
190
+ --_padding-block: var(--slotted-dialog-padding-block-sm, var(--slotted-space-6, 1rem));
187
191
  --_header-padding-block: var(--slotted-space-5, 0.75rem);
188
192
  --_footer-padding-block: var(--slotted-space-4, 0.5rem);
189
193
  --_title-font-size: var(--slotted-font-size-lg, 1rem);
@@ -281,6 +285,15 @@
281
285
  /* ── The panel ────────────────────────────────────────────────────────── */
282
286
 
283
287
  [data-ui='dialog'] > [data-part='viewport'] > [data-part='content'] {
288
+ /**
289
+ * The inset the rows carry, stated where a layout of the consumer's own can
290
+ * read it: the panel draws no padding, so content written straight inside
291
+ * it reads `--slotted-dialog-inset-inline` for its padding and stands
292
+ * in the column the header, the body and the footer stand in.
293
+ */
294
+ --slotted-dialog-inset-inline: var(--_padding-inline);
295
+ --slotted-dialog-inset-block: var(--_padding-block);
296
+
284
297
  display: grid;
285
298
  grid-template-rows: auto minmax(0, 1fr) auto;
286
299
  inline-size: 100%;
@@ -17,6 +17,10 @@
17
17
  "--slotted-dialog-description-color",
18
18
  "--slotted-dialog-footer-surface",
19
19
  "--slotted-dialog-measure",
20
+ "--slotted-dialog-padding-block",
21
+ "--slotted-dialog-padding-block-sm",
22
+ "--slotted-dialog-padding-inline",
23
+ "--slotted-dialog-padding-inline-sm",
20
24
  "--slotted-dialog-radius",
21
25
  "--slotted-dialog-rule-color",
22
26
  "--slotted-dialog-scrim",
package/src/list/list.css CHANGED
@@ -193,6 +193,33 @@
193
193
  * level is the library's own sticky step, so a heading never rises above an
194
194
  * overlay that is above the page.
195
195
  */
196
+ /* A heading with an end sets the name at the start and the end content on
197
+ the same line, at the end. */
198
+ [data-ui='list'] [data-part='section-label']:has(> [data-part='section-end']) {
199
+ align-items: baseline;
200
+ display: flex;
201
+ gap: var(--slotted-space-4, 0.5rem);
202
+ justify-content: space-between;
203
+ }
204
+
205
+ [data-ui='list'] [data-part='section-end'] {
206
+ flex: none;
207
+ font-variant-numeric: tabular-nums;
208
+ white-space: nowrap;
209
+ }
210
+
211
+ /**
212
+ * `ruled`: the name in the text colour over a rule, with no ground behind it
213
+ * — a day of a phone list with its balance at the end. The sticky ground is
214
+ * still the set's surface, so the rows passing under it are covered.
215
+ */
216
+ [data-ui='list'] [data-part='section-label'][data-variant='ruled'] {
217
+ border-block-end: var(--slotted-border-width-thin, 1px) solid
218
+ var(--slotted-list-section-rule-color, var(--slotted-border-subtle, GrayText));
219
+ color: var(--slotted-list-section-ruled-color, var(--slotted-text, CanvasText));
220
+ font-weight: var(--slotted-font-weight-medium, 500);
221
+ }
222
+
196
223
  [data-ui='list'] [data-part='section-label'][data-sticky] {
197
224
  background-color: var(--_surface);
198
225
  inset-block-start: 0;
@@ -5,6 +5,7 @@
5
5
  "--slotted-control-padding-inline-md",
6
6
  "--slotted-control-padding-inline-sm",
7
7
  "--slotted-font-size-xs",
8
+ "--slotted-font-weight-medium",
8
9
  "--slotted-font-weight-semibold",
9
10
  "--slotted-line-height-sm",
10
11
  "--slotted-list-background",
@@ -28,6 +29,8 @@
28
29
  "--slotted-list-section-padding-block",
29
30
  "--slotted-list-section-padding-block-lg",
30
31
  "--slotted-list-section-padding-block-sm",
32
+ "--slotted-list-section-rule-color",
33
+ "--slotted-list-section-ruled-color",
31
34
  "--slotted-radius-md",
32
35
  "--slotted-space-2",
33
36
  "--slotted-space-3",
@@ -37,6 +40,7 @@
37
40
  "--slotted-space-8",
38
41
  "--slotted-space-9",
39
42
  "--slotted-surface",
43
+ "--slotted-text",
40
44
  "--slotted-text-muted",
41
45
  "--slotted-z-index-sticky"
42
46
  ]
@@ -520,6 +520,86 @@
520
520
  box-shadow: none;
521
521
  }
522
522
 
523
+ /**
524
+ * ── Underline ──────────────────────────────────────────────────────────
525
+ *
526
+ * The same radio group with no track: the words alone, sized to their own
527
+ * width, the chosen one in the text colour and underlined. Every other word
528
+ * is muted and takes the text colour under the pointer. No thumb, no
529
+ * dividers, no ground — the underline is the mark, and it sits under the
530
+ * word rather than on an edge of a box (R1).
531
+ */
532
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline'] {
533
+ --_inner: var(--_height);
534
+
535
+ background: none;
536
+ border: 0;
537
+ border-radius: 0;
538
+ box-shadow: none;
539
+ column-gap: var(--slotted-segmented-control-underline-gap, var(--slotted-space-6, 1rem));
540
+ grid-auto-columns: auto;
541
+ padding: 0;
542
+ }
543
+
544
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline'] [data-part='indicator'],
545
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']
546
+ [data-part='item']
547
+ + [data-part='item']::before {
548
+ display: none;
549
+ }
550
+
551
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline'] [data-part='item'] {
552
+ color: var(--slotted-segmented-control-underline-color, var(--slotted-text-muted, GrayText));
553
+ font-weight: var(--slotted-font-weight-medium, 500);
554
+ min-inline-size: var(--slotted-target-min, 24px);
555
+ padding-inline: 0;
556
+ }
557
+
558
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']
559
+ [data-part='item'][data-checked] {
560
+ color: var(
561
+ --slotted-segmented-control-underline-checked-color,
562
+ var(--slotted-text, CanvasText)
563
+ );
564
+ }
565
+
566
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']
567
+ [data-part='item'][data-checked]
568
+ [data-part='label'] {
569
+ text-decoration-color: currentColor;
570
+ text-decoration-line: underline;
571
+ text-decoration-thickness: var(--slotted-border-width-thick, 2px);
572
+ text-underline-offset: 0.35em;
573
+ }
574
+
575
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline'][data-invalid]
576
+ [data-part='item'][data-checked]
577
+ [data-part='label'] {
578
+ text-decoration-color: var(--slotted-tone-danger-border, CanvasText);
579
+ }
580
+
581
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']:not([data-readonly])
582
+ [data-part='item']:hover:not([data-disabled]):not([data-checked]):has(
583
+ [data-part='control']:enabled
584
+ ),
585
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']:not([data-readonly])
586
+ [data-part='item']:active:not([data-disabled]):not([data-checked]):has(
587
+ [data-part='control']:enabled
588
+ ) {
589
+ background: none;
590
+ color: var(--slotted-text, CanvasText);
591
+ }
592
+
593
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']
594
+ [data-part='item']:has([data-part='control']:focus-visible) {
595
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
596
+ }
597
+
598
+ [data-ui='segmented-control'][data-part='root'][data-variant='underline']
599
+ [data-part='item'][data-disabled] {
600
+ color: var(--slotted-disabled-foreground, GrayText);
601
+ }
602
+
523
603
  /* ── Condensed ────────────────────────────────────────────────────────── */
524
604
 
525
605
  /**
@@ -1,5 +1,6 @@
1
1
  [
2
2
  "--slotted-border-subtle",
3
+ "--slotted-border-width-thick",
3
4
  "--slotted-control-border-color",
4
5
  "--slotted-control-border-width",
5
6
  "--slotted-control-font-family",
@@ -35,7 +36,9 @@
35
36
  "--slotted-easing-standard",
36
37
  "--slotted-focus-ring-color",
37
38
  "--slotted-focus-ring-color-invalid",
39
+ "--slotted-focus-ring-offset",
38
40
  "--slotted-focus-ring-width",
41
+ "--slotted-font-weight-medium",
39
42
  "--slotted-radius-xs",
40
43
  "--slotted-segmented-control-active-background",
41
44
  "--slotted-segmented-control-background",
@@ -55,9 +58,14 @@
55
58
  "--slotted-segmented-control-invalid-focus-ring-color",
56
59
  "--slotted-segmented-control-radius",
57
60
  "--slotted-segmented-control-shadow",
61
+ "--slotted-segmented-control-underline-checked-color",
62
+ "--slotted-segmented-control-underline-color",
63
+ "--slotted-segmented-control-underline-gap",
58
64
  "--slotted-space-1",
65
+ "--slotted-space-6",
59
66
  "--slotted-target-min",
60
67
  "--slotted-text",
68
+ "--slotted-text-muted",
61
69
  "--slotted-tone-accent-border",
62
70
  "--slotted-tone-accent-subtle-active",
63
71
  "--slotted-tone-accent-text",
@@ -446,7 +446,9 @@
446
446
  font-size: var(--_value-size);
447
447
  font-variant-numeric: proportional-nums;
448
448
  font-weight: var(--slotted-font-weight-semibold, 600);
449
- letter-spacing: -0.02em;
449
+ /* The figure is set at the 3xl or 4xl step, where the theme's tighter
450
+ tracking applies. */
451
+ letter-spacing: var(--slotted-letter-spacing-tighter, -0.03em);
450
452
  unicode-bidi: plaintext;
451
453
  line-height: var(--_value-line);
452
454
  margin: 0;
@@ -13,6 +13,7 @@
13
13
  "--slotted-font-size-xs",
14
14
  "--slotted-font-weight-medium",
15
15
  "--slotted-font-weight-semibold",
16
+ "--slotted-letter-spacing-tighter",
16
17
  "--slotted-line-height-2xl",
17
18
  "--slotted-line-height-3xl",
18
19
  "--slotted-line-height-4xl",
@@ -461,6 +461,84 @@
461
461
  color: var(--slotted-disabled-foreground, GrayText);
462
462
  }
463
463
 
464
+ /**
465
+ * The row the page shows elsewhere — the record open in a detail pane. A
466
+ * neutral ground a step beyond hover, so the pointer passing over it changes
467
+ * nothing, and no edge on the start side (R1). It is opaque, because a
468
+ * pinned cell copies the row's ground and a translucent one shows the
469
+ * scrolled cells through it. Selection is stronger and paints over it.
470
+ */
471
+ [data-ui='table'] [data-part='body'] > [data-part='row'][data-current]:not([data-selected]) {
472
+ background-color: var(
473
+ --slotted-table-row-surface-current,
474
+ var(--slotted-tone-secondary-subtle-active, ButtonFace)
475
+ );
476
+ }
477
+
478
+ /* A row with an action of its own is a thing the pointer presses. */
479
+ [data-ui='table'] [data-part='body'] > [data-part='row'][data-interactive]:not([data-disabled]) {
480
+ cursor: pointer;
481
+ }
482
+
483
+ /**
484
+ * ── The band that opens a group ────────────────────────────────────────
485
+ *
486
+ * One header cell across every column: the group's name at the start and
487
+ * its total at the end, in tabular figures so a column of daily nets lines
488
+ * up. The ground is the stripe's step, opaque for the same reason a pinned
489
+ * cell's is, and the band stays where it is when the pointer passes.
490
+ */
491
+ [data-ui='table'] [data-part='group-header'] {
492
+ background-color: var(--slotted-table-group-surface, var(--_stripe));
493
+ border-block-end: var(--_rule-width) solid var(--_rule);
494
+ color: var(--slotted-table-group-color, var(--_text));
495
+ font-weight: var(--slotted-font-weight-semibold, 600);
496
+ padding-block: var(--_pad-block);
497
+ padding-inline: var(--_pad-inline);
498
+ text-align: start;
499
+ }
500
+
501
+ [data-ui='table'] [data-part='group-content'] {
502
+ align-items: baseline;
503
+ display: flex;
504
+ gap: var(--_gap);
505
+ justify-content: space-between;
506
+ min-inline-size: 0;
507
+ }
508
+
509
+ [data-ui='table'] [data-part='group-end'] {
510
+ font-variant-numeric: tabular-nums;
511
+ text-align: end;
512
+ white-space: nowrap;
513
+ }
514
+
515
+ /**
516
+ * A sticky band stops under the header when the header sticks too. The
517
+ * header's height is one row of the control scale and its rule; a header
518
+ * that wraps sets `--slotted-table-group-sticky-offset` itself.
519
+ */
520
+ [data-ui='table'] [data-part='group-row'][data-sticky] > [data-part='group-header'] {
521
+ inset-block-start: var(--slotted-table-group-sticky-offset, 0);
522
+ position: sticky;
523
+ z-index: var(--slotted-z-index-sticky, 100);
524
+ }
525
+
526
+ [data-ui='table'][data-sticky-header]
527
+ [data-part='group-row'][data-sticky]
528
+ > [data-part='group-header'] {
529
+ inset-block-start: var(
530
+ --slotted-table-group-sticky-offset,
531
+ calc(var(--_row-min-block) + var(--_rule-width))
532
+ );
533
+ }
534
+
535
+ @media (forced-colors: active) {
536
+ [data-ui='table'] [data-part='body'] > [data-part='row'][data-current] {
537
+ outline: var(--_rule-width) solid Highlight;
538
+ outline-offset: calc(var(--_rule-width) * -1);
539
+ }
540
+ }
541
+
464
542
  /**
465
543
  * ── Alignment and numerals ─────────────────────────────────────────────
466
544
  *
@@ -542,20 +620,32 @@
542
620
  * written where the choice is made: a table wider than the page pushes the
543
621
  * page sideways instead of scrolling inside its frame.
544
622
  *
545
- * The offset is where the header stops. An application with a bar of its own
546
- * sets `--slotted-table-sticky-offset` once, and every table under it stops
547
- * below the bar rather than under it.
623
+ * The offset is where the header stops under `page`. An application with a
624
+ * bar of its own sets `--slotted-table-sticky-offset` once, and every table
625
+ * under it stops below the bar rather than under it. Under `scroll` the
626
+ * header stops at the top of the family's own scroller and reads no offset:
627
+ * `page.css` binds the offset to the page's chrome for every table inside
628
+ * the page, and a header reading it stood that far below its own scroller's
629
+ * top, over the first rows. A `page` table inside a scrolling box of the
630
+ * consumer's own sets the offset on that box, `0` for its top edge.
548
631
  */
549
632
  [data-ui='table'][data-sticky-header] [data-part='column-header'],
550
633
  /* The chooser's own header is a `selection` cell and not a `column-header`,
551
634
  and a rule naming only the second left the select-all scrolling away while
552
635
  every column beside it stayed. */
553
636
  [data-ui='table'][data-sticky-header] [data-part='head'] [data-part='selection'] {
554
- inset-block-start: var(--slotted-table-sticky-offset, 0);
637
+ inset-block-start: 0;
555
638
  position: sticky;
556
639
  z-index: calc(var(--slotted-z-index-sticky, 100) + 1);
557
640
  }
558
641
 
642
+ [data-ui='table'][data-sticky-to='page'][data-sticky-header] [data-part='column-header'],
643
+ [data-ui='table'][data-sticky-to='page'][data-sticky-header]
644
+ [data-part='head']
645
+ [data-part='selection'] {
646
+ inset-block-start: var(--slotted-table-sticky-offset, 0);
647
+ }
648
+
559
649
  [data-ui='table'][data-sticky-to='page'] [data-part='scroll'] {
560
650
  overflow: visible;
561
651
  }
@@ -572,11 +662,18 @@
572
662
  * sibling of the scroller and never leaves it in the first place.
573
663
  */
574
664
  [data-ui='table'][data-sticky-footer] [data-part='summary'] > [data-part='row'] > * {
575
- inset-block-end: var(--slotted-table-sticky-offset-end, 0);
665
+ inset-block-end: 0;
576
666
  position: sticky;
577
667
  z-index: calc(var(--slotted-z-index-sticky, 100) + 1);
578
668
  }
579
669
 
670
+ [data-ui='table'][data-sticky-to='page'][data-sticky-footer]
671
+ [data-part='summary']
672
+ > [data-part='row']
673
+ > * {
674
+ inset-block-end: var(--slotted-table-sticky-offset-end, 0);
675
+ }
676
+
580
677
  /* The corner again, at the bottom: a summary cell that is also a pinned
581
678
  column takes both insets and the step above both. */
582
679
  [data-ui='table'][data-sticky-footer] [data-part='summary'] [data-sticky] {
@@ -41,12 +41,16 @@
41
41
  "--slotted-table-font-family",
42
42
  "--slotted-table-font-size",
43
43
  "--slotted-table-gap",
44
+ "--slotted-table-group-color",
45
+ "--slotted-table-group-sticky-offset",
46
+ "--slotted-table-group-surface",
44
47
  "--slotted-table-header-surface",
45
48
  "--slotted-table-header-surface-hover",
46
49
  "--slotted-table-icon-size",
47
50
  "--slotted-table-radius",
48
51
  "--slotted-table-row-color-selected",
49
52
  "--slotted-table-row-min-block-size",
53
+ "--slotted-table-row-surface-current",
50
54
  "--slotted-table-row-surface-hover",
51
55
  "--slotted-table-row-surface-selected",
52
56
  "--slotted-table-row-surface-selected-hover",
@@ -64,6 +68,7 @@
64
68
  "--slotted-tone-accent-subtle-hover",
65
69
  "--slotted-tone-accent-surface",
66
70
  "--slotted-tone-accent-text",
71
+ "--slotted-tone-secondary-subtle-active",
67
72
  "--slotted-tone-secondary-subtle-hover",
68
73
  "--slotted-z-index-sticky"
69
74
  ]
@@ -235,6 +235,47 @@
235
235
  transition-duration: var(--slotted-duration-instant);
236
236
  }
237
237
 
238
+ /**
239
+ * ── Chips ──────────────────────────────────────────────────────────────
240
+ *
241
+ * The same chip `toggle-group` draws: a rounded item with the control edge,
242
+ * pressed in the neutral tone's ink.
243
+ */
244
+ [data-ui='toggle'][data-part='root'][data-variant='chips'] {
245
+ border-color: var(--_border-color);
246
+ border-radius: var(--slotted-toggle-chips-radius, var(--slotted-radius-full, 9999px));
247
+ font-weight: var(--slotted-font-weight-medium, 500);
248
+ }
249
+
250
+ [data-ui='toggle'][data-part='root'][data-variant='chips'][data-pressed]:not(:disabled):not(
251
+ [data-disabled]
252
+ ),
253
+ [data-ui='toggle'][data-part='root'][data-variant='chips'][data-pressed]:active:not(
254
+ :disabled
255
+ ):not([data-disabled]) {
256
+ background: var(
257
+ --slotted-toggle-chips-pressed-background,
258
+ var(--slotted-tone-neutral-solid, CanvasText)
259
+ );
260
+ border-color: var(
261
+ --slotted-toggle-chips-pressed-background,
262
+ var(--slotted-tone-neutral-solid, CanvasText)
263
+ );
264
+ color: var(--slotted-toggle-chips-pressed-color, var(--slotted-tone-neutral-on-solid, Canvas));
265
+ }
266
+
267
+ [data-ui='toggle'][data-part='root'][data-variant='chips'][data-pressed]:hover:not(:disabled):not(
268
+ [data-disabled]
269
+ ) {
270
+ background: var(--slotted-tone-neutral-solid-hover, CanvasText);
271
+ border-color: var(--slotted-tone-neutral-solid-hover, CanvasText);
272
+ }
273
+
274
+ [data-ui='toggle'][data-part='root'][data-variant='chips']:disabled,
275
+ [data-ui='toggle'][data-part='root'][data-variant='chips'][data-disabled] {
276
+ border-color: var(--slotted-disabled-border, GrayText);
277
+ }
278
+
238
279
  /* ── Focus ────────────────────────────────────────────────────────────── */
239
280
 
240
281
  /**
@@ -31,9 +31,14 @@
31
31
  "--slotted-focus-ring-color",
32
32
  "--slotted-focus-ring-offset",
33
33
  "--slotted-focus-ring-width",
34
+ "--slotted-font-weight-medium",
35
+ "--slotted-radius-full",
34
36
  "--slotted-text",
35
37
  "--slotted-toggle-active-background",
36
38
  "--slotted-toggle-border-color",
39
+ "--slotted-toggle-chips-pressed-background",
40
+ "--slotted-toggle-chips-pressed-color",
41
+ "--slotted-toggle-chips-radius",
37
42
  "--slotted-toggle-color",
38
43
  "--slotted-toggle-disabled-border-color",
39
44
  "--slotted-toggle-disabled-color",
@@ -49,6 +54,9 @@
49
54
  "--slotted-tone-accent-subtle-active",
50
55
  "--slotted-tone-accent-subtle-hover",
51
56
  "--slotted-tone-accent-text",
57
+ "--slotted-tone-neutral-on-solid",
58
+ "--slotted-tone-neutral-solid",
59
+ "--slotted-tone-neutral-solid-hover",
52
60
  "--slotted-tone-secondary-subtle-active",
53
61
  "--slotted-tone-secondary-subtle-hover"
54
62
  ]
@@ -392,6 +392,56 @@
392
392
  transition-duration: var(--slotted-duration-instant);
393
393
  }
394
394
 
395
+ /**
396
+ * ── Chips ──────────────────────────────────────────────────────────────
397
+ *
398
+ * A short list of choices as separate rounded items that wrap onto a second
399
+ * line rather than overflow, never joined into a bar. A chip at rest has the
400
+ * control edge; the pressed one is the neutral tone's ink — its solid ground
401
+ * under its own label — which is the one state a chip has to say at a
402
+ * glance. Hover and press move the ground of a chip at rest only.
403
+ */
404
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips'] {
405
+ flex-wrap: wrap;
406
+ gap: var(--slotted-toggle-group-chips-gap, var(--slotted-space-3, 0.375rem));
407
+ }
408
+
409
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips'] [data-part='item'] {
410
+ border-color: var(--_border-color);
411
+ border-radius: var(--slotted-toggle-group-chips-radius, var(--slotted-radius-full, 9999px));
412
+ font-weight: var(--slotted-font-weight-medium, 500);
413
+ }
414
+
415
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips']
416
+ [data-part='item'][data-pressed]:not(:disabled):not([data-disabled]),
417
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips']
418
+ [data-part='item'][data-pressed]:active:not(:disabled):not([data-disabled]) {
419
+ background: var(
420
+ --slotted-toggle-group-chips-pressed-background,
421
+ var(--slotted-tone-neutral-solid, CanvasText)
422
+ );
423
+ border-color: var(
424
+ --slotted-toggle-group-chips-pressed-background,
425
+ var(--slotted-tone-neutral-solid, CanvasText)
426
+ );
427
+ color: var(
428
+ --slotted-toggle-group-chips-pressed-color,
429
+ var(--slotted-tone-neutral-on-solid, Canvas)
430
+ );
431
+ }
432
+
433
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips']
434
+ [data-part='item'][data-pressed]:hover:not(:disabled):not([data-disabled]) {
435
+ background: var(--slotted-tone-neutral-solid-hover, CanvasText);
436
+ border-color: var(--slotted-tone-neutral-solid-hover, CanvasText);
437
+ }
438
+
439
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips'] [data-part='item']:disabled,
440
+ [data-ui='toggle-group'][data-part='root'][data-variant='chips']
441
+ [data-part='item'][data-disabled] {
442
+ border-color: var(--slotted-disabled-border, GrayText);
443
+ }
444
+
395
445
  /* ── Focus ────────────────────────────────────────────────────────────── */
396
446
 
397
447
  /**
@@ -31,9 +31,16 @@
31
31
  "--slotted-focus-ring-color",
32
32
  "--slotted-focus-ring-offset",
33
33
  "--slotted-focus-ring-width",
34
+ "--slotted-font-weight-medium",
35
+ "--slotted-radius-full",
36
+ "--slotted-space-3",
34
37
  "--slotted-text",
35
38
  "--slotted-toggle-group-active-background",
36
39
  "--slotted-toggle-group-border-color",
40
+ "--slotted-toggle-group-chips-gap",
41
+ "--slotted-toggle-group-chips-pressed-background",
42
+ "--slotted-toggle-group-chips-pressed-color",
43
+ "--slotted-toggle-group-chips-radius",
37
44
  "--slotted-toggle-group-color",
38
45
  "--slotted-toggle-group-disabled-border-color",
39
46
  "--slotted-toggle-group-disabled-color",
@@ -49,6 +56,9 @@
49
56
  "--slotted-tone-accent-subtle-active",
50
57
  "--slotted-tone-accent-subtle-hover",
51
58
  "--slotted-tone-accent-text",
59
+ "--slotted-tone-neutral-on-solid",
60
+ "--slotted-tone-neutral-solid",
61
+ "--slotted-tone-neutral-solid-hover",
52
62
  "--slotted-tone-secondary-subtle-active",
53
63
  "--slotted-tone-secondary-subtle-hover"
54
64
  ]