@slotted/styles 0.1.0-beta.3 → 0.1.0-beta.5
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 +1 -1
- package/src/chart/chart.css +8 -2
- package/src/page-header/page-header.css +37 -0
- package/src/page-header/page-header.tokens.json +1 -0
- package/src/scroll-area/scroll-area.css +11 -1
- package/src/stat-card/stat-card.css +317 -227
- package/src/table/table.css +60 -3
- package/src/table/table.tokens.json +1 -0
- package/src/tabs/tabs.css +179 -151
- package/src/tabs/tabs.tokens.json +4 -1
package/src/table/table.css
CHANGED
|
@@ -189,8 +189,14 @@
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
/* The ring is drawn inside, because a scroller flush against the frame would
|
|
192
|
-
otherwise draw half its ring outside it.
|
|
193
|
-
|
|
192
|
+
otherwise draw half its ring outside it. It is drawn for a focus from the
|
|
193
|
+
keyboard: a click on a cell focuses the scroller too, and the next Shift
|
|
194
|
+
would make it match `:focus-visible` (`createFocusOrigin`). The browser's own
|
|
195
|
+
ring is suppressed for the same focus. */
|
|
196
|
+
[data-ui='table'] [data-part='scroll']:focus {
|
|
197
|
+
outline: none;
|
|
198
|
+
}
|
|
199
|
+
[data-ui='table'] [data-part='scroll']:focus-visible[data-focus-origin='keyboard'] {
|
|
194
200
|
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
195
201
|
outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
|
|
196
202
|
}
|
|
@@ -232,7 +238,7 @@
|
|
|
232
238
|
color: var(--_muted);
|
|
233
239
|
font-size: var(--slotted-font-size-xs, 0.75rem);
|
|
234
240
|
padding-block: var(--_pad-block);
|
|
235
|
-
padding-inline: var(--
|
|
241
|
+
padding-inline: var(--_edge-inset);
|
|
236
242
|
text-align: start;
|
|
237
243
|
}
|
|
238
244
|
|
|
@@ -319,6 +325,57 @@
|
|
|
319
325
|
vertical-align: var(--_cell-align);
|
|
320
326
|
}
|
|
321
327
|
|
|
328
|
+
/**
|
|
329
|
+
* ── The outer edges ────────────────────────────────────────────────────
|
|
330
|
+
*
|
|
331
|
+
* The first and the last column take `--_edge-inset` on their outer side:
|
|
332
|
+
* the cell's own inset by default, and under `edges="flush"` the theme's
|
|
333
|
+
* `--slotted-table-edge-inset`, nought when it sets none — so a `plain` or
|
|
334
|
+
* `ruled` table lines its text up with the heading above it. A `framed`
|
|
335
|
+
* table keeps the inset whatever `edges` says: its text stands against a
|
|
336
|
+
* border, and text touching a border is the cramped picture the frame
|
|
337
|
+
* exists to avoid. A pinned column keeps its own offset, which is a
|
|
338
|
+
* position rather than a padding, and the selection cell keeps its own
|
|
339
|
+
* inset because it is not one of the parts named here — a table that leads
|
|
340
|
+
* with a chooser has no text at its edge.
|
|
341
|
+
*/
|
|
342
|
+
[data-ui='table'][data-part='root'] {
|
|
343
|
+
--_edge-inset: var(--_pad-inline);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
[data-ui='table'][data-part='root'][data-edges='flush']:is(
|
|
347
|
+
[data-variant='plain'],
|
|
348
|
+
[data-variant='ruled']
|
|
349
|
+
) {
|
|
350
|
+
--_edge-inset: var(--slotted-table-edge-inset, 0px);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
[data-ui='table']
|
|
354
|
+
[data-part='row']
|
|
355
|
+
> :is([data-part='cell'], [data-part='row-header'], [data-part='group-header']):first-child,
|
|
356
|
+
[data-ui='table']
|
|
357
|
+
[data-part='row']
|
|
358
|
+
> [data-part='column-header']:first-child:not(:has(> [data-part='sort'])),
|
|
359
|
+
[data-ui='table']
|
|
360
|
+
[data-part='row']
|
|
361
|
+
> [data-part='column-header']:first-child
|
|
362
|
+
> [data-part='sort'] {
|
|
363
|
+
padding-inline-start: var(--_edge-inset);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
[data-ui='table']
|
|
367
|
+
[data-part='row']
|
|
368
|
+
> :is([data-part='cell'], [data-part='row-header'], [data-part='group-header']):last-child,
|
|
369
|
+
[data-ui='table']
|
|
370
|
+
[data-part='row']
|
|
371
|
+
> [data-part='column-header']:last-child:not(:has(> [data-part='sort'])),
|
|
372
|
+
[data-ui='table']
|
|
373
|
+
[data-part='row']
|
|
374
|
+
> [data-part='column-header']:last-child
|
|
375
|
+
> [data-part='sort'] {
|
|
376
|
+
padding-inline-end: var(--_edge-inset);
|
|
377
|
+
}
|
|
378
|
+
|
|
322
379
|
[data-ui='table'] [data-block-align='start'] {
|
|
323
380
|
vertical-align: top;
|
|
324
381
|
}
|
package/src/tabs/tabs.css
CHANGED
|
@@ -47,23 +47,28 @@
|
|
|
47
47
|
min(calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)), var(--_inner-size))
|
|
48
48
|
);
|
|
49
49
|
--_dismiss-overhang: calc((var(--_dismiss-size) - var(--_icon-size)) / 2);
|
|
50
|
-
|
|
50
|
+
/**
|
|
51
|
+
* The marker: one bar the list draws under the selected tab, and the hover
|
|
52
|
+
* bar under the tab the pointer is on, in the same geometry — the tab's
|
|
53
|
+
* content box, a pill on the list's edge. It is never thinner than the
|
|
54
|
+
* thick border width, the floor the high-contrast scheme keeps for a mark
|
|
55
|
+
* that carries state, and its thickness, its rounding and its inset are
|
|
56
|
+
* tokens of their own: tied to the thick border width, a theme could not
|
|
57
|
+
* thicken the marker without thickening sixty other rules.
|
|
58
|
+
*/
|
|
59
|
+
--_marker-size: max(
|
|
60
|
+
var(--slotted-tabs-marker-size, 3px),
|
|
61
|
+
var(--slotted-border-width-thick, 2px)
|
|
62
|
+
);
|
|
63
|
+
--_marker-radius: var(--slotted-tabs-marker-radius, var(--slotted-radius-full, 9999px));
|
|
64
|
+
--_marker-inset: var(--slotted-tabs-marker-inset, var(--_padding-inline));
|
|
65
|
+
--_track-color: var(--slotted-tabs-track-color, var(--slotted-border-subtle, ButtonBorder));
|
|
51
66
|
/**
|
|
52
67
|
* The length of the fade a scrolling list takes at an edge that has more
|
|
53
68
|
* behind it, read once here so the five mask gradients below state a
|
|
54
69
|
* length and no public property of their own.
|
|
55
70
|
*/
|
|
56
71
|
--_fade: var(--slotted-tabs-fade-size, var(--slotted-space-6, 1rem));
|
|
57
|
-
/**
|
|
58
|
-
* Which way the selection travelled, resolved into a transform origin. The
|
|
59
|
-
* marker of the tab being left collapses toward the direction of travel
|
|
60
|
-
* and the marker of the tab being entered grows from the side the reader
|
|
61
|
-
* came from, so the pair reads as one bar moving. Nothing is measured:
|
|
62
|
-
* every surveyed indicator reads the active tab's box, which is why Base UI
|
|
63
|
-
* ships `renderBeforeHydration` and Ark UI a `setIndicatorRect`.
|
|
64
|
-
*/
|
|
65
|
-
--_marker-origin: 50%;
|
|
66
|
-
--_marker-origin-selected: 50%;
|
|
67
72
|
|
|
68
73
|
/**
|
|
69
74
|
* No column gap on the grid itself: three gaps stood around two empty
|
|
@@ -112,6 +117,9 @@
|
|
|
112
117
|
* it the panel's first letter touched the track on the list's end edge.
|
|
113
118
|
*/
|
|
114
119
|
[data-ui='tabs'][data-orientation='vertical'] {
|
|
120
|
+
/* The inset runs along the block axis, where a tab has no padding. */
|
|
121
|
+
--_marker-inset: var(--slotted-tabs-marker-inset, 0px);
|
|
122
|
+
|
|
115
123
|
column-gap: var(--slotted-tabs-gap, var(--slotted-space-6, 1rem));
|
|
116
124
|
grid-template-columns: auto minmax(0, 1fr);
|
|
117
125
|
grid-template-rows: auto auto;
|
|
@@ -140,6 +148,8 @@
|
|
|
140
148
|
overflow-x: auto;
|
|
141
149
|
overflow-y: hidden;
|
|
142
150
|
overscroll-behavior-inline: contain;
|
|
151
|
+
/* The containing block of the marker, which scrolls with the tabs. */
|
|
152
|
+
position: relative;
|
|
143
153
|
/**
|
|
144
154
|
* The platform's scrollbar is the affordance until the family draws its
|
|
145
155
|
* own. It is hidden only once `data-overflowing` says the paging controls
|
|
@@ -153,9 +163,19 @@
|
|
|
153
163
|
scrollbar-width: none;
|
|
154
164
|
}
|
|
155
165
|
|
|
166
|
+
/**
|
|
167
|
+
* The track is an inset shadow on the list's own padding rather than its
|
|
168
|
+
* border. The list is a scroll container, which clips what it draws to its
|
|
169
|
+
* padding box, so a marker standing over a border was cut along it; inside
|
|
170
|
+
* the padding the marker lies over the line, flush with the list's edge. The
|
|
171
|
+
* shadow is the box's, so the line does not scroll with the tabs.
|
|
172
|
+
*/
|
|
156
173
|
[data-ui='tabs'][data-variant='line'][data-track='line'] > [data-part='list'] {
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
/* How far the hover bar reaches past an item to stand on the track. */
|
|
175
|
+
--_track-reach: var(--_track-size);
|
|
176
|
+
|
|
177
|
+
box-shadow: inset 0 calc(-1 * var(--_track-size)) 0 var(--_track-color);
|
|
178
|
+
padding-block-end: var(--_track-size);
|
|
159
179
|
}
|
|
160
180
|
|
|
161
181
|
/**
|
|
@@ -169,24 +189,10 @@
|
|
|
169
189
|
* variant for the same case, which is a second family's worth of paint to
|
|
170
190
|
* remove one line.
|
|
171
191
|
*
|
|
172
|
-
* The marker then sits on the
|
|
173
|
-
*
|
|
174
|
-
*
|
|
192
|
+
* The marker then sits on the list's own edge, which is the items' edge, so
|
|
193
|
+
* it lands on the line the page already drew. Where that line is is the
|
|
194
|
+
* page's business: the family stops at its own box.
|
|
175
195
|
*/
|
|
176
|
-
[data-ui='tabs'][data-track='none'] > :where([data-part='list']) > [data-part='item']::before,
|
|
177
|
-
[data-ui='tabs'][data-track='none'] > :where([data-part='list']) > [data-part='item']::after {
|
|
178
|
-
inset-block-end: 0;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
[data-ui='tabs'][data-track='none'][data-orientation='vertical']
|
|
182
|
-
> :where([data-part='list'])
|
|
183
|
-
> [data-part='item']::before,
|
|
184
|
-
[data-ui='tabs'][data-track='none'][data-orientation='vertical']
|
|
185
|
-
> :where([data-part='list'])
|
|
186
|
-
> [data-part='item']::after {
|
|
187
|
-
inset-block-end: auto;
|
|
188
|
-
inset-inline-end: 0;
|
|
189
|
-
}
|
|
190
196
|
|
|
191
197
|
/**
|
|
192
198
|
* A column of labels reads down its own start edge. Centring them is what the
|
|
@@ -209,11 +215,17 @@
|
|
|
209
215
|
overflow-y: auto;
|
|
210
216
|
}
|
|
211
217
|
|
|
218
|
+
/* A shadow takes no logical offset, so the line's side is mirrored by hand. */
|
|
212
219
|
[data-ui='tabs'][data-orientation='vertical'][data-variant='line'][data-track='line']
|
|
213
220
|
> [data-part='list'] {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
box-shadow: inset calc(-1 * var(--_track-size)) 0 0 var(--_track-color);
|
|
222
|
+
padding-block-end: 0;
|
|
223
|
+
padding-inline-end: var(--_track-size);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
[data-ui='tabs'][data-orientation='vertical'][data-variant='line'][data-track='line']:dir(rtl)
|
|
227
|
+
> [data-part='list'] {
|
|
228
|
+
box-shadow: inset var(--_track-size) 0 0 var(--_track-color);
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
/**
|
|
@@ -251,10 +263,9 @@
|
|
|
251
263
|
/* ── One tab, and the box that holds it ───────────────────────────────── */
|
|
252
264
|
|
|
253
265
|
/**
|
|
254
|
-
* The item is presentational, and it exists
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
* rather than only the label.
|
|
266
|
+
* The item is presentational, and it exists because a `button` may not
|
|
267
|
+
* contain a `button`: a dismissible tab needs a box for its second control.
|
|
268
|
+
* It also carries the hover bar, under the tab and not the control.
|
|
258
269
|
*/
|
|
259
270
|
[data-ui='tabs'] > :where([data-part='list']) > [data-part='item'] {
|
|
260
271
|
align-items: stretch;
|
|
@@ -438,52 +449,105 @@
|
|
|
438
449
|
/* ── The marker ───────────────────────────────────────────────────────── */
|
|
439
450
|
|
|
440
451
|
/**
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
* lines are one line rather than a hairline with a thicker line beside it.
|
|
452
|
+
* One bar, drawn by the list rather than by each item, that slides from the
|
|
453
|
+
* tab being left to the tab being entered: a mark per item can only appear
|
|
454
|
+
* or scale from an edge, and one mark moving is what says the selection
|
|
455
|
+
* moved. The binding creates it with `createIndicator` from
|
|
456
|
+
* `@slotted/core/measure`, which writes the selected tab's start and length
|
|
457
|
+
* in the list's scroll coordinates; everything else is decided here.
|
|
448
458
|
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*/
|
|
457
|
-
[data-ui='tabs'] > :where([data-part='list']) > [data-part='
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
459
|
+
* It spans the tab's content box — the icon and the label — through
|
|
460
|
+
* `--slotted-tabs-marker-inset`, which defaults to the tab's own inline
|
|
461
|
+
* padding, and never the closing control: a tab followed by one gives up its
|
|
462
|
+
* end padding, so the end inset is nought there. Below the width of a short
|
|
463
|
+
* label it keeps a minimum length, centred on the content. It stands on the
|
|
464
|
+
* list's edge, over the track, and the axes are physical in this one rule
|
|
465
|
+
* because the measurement is: the translate is from the list's left edge.
|
|
466
|
+
*/
|
|
467
|
+
[data-ui='tabs'] > :where([data-part='list']) > [data-part='marker'] {
|
|
468
|
+
--_start-inset: var(--_marker-inset);
|
|
469
|
+
--_end-inset: var(--_marker-inset);
|
|
470
|
+
--_left-inset: var(--_start-inset);
|
|
471
|
+
--_span: calc(var(--_indicator-length, 0px) - var(--_start-inset) - var(--_end-inset));
|
|
472
|
+
--_length: max(var(--slotted-space-6, 1rem), var(--_span));
|
|
473
|
+
|
|
474
|
+
background-color: var(--slotted-tabs-marker-color, var(--slotted-tone-accent-solid));
|
|
461
475
|
block-size: var(--_marker-size);
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
inset-
|
|
465
|
-
|
|
476
|
+
border-radius: var(--_marker-radius);
|
|
477
|
+
inline-size: var(--_length);
|
|
478
|
+
inset-block-end: var(--_marker-lift, 0px);
|
|
479
|
+
left: 0;
|
|
466
480
|
pointer-events: none;
|
|
467
481
|
position: absolute;
|
|
482
|
+
translate: calc(
|
|
483
|
+
var(--_indicator-start, 0px) + var(--_left-inset) + (var(--_span) - var(--_length)) / 2
|
|
484
|
+
)
|
|
485
|
+
0;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
[data-ui='tabs']:dir(rtl) > :where([data-part='list']) > [data-part='marker'] {
|
|
489
|
+
--_left-inset: var(--_end-inset);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
[data-ui='tabs']:not([data-orientation='vertical'])
|
|
493
|
+
> [data-part='list']:has(> [data-part='item'][data-selected] > [data-part='dismiss'])
|
|
494
|
+
> [data-part='marker'] {
|
|
495
|
+
--_end-inset: 0px;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
[data-ui='tabs'] > :where([data-part='list']) > [data-part='marker'][hidden] {
|
|
499
|
+
display: none;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Placed once without motion, then it slides: the first position arrives
|
|
504
|
+
* before `data-positioned`, so the bar does not travel in from the list's
|
|
505
|
+
* corner. Under reduced motion it jumps.
|
|
506
|
+
*/
|
|
507
|
+
[data-ui='tabs'] > :where([data-part='list']) > [data-part='marker'][data-positioned] {
|
|
508
|
+
transition:
|
|
509
|
+
translate var(--slotted-control-transition-duration) var(--slotted-control-transition-easing),
|
|
510
|
+
inline-size var(--slotted-control-transition-duration)
|
|
511
|
+
var(--slotted-control-transition-easing),
|
|
512
|
+
block-size var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
468
513
|
}
|
|
469
514
|
|
|
515
|
+
@media (prefers-reduced-motion: reduce) {
|
|
516
|
+
[data-ui='tabs'] > :where([data-part='list']) > [data-part='marker'][data-positioned] {
|
|
517
|
+
transition: none;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* The hover bar: the marker's geometry under the tab the pointer is on, in a
|
|
523
|
+
* neutral at a reduced opacity, saying where the mark would go. It is drawn
|
|
524
|
+
* on the item, and it fades rather than slides — a bar that travelled on
|
|
525
|
+
* every pass of the pointer would be the selection's motion with nothing
|
|
526
|
+
* selected. It reaches past the item by the track's width to lie on it, and
|
|
527
|
+
* stops at the tab where a closing control follows: that control is the
|
|
528
|
+
* tab's inline padding on either side of the glyph.
|
|
529
|
+
*/
|
|
470
530
|
[data-ui='tabs'] > :where([data-part='list']) > [data-part='item']::before {
|
|
471
|
-
/* No system colour as a last resort: unthemed, the bar disappears rather
|
|
472
|
-
than shouts, as the mark beside it already does. */
|
|
473
531
|
background-color: var(--slotted-tabs-hover-marker-color, var(--slotted-border-strong));
|
|
532
|
+
block-size: var(--_marker-size);
|
|
533
|
+
border-radius: var(--_marker-radius);
|
|
534
|
+
content: '';
|
|
535
|
+
inset-block-end: calc(-1 * var(--_track-reach, 0px));
|
|
536
|
+
inset-inline: var(--_marker-inset);
|
|
537
|
+
min-inline-size: var(--slotted-space-6, 1rem);
|
|
538
|
+
opacity: 0;
|
|
539
|
+
pointer-events: none;
|
|
540
|
+
position: absolute;
|
|
474
541
|
transition:
|
|
475
542
|
background-color var(--slotted-control-transition-duration)
|
|
476
543
|
var(--slotted-control-transition-easing),
|
|
477
544
|
opacity var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
478
545
|
}
|
|
479
546
|
|
|
480
|
-
[data-ui='tabs']
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
transition:
|
|
485
|
-
opacity var(--slotted-control-transition-duration) var(--slotted-control-transition-easing),
|
|
486
|
-
transform var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
547
|
+
[data-ui='tabs']:not([data-orientation='vertical'])
|
|
548
|
+
> :where([data-part='list'])
|
|
549
|
+
> [data-part='item']:has(> [data-part='dismiss'])::before {
|
|
550
|
+
inset-inline-end: calc(2 * var(--_padding-inline) + var(--_icon-size));
|
|
487
551
|
}
|
|
488
552
|
|
|
489
553
|
[data-ui='tabs'][data-variant='line']
|
|
@@ -491,7 +555,7 @@
|
|
|
491
555
|
> [data-part='item']:not([data-selected]):has(
|
|
492
556
|
> [data-part='tab']:not(:disabled):hover
|
|
493
557
|
)::before {
|
|
494
|
-
opacity:
|
|
558
|
+
opacity: var(--slotted-tabs-hover-marker-opacity, 0.5);
|
|
495
559
|
}
|
|
496
560
|
|
|
497
561
|
/** Press takes the bar to the label's own ink: the two say one thing. */
|
|
@@ -503,67 +567,31 @@
|
|
|
503
567
|
background-color: var(--slotted-tabs-active-marker-color, var(--slotted-text));
|
|
504
568
|
}
|
|
505
569
|
|
|
506
|
-
[data-ui='tabs'] > :where([data-part='list']) > [data-part='item'][data-selected]::after {
|
|
507
|
-
opacity: 1;
|
|
508
|
-
transform: scale(1, 1);
|
|
509
|
-
transform-origin: var(--_marker-origin-selected) 50%;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
570
|
/**
|
|
513
|
-
*
|
|
514
|
-
* the
|
|
515
|
-
*
|
|
516
|
-
* percentages swap under `:dir(rtl)` — the one place in this stylesheet
|
|
517
|
-
* where a rule is mirrored by hand.
|
|
571
|
+
* A quarter turn: both bars stand on the list's inline-end edge and run along
|
|
572
|
+
* the block axis, where the inset defaults to nought because a tab has no
|
|
573
|
+
* block padding.
|
|
518
574
|
*/
|
|
519
|
-
[data-ui='tabs'][data-activation-direction='forward'] {
|
|
520
|
-
--_marker-origin: 100%;
|
|
521
|
-
--_marker-origin-selected: 0%;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
[data-ui='tabs'][data-activation-direction='backward'] {
|
|
525
|
-
--_marker-origin: 0%;
|
|
526
|
-
--_marker-origin-selected: 100%;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
[data-ui='tabs'][data-activation-direction='forward']:dir(rtl) {
|
|
530
|
-
--_marker-origin: 0%;
|
|
531
|
-
--_marker-origin-selected: 100%;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
[data-ui='tabs'][data-activation-direction='backward']:dir(rtl) {
|
|
535
|
-
--_marker-origin: 100%;
|
|
536
|
-
--_marker-origin-selected: 0%;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/** A quarter turn: the bar stands on the list's own edge and grows in block. */
|
|
540
575
|
[data-ui='tabs'][data-orientation='vertical']
|
|
541
576
|
> :where([data-part='list'])
|
|
542
|
-
> [data-part='
|
|
543
|
-
|
|
544
|
-
> :where([data-part='list'])
|
|
545
|
-
> [data-part='item']::after {
|
|
546
|
-
block-size: auto;
|
|
547
|
-
border-start-end-radius: var(--slotted-radius-xs, 2px);
|
|
548
|
-
border-start-start-radius: 0;
|
|
549
|
-
border-end-end-radius: var(--slotted-radius-xs, 2px);
|
|
577
|
+
> [data-part='marker'] {
|
|
578
|
+
block-size: var(--_length);
|
|
550
579
|
inline-size: var(--_marker-size);
|
|
551
|
-
inset-block: 0;
|
|
552
|
-
inset-inline: auto
|
|
580
|
+
inset-block: 0 auto;
|
|
581
|
+
inset-inline: auto var(--_marker-lift, 0px);
|
|
582
|
+
translate: 0
|
|
583
|
+
calc(var(--_indicator-start, 0px) + var(--_start-inset) + (var(--_span) - var(--_length)) / 2);
|
|
553
584
|
}
|
|
554
585
|
|
|
555
586
|
[data-ui='tabs'][data-orientation='vertical']
|
|
556
587
|
> :where([data-part='list'])
|
|
557
|
-
> [data-part='item']::
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
> [data-part='item'][data-selected]::after {
|
|
565
|
-
transform: scale(1, 1);
|
|
566
|
-
transform-origin: 50% var(--_marker-origin-selected);
|
|
588
|
+
> [data-part='item']::before {
|
|
589
|
+
block-size: auto;
|
|
590
|
+
inline-size: var(--_marker-size);
|
|
591
|
+
inset-block: var(--_marker-inset);
|
|
592
|
+
inset-inline: auto calc(-1 * var(--_track-reach, 0px));
|
|
593
|
+
min-block-size: var(--slotted-space-6, 1rem);
|
|
594
|
+
min-inline-size: 0;
|
|
567
595
|
}
|
|
568
596
|
|
|
569
597
|
/* ── Contained ────────────────────────────────────────────────────────── */
|
|
@@ -582,6 +610,9 @@
|
|
|
582
610
|
* there the track is the edge of the panel below it.
|
|
583
611
|
*/
|
|
584
612
|
[data-ui='tabs'][data-variant='contained'] > [data-part='list'] {
|
|
613
|
+
/* The marker underlines the label inside the selected surface, a step above its edge. */
|
|
614
|
+
--_marker-lift: calc(2 * var(--slotted-space-1, 0.125rem));
|
|
615
|
+
|
|
585
616
|
background-color: var(--slotted-tabs-contained-background, var(--slotted-surface-sunken));
|
|
586
617
|
border-radius: var(--slotted-radius-md, 6px);
|
|
587
618
|
justify-self: start;
|
|
@@ -602,26 +633,6 @@
|
|
|
602
633
|
box-shadow: var(--slotted-shadow-xs);
|
|
603
634
|
}
|
|
604
635
|
|
|
605
|
-
/**
|
|
606
|
-
* Inset from the corners by the radius, so the bar underlines the label
|
|
607
|
-
* instead of tracing the edge of the surface it sits on. Sitting on the
|
|
608
|
-
* edge, it read as a second border of a different colour, and the capture
|
|
609
|
-
* showed a pill with one blue side.
|
|
610
|
-
*/
|
|
611
|
-
[data-ui='tabs'][data-variant='contained']
|
|
612
|
-
> :where([data-part='list'])
|
|
613
|
-
> [data-part='item']::after {
|
|
614
|
-
inset-block-end: var(--slotted-space-1, 0.125rem);
|
|
615
|
-
inset-inline: var(--slotted-radius-sm, 4px);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
[data-ui='tabs'][data-variant='contained'][data-orientation='vertical']
|
|
619
|
-
> :where([data-part='list'])
|
|
620
|
-
> [data-part='item']::after {
|
|
621
|
-
inset-block: var(--slotted-radius-sm, 4px);
|
|
622
|
-
inset-inline: auto var(--slotted-space-1, 0.125rem);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
636
|
/* ── The dismiss control ──────────────────────────────────────────────── */
|
|
626
637
|
|
|
627
638
|
/**
|
|
@@ -963,8 +974,8 @@
|
|
|
963
974
|
* adds is the track: a disabled family should not read as a live one with
|
|
964
975
|
* grey labels.
|
|
965
976
|
*/
|
|
966
|
-
[data-ui='tabs'][data-disabled]
|
|
967
|
-
|
|
977
|
+
[data-ui='tabs'][data-disabled] {
|
|
978
|
+
--_track-color: var(--slotted-disabled-border, GrayText);
|
|
968
979
|
}
|
|
969
980
|
|
|
970
981
|
[data-ui='tabs'][data-disabled][data-variant='contained'] > [data-part='list'] {
|
|
@@ -976,21 +987,38 @@
|
|
|
976
987
|
* decoration in an unthemed page should disappear rather than shout, and a
|
|
977
988
|
* marker painted `GrayText` with no theme would be the loudest thing on it.
|
|
978
989
|
*/
|
|
979
|
-
[data-ui='tabs'][data-disabled]
|
|
980
|
-
> :where([data-part='list'])
|
|
981
|
-
> [data-part='item'][data-selected]::after {
|
|
990
|
+
[data-ui='tabs'][data-disabled] > :where([data-part='list']) > [data-part='marker'] {
|
|
982
991
|
background-color: var(--slotted-disabled-border);
|
|
983
992
|
}
|
|
984
993
|
|
|
985
994
|
/* ── Forced colours ──────────────────────────────────────────────────── */
|
|
986
995
|
|
|
987
996
|
/**
|
|
988
|
-
* The theme maps every scheme token to a system colour, so the
|
|
989
|
-
*
|
|
990
|
-
*
|
|
991
|
-
* track it stands in.
|
|
997
|
+
* The theme maps every scheme token to a system colour, so the rules here
|
|
998
|
+
* are about paint the theme cannot reach: the track drawn as a shadow, the
|
|
999
|
+
* marker's ground, and a selected tab in the contained variant, whose fill
|
|
1000
|
+
* flattens to `Canvas` along with the track it stands in.
|
|
992
1001
|
*/
|
|
993
1002
|
@media (forced-colors: active) {
|
|
1003
|
+
/* A shadow is not drawn under forced colours: the track is a border again. */
|
|
1004
|
+
[data-ui='tabs'][data-variant='line'][data-track='line'] > [data-part='list'] {
|
|
1005
|
+
border-block-end: var(--_track-size) solid CanvasText;
|
|
1006
|
+
padding-block-end: 0;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
[data-ui='tabs'][data-orientation='vertical'][data-variant='line'][data-track='line']
|
|
1010
|
+
> [data-part='list'] {
|
|
1011
|
+
border-block-end: 0;
|
|
1012
|
+
border-inline-end: var(--_track-size) solid CanvasText;
|
|
1013
|
+
padding-inline-end: 0;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/* The marker's ground would flatten to Canvas with every other ground. */
|
|
1017
|
+
[data-ui='tabs'] > :where([data-part='list']) > [data-part='marker'] {
|
|
1018
|
+
background-color: Highlight;
|
|
1019
|
+
forced-color-adjust: none;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
994
1022
|
[data-ui='tabs'][data-variant='contained']
|
|
995
1023
|
> :where([data-part='list'])
|
|
996
1024
|
> [data-part='item'][data-selected] {
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"--slotted-radius-full",
|
|
40
40
|
"--slotted-radius-md",
|
|
41
41
|
"--slotted-radius-sm",
|
|
42
|
-
"--slotted-radius-xs",
|
|
43
42
|
"--slotted-shadow-xs",
|
|
44
43
|
"--slotted-space-1",
|
|
45
44
|
"--slotted-space-2",
|
|
@@ -63,8 +62,12 @@
|
|
|
63
62
|
"--slotted-tabs-hover-background",
|
|
64
63
|
"--slotted-tabs-hover-color",
|
|
65
64
|
"--slotted-tabs-hover-marker-color",
|
|
65
|
+
"--slotted-tabs-hover-marker-opacity",
|
|
66
66
|
"--slotted-tabs-list-gap",
|
|
67
67
|
"--slotted-tabs-marker-color",
|
|
68
|
+
"--slotted-tabs-marker-inset",
|
|
69
|
+
"--slotted-tabs-marker-radius",
|
|
70
|
+
"--slotted-tabs-marker-size",
|
|
68
71
|
"--slotted-tabs-scroll-color",
|
|
69
72
|
"--slotted-tabs-selected-color",
|
|
70
73
|
"--slotted-tabs-track-color",
|