@slotted/styles 0.1.0-beta.10 → 0.1.0-beta.11
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/action-bar/action-bar.css +10 -16
- package/src/button/button.css +10 -4
- package/src/button-group/button-group.css +3 -2
- package/src/command-palette/command-palette.css +19 -0
- package/src/command-palette/command-palette.tokens.json +1 -0
- package/src/data-grid/data-grid.css +32 -2
- package/src/data-grid/data-grid.tokens.json +2 -0
- package/src/detail-panel/detail-panel.css +16 -1
- package/src/detail-panel/detail-panel.tokens.json +2 -0
- package/src/dialog/dialog.css +38 -0
- package/src/dialog/dialog.tokens.json +1 -0
- package/src/drawer/drawer.css +19 -1
- package/src/drawer/drawer.tokens.json +1 -0
- package/src/page/page.css +16 -0
- package/src/page/page.tokens.json +1 -0
- package/src/page-header/page-header.css +57 -4
- package/src/page-header/page-header.tokens.json +4 -0
- package/src/spinner/spinner.css +81 -35
- package/src/spinner/spinner.tokens.json +1 -0
- package/src/tabs/tabs.css +25 -18
- package/src/toast/toast.css +19 -0
- package/src/toast/toast.tokens.json +1 -0
package/package.json
CHANGED
|
@@ -380,6 +380,11 @@
|
|
|
380
380
|
* breakpoint is. While it is raised the collapse does not run: a column has
|
|
381
381
|
* room for every action, and a surface holding what did not fit would be a
|
|
382
382
|
* menu for nothing.
|
|
383
|
+
*
|
|
384
|
+
* A bar that holds an overflow control does not stack: it keeps one row, the
|
|
385
|
+
* actions without a counterpart stay and the rest fold into the menu. It
|
|
386
|
+
* stacked once, hid its control, and three actions with counterparts stood
|
|
387
|
+
* in a bar 164 pixels tall on a 358 pixel phone.
|
|
383
388
|
*/
|
|
384
389
|
@container slotted-action-bar (width < 24rem) {
|
|
385
390
|
/**
|
|
@@ -388,7 +393,7 @@
|
|
|
388
393
|
* the order a form is read in, and only the paint is reversed. `stretch`
|
|
389
394
|
* fills the column, because a column of natural widths is a ragged edge.
|
|
390
395
|
*/
|
|
391
|
-
[data-ui-action-bar] [data-part-actions] {
|
|
396
|
+
[data-ui-action-bar]:not(:has([data-part-overflow])) [data-part-actions] {
|
|
392
397
|
--_stacked: 1;
|
|
393
398
|
|
|
394
399
|
align-items: stretch;
|
|
@@ -397,26 +402,15 @@
|
|
|
397
402
|
margin-inline: 0;
|
|
398
403
|
}
|
|
399
404
|
|
|
400
|
-
[data-ui-action-bar] [data-part-action] > * {
|
|
405
|
+
[data-ui-action-bar]:not(:has([data-part-overflow])) [data-part-action] > * {
|
|
401
406
|
inline-size: 100%;
|
|
402
407
|
}
|
|
403
408
|
|
|
404
|
-
/**
|
|
405
|
-
* While the bar is a column there is no overflow, because a column has room
|
|
406
|
-
* for every action — the binding stops measuring, and the rule says the same
|
|
407
|
-
* thing on the side a reader is looking at. Without it the trigger is
|
|
408
|
-
* painted at the top of the column by the reversal, which is where the
|
|
409
|
-
* action that confirms belongs.
|
|
410
|
-
*/
|
|
411
|
-
[data-ui-action-bar] [data-part-overflow] {
|
|
412
|
-
display: none;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
409
|
/**
|
|
416
410
|
* A rule that divided two controls in a row divides two rows here, so it
|
|
417
411
|
* turns with them.
|
|
418
412
|
*/
|
|
419
|
-
[data-ui-action-bar] [data-part-separator] {
|
|
413
|
+
[data-ui-action-bar]:not(:has([data-part-overflow])) [data-part-separator] {
|
|
420
414
|
block-size: var(--slotted-border-width-thin, 1px);
|
|
421
415
|
inline-size: auto;
|
|
422
416
|
margin-block: calc(var(--_gap) / 2);
|
|
@@ -424,14 +418,14 @@
|
|
|
424
418
|
min-block-size: 0;
|
|
425
419
|
}
|
|
426
420
|
|
|
427
|
-
[data-ui-action-bar] [data-part-status] {
|
|
421
|
+
[data-ui-action-bar]:not(:has([data-part-overflow])) [data-part-status] {
|
|
428
422
|
flex: 1 1 100%;
|
|
429
423
|
}
|
|
430
424
|
|
|
431
425
|
/* What the consumer put in the status, addressed as the part's child and
|
|
432
426
|
never by a class of its own: while the bar is a column the status fills
|
|
433
427
|
the row, as an action does two rules above. */
|
|
434
|
-
[data-ui-action-bar] [data-part-status] > * {
|
|
428
|
+
[data-ui-action-bar]:not(:has([data-part-overflow])) [data-part-status] > * {
|
|
435
429
|
align-content: space-between;
|
|
436
430
|
inline-size: 100%;
|
|
437
431
|
}
|
package/src/button/button.css
CHANGED
|
@@ -676,14 +676,20 @@
|
|
|
676
676
|
}
|
|
677
677
|
|
|
678
678
|
/**
|
|
679
|
-
* The label
|
|
680
|
-
*
|
|
681
|
-
*
|
|
679
|
+
* The label is one line at its own width. It broke anywhere once, which made
|
|
680
|
+
* a button in a row as narrow as one letter: squeezed, "Corrigir" became
|
|
681
|
+
* three lines and broke inside the word. A row of buttons now overflows, or
|
|
682
|
+
* a toolbar folds what does not fit; a control held narrower than its label
|
|
683
|
+
* by its container — `max-inline-size: 100%` — cuts the label with an
|
|
684
|
+
* ellipsis rather than spilling it past the border. The line height is the
|
|
685
|
+
* text step's, which the trim below reads.
|
|
682
686
|
*/
|
|
683
687
|
[data-ui-button] [data-part-label] {
|
|
684
688
|
line-height: var(--slotted-line-height-sm, 1.45);
|
|
685
689
|
min-inline-size: 0;
|
|
686
|
-
overflow
|
|
690
|
+
overflow: hidden;
|
|
691
|
+
text-overflow: ellipsis;
|
|
692
|
+
white-space: nowrap;
|
|
687
693
|
}
|
|
688
694
|
|
|
689
695
|
/**
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* the ends of the bar and nowhere else — and states no distance between its
|
|
16
16
|
* controls. A joined bar does not wrap and does not stack: its shape is the
|
|
17
17
|
* whole point of it, and no surveyed implementation flips that shape at a
|
|
18
|
-
* width the consumer cannot see coming. A label that outgrows the bar
|
|
19
|
-
* inside its own control, which is `button`'s rule and not
|
|
18
|
+
* width the consumer cannot see coming. A label that outgrows the bar ends
|
|
19
|
+
* in an ellipsis inside its own control, which is `button`'s rule and not
|
|
20
|
+
* this family's.
|
|
20
21
|
*
|
|
21
22
|
* The children are the consumer's own elements, selected as direct children.
|
|
22
23
|
* Primer wraps each child in a div of its own and pays for it twice: its
|
|
@@ -135,6 +135,25 @@
|
|
|
135
135
|
overflow: clip;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* A theme draws the panel as a material with this filter beside a surface
|
|
140
|
+
* with alpha: `--slotted-command-palette-backdrop-filter`, `none` unless set.
|
|
141
|
+
* The root is the one layer that paints a ground under either presentation.
|
|
142
|
+
* A reader who asked for less transparency gets no filter, and under forced
|
|
143
|
+
* colours the ground is the system's.
|
|
144
|
+
*/
|
|
145
|
+
[data-ui-command-palette] {
|
|
146
|
+
-webkit-backdrop-filter: var(--slotted-command-palette-backdrop-filter, none);
|
|
147
|
+
backdrop-filter: var(--slotted-command-palette-backdrop-filter, none);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@media (prefers-reduced-transparency: reduce), (forced-colors: active) {
|
|
151
|
+
[data-ui-command-palette] {
|
|
152
|
+
-webkit-backdrop-filter: none;
|
|
153
|
+
backdrop-filter: none;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
138
157
|
/* ── Size ─────────────────────────────────────────────────────────────── */
|
|
139
158
|
|
|
140
159
|
[data-ui-command-palette][data-size='sm'] {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"--slotted-border-subtle",
|
|
3
3
|
"--slotted-border-width-thin",
|
|
4
4
|
"--slotted-command-palette-active",
|
|
5
|
+
"--slotted-command-palette-backdrop-filter",
|
|
5
6
|
"--slotted-command-palette-border-color",
|
|
6
7
|
"--slotted-command-palette-footer-surface",
|
|
7
8
|
"--slotted-command-palette-highlight",
|
|
@@ -812,10 +812,11 @@
|
|
|
812
812
|
|
|
813
813
|
/* The last column's handle stays inside the row: half a target hanging
|
|
814
814
|
past the last cell was twelve pixels of overflow on a row nothing could
|
|
815
|
-
scroll to.
|
|
815
|
+
scroll to. The last column header, not the row's last child: the pop-in
|
|
816
|
+
header follows it when columns yield to the frame. */
|
|
816
817
|
[data-ui-data-grid]
|
|
817
818
|
[data-part-header-row]
|
|
818
|
-
> [data-part-column-header]:
|
|
819
|
+
> [data-part-column-header]:not(:has(~ [data-part-column-header]))
|
|
819
820
|
> [data-part-resizer] {
|
|
820
821
|
inline-size: calc(var(--slotted-target-min, 24px) / 2);
|
|
821
822
|
inset-inline-end: 0;
|
|
@@ -840,6 +841,30 @@
|
|
|
840
841
|
background-color: var(--_cursor);
|
|
841
842
|
}
|
|
842
843
|
|
|
844
|
+
/**
|
|
845
|
+
* Under `resizeMode="deferred"` the drag moves this line and nothing else:
|
|
846
|
+
* it stands on the column's edge, spans the scroller's visible height and
|
|
847
|
+
* slides by `translate`, which lays nothing out; the width is applied once,
|
|
848
|
+
* on release.
|
|
849
|
+
*/
|
|
850
|
+
[data-ui-data-grid] [data-part-resizer] > [data-part-resize-guide] {
|
|
851
|
+
background-color: var(
|
|
852
|
+
--slotted-data-grid-resize-guide-color,
|
|
853
|
+
var(--slotted-focus-ring-color, Highlight)
|
|
854
|
+
);
|
|
855
|
+
inline-size: var(
|
|
856
|
+
--slotted-data-grid-resize-guide-width,
|
|
857
|
+
var(--slotted-border-width-thick, 2px)
|
|
858
|
+
);
|
|
859
|
+
inset-block-start: 0;
|
|
860
|
+
inset-inline-start: calc(
|
|
861
|
+
50% - var(--slotted-data-grid-resize-guide-width, var(--slotted-border-width-thick, 2px)) / 2
|
|
862
|
+
);
|
|
863
|
+
pointer-events: none;
|
|
864
|
+
position: absolute;
|
|
865
|
+
z-index: 2;
|
|
866
|
+
}
|
|
867
|
+
|
|
843
868
|
/**
|
|
844
869
|
* ── Reordering ─────────────────────────────────────────────────────────
|
|
845
870
|
*
|
|
@@ -2414,6 +2439,11 @@
|
|
|
2414
2439
|
* ── Scheme and platform ────────────────────────────────────────────────
|
|
2415
2440
|
*/
|
|
2416
2441
|
@media (forced-colors: active) {
|
|
2442
|
+
[data-ui-data-grid] [data-part-resizer] > [data-part-resize-guide] {
|
|
2443
|
+
background-color: Highlight;
|
|
2444
|
+
forced-color-adjust: none;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2417
2447
|
[data-ui-data-grid] [role='gridcell'][data-current],
|
|
2418
2448
|
[data-ui-data-grid] [role='columnheader'][data-current] {
|
|
2419
2449
|
box-shadow: inset 0 0 0 var(--_ring-width) Highlight;
|
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
"--slotted-data-grid-pin-shadow-size",
|
|
46
46
|
"--slotted-data-grid-radius",
|
|
47
47
|
"--slotted-data-grid-range-surface",
|
|
48
|
+
"--slotted-data-grid-resize-guide-color",
|
|
49
|
+
"--slotted-data-grid-resize-guide-width",
|
|
48
50
|
"--slotted-data-grid-row-block-size",
|
|
49
51
|
"--slotted-data-grid-row-color-selected",
|
|
50
52
|
"--slotted-data-grid-row-max-block-size",
|
|
@@ -318,7 +318,9 @@
|
|
|
318
318
|
* column above.
|
|
319
319
|
*/
|
|
320
320
|
[data-ui-detail-panel] > [data-part-footer] {
|
|
321
|
-
|
|
321
|
+
-webkit-backdrop-filter: var(--slotted-detail-panel-footer-backdrop-filter, none);
|
|
322
|
+
backdrop-filter: var(--slotted-detail-panel-footer-backdrop-filter, none);
|
|
323
|
+
background-color: var(--slotted-detail-panel-footer-background, var(--_ground));
|
|
322
324
|
border-block-start: var(--_rule-size) solid var(--_rule);
|
|
323
325
|
inset-block-end: var(--slotted-page-sticky-bottom, 0px);
|
|
324
326
|
margin-block-start: auto;
|
|
@@ -326,4 +328,17 @@
|
|
|
326
328
|
position: sticky;
|
|
327
329
|
z-index: var(--slotted-z-index-sticky, 100);
|
|
328
330
|
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* A theme draws the footer as a material with its own ground and filter,
|
|
334
|
+
* apart from the ground a sticky section header reads. A reader who asked
|
|
335
|
+
* for less transparency gets no filter, and under forced colours the ground
|
|
336
|
+
* is the system's.
|
|
337
|
+
*/
|
|
338
|
+
@media (prefers-reduced-transparency: reduce), (forced-colors: active) {
|
|
339
|
+
[data-ui-detail-panel] > [data-part-footer] {
|
|
340
|
+
-webkit-backdrop-filter: none;
|
|
341
|
+
backdrop-filter: none;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
329
344
|
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
"--slotted-detail-panel-aside-size-md",
|
|
7
7
|
"--slotted-detail-panel-aside-size-sm",
|
|
8
8
|
"--slotted-detail-panel-border",
|
|
9
|
+
"--slotted-detail-panel-footer-backdrop-filter",
|
|
10
|
+
"--slotted-detail-panel-footer-background",
|
|
9
11
|
"--slotted-detail-panel-gap-lg",
|
|
10
12
|
"--slotted-detail-panel-gap-md",
|
|
11
13
|
"--slotted-detail-panel-gap-sm",
|
package/src/dialog/dialog.css
CHANGED
|
@@ -356,6 +356,21 @@
|
|
|
356
356
|
*/
|
|
357
357
|
opacity: 0;
|
|
358
358
|
transition: opacity var(--slotted-duration-short) var(--slotted-easing-exit);
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* A theme draws the panel as a material with a surface that has alpha and
|
|
362
|
+
* this filter, `none` unless set. The panel's own fade keeps the filter
|
|
363
|
+
* drawn; an ancestor's opacity below one is what removes it.
|
|
364
|
+
*/
|
|
365
|
+
-webkit-backdrop-filter: var(--slotted-dialog-backdrop-filter, none);
|
|
366
|
+
backdrop-filter: var(--slotted-dialog-backdrop-filter, none);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
@media (prefers-reduced-transparency: reduce), (forced-colors: active) {
|
|
370
|
+
[data-ui-dialog] > [data-part-viewport] > [data-part-content] {
|
|
371
|
+
-webkit-backdrop-filter: none;
|
|
372
|
+
backdrop-filter: none;
|
|
373
|
+
}
|
|
359
374
|
}
|
|
360
375
|
|
|
361
376
|
/**
|
|
@@ -1045,6 +1060,29 @@
|
|
|
1045
1060
|
overflow: visible;
|
|
1046
1061
|
}
|
|
1047
1062
|
|
|
1063
|
+
/**
|
|
1064
|
+
* The children fade in the panel's place, at the panel's durations. A plain
|
|
1065
|
+
* panel paints nothing, so the picture is the same; what changes is that no
|
|
1066
|
+
* ancestor of a child's material is below full opacity, which in Chromium
|
|
1067
|
+
* would draw no backdrop filter until the fade ended — a command palette
|
|
1068
|
+
* drawn as a material showed the page sharp behind it for the whole fade.
|
|
1069
|
+
*/
|
|
1070
|
+
[data-ui-dialog][data-surface='plain'] > [data-part-viewport] > [data-part-content] {
|
|
1071
|
+
opacity: 1;
|
|
1072
|
+
transition: none;
|
|
1073
|
+
}
|
|
1074
|
+
[data-ui-dialog][data-surface='plain'] > [data-part-viewport] > [data-part-content] > * {
|
|
1075
|
+
opacity: 0;
|
|
1076
|
+
transition: opacity var(--slotted-duration-short) var(--slotted-easing-exit);
|
|
1077
|
+
}
|
|
1078
|
+
[data-ui-dialog][data-surface='plain'][data-open]
|
|
1079
|
+
> [data-part-viewport]
|
|
1080
|
+
> [data-part-content]
|
|
1081
|
+
> * {
|
|
1082
|
+
opacity: 1;
|
|
1083
|
+
transition: opacity var(--slotted-duration-long) var(--slotted-easing-standard);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1048
1086
|
[data-ui-dialog][data-surface='plain']
|
|
1049
1087
|
> [data-part-viewport]
|
|
1050
1088
|
> [data-part-content]
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"--slotted-control-radius",
|
|
9
9
|
"--slotted-control-transition-duration",
|
|
10
10
|
"--slotted-control-transition-easing",
|
|
11
|
+
"--slotted-dialog-backdrop-filter",
|
|
11
12
|
"--slotted-dialog-body-color",
|
|
12
13
|
"--slotted-dialog-border-color",
|
|
13
14
|
"--slotted-dialog-close-active-background",
|
package/src/drawer/drawer.css
CHANGED
|
@@ -412,7 +412,9 @@
|
|
|
412
412
|
transition:
|
|
413
413
|
translate var(--_slide),
|
|
414
414
|
inline-size var(--_move),
|
|
415
|
-
block-size var(--_move)
|
|
415
|
+
block-size var(--_move),
|
|
416
|
+
border-start-start-radius var(--_move),
|
|
417
|
+
border-start-end-radius var(--_move);
|
|
416
418
|
}
|
|
417
419
|
|
|
418
420
|
[data-ui-drawer][data-mode='overlay']:not([data-open]) > [data-part-panel] {
|
|
@@ -525,6 +527,22 @@
|
|
|
525
527
|
border-start-end-radius: var(--slotted-drawer-radius, var(--_radius));
|
|
526
528
|
}
|
|
527
529
|
|
|
530
|
+
/**
|
|
531
|
+
* A sheet that reaches the top of the layer is the screen, Material 3's
|
|
532
|
+
* expanded bottom sheet: its top corners square — a theme keeps a radius
|
|
533
|
+
* with `--slotted-drawer-radius-expanded` — and its header clears the safe
|
|
534
|
+
* area the status bar takes. The binding writes `data-expanded` while the
|
|
535
|
+
* extent is the whole layer, and under `size="full"`.
|
|
536
|
+
*/
|
|
537
|
+
[data-ui-drawer][data-side='bottom'][data-expanded] > [data-part-panel] {
|
|
538
|
+
border-start-start-radius: var(--slotted-drawer-radius-expanded, 0px);
|
|
539
|
+
border-start-end-radius: var(--slotted-drawer-radius-expanded, 0px);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
[data-ui-drawer][data-side='bottom'][data-expanded] > [data-part-panel] > [data-part-header] {
|
|
543
|
+
padding-block-start: calc(var(--_padding-block) + env(safe-area-inset-top, 0px));
|
|
544
|
+
}
|
|
545
|
+
|
|
528
546
|
/**
|
|
529
547
|
* A sheet's separator takes the first row, so the three that follow move down
|
|
530
548
|
* one. `top` needs no such rule: its separator is the fourth row and the
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"--slotted-drawer-extent-xl",
|
|
24
24
|
"--slotted-drawer-footer-surface",
|
|
25
25
|
"--slotted-drawer-radius",
|
|
26
|
+
"--slotted-drawer-radius-expanded",
|
|
26
27
|
"--slotted-drawer-resizer-line-active-color",
|
|
27
28
|
"--slotted-drawer-resizer-line-color",
|
|
28
29
|
"--slotted-drawer-rule-color",
|
package/src/page/page.css
CHANGED
|
@@ -147,6 +147,22 @@
|
|
|
147
147
|
translate: 0 100%;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* A theme draws the footer as a material with a ground that has alpha and
|
|
152
|
+
* `--slotted-page-footer-backdrop-filter`, `none` unless set. The footer's
|
|
153
|
+
* own fade keeps the filter drawn: only an ancestor's opacity removes it.
|
|
154
|
+
*/
|
|
155
|
+
[data-ui-page] > [data-part-footer] {
|
|
156
|
+
-webkit-backdrop-filter: var(--slotted-page-footer-backdrop-filter, none);
|
|
157
|
+
backdrop-filter: var(--slotted-page-footer-backdrop-filter, none);
|
|
158
|
+
}
|
|
159
|
+
@media (prefers-reduced-transparency: reduce), (forced-colors: active) {
|
|
160
|
+
[data-ui-page] > [data-part-footer] {
|
|
161
|
+
-webkit-backdrop-filter: none;
|
|
162
|
+
backdrop-filter: none;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
150
166
|
[data-ui-page] > [data-part-footer] > * > [data-part-actions] {
|
|
151
167
|
align-items: center;
|
|
152
168
|
display: flex;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"--slotted-font-family-sans",
|
|
8
8
|
"--slotted-page-background-sunken",
|
|
9
9
|
"--slotted-page-background-surface",
|
|
10
|
+
"--slotted-page-footer-backdrop-filter",
|
|
10
11
|
"--slotted-page-footer-background",
|
|
11
12
|
"--slotted-page-footer-border",
|
|
12
13
|
"--slotted-page-footer-padding-block",
|
|
@@ -77,6 +77,14 @@
|
|
|
77
77
|
--_rule-size: var(--slotted-border-width-thin, 1px);
|
|
78
78
|
--_duration: var(--slotted-duration-medium);
|
|
79
79
|
--_easing: var(--slotted-easing-standard, cubic-bezier(0.2, 0, 0, 1));
|
|
80
|
+
/**
|
|
81
|
+
* How the ground changes when `plain` takes it back, or a material takes
|
|
82
|
+
* over, as content passes under the chrome. A duration of nought makes the
|
|
83
|
+
* change instant.
|
|
84
|
+
*/
|
|
85
|
+
--_ground-transition: background-color
|
|
86
|
+
var(--slotted-page-header-ground-duration, var(--_duration))
|
|
87
|
+
var(--slotted-page-header-ground-easing, var(--_easing));
|
|
80
88
|
|
|
81
89
|
background-color: var(--_ground);
|
|
82
90
|
color: var(--_text);
|
|
@@ -98,7 +106,9 @@
|
|
|
98
106
|
* is the slide of the header area under the title and never a fight with
|
|
99
107
|
* the scroll, during which the offset is constant.
|
|
100
108
|
*/
|
|
101
|
-
transition:
|
|
109
|
+
transition:
|
|
110
|
+
inset-block-start var(--_duration) var(--_easing),
|
|
111
|
+
var(--_ground-transition);
|
|
102
112
|
/**
|
|
103
113
|
* Above every other sticky thing on the page — a section's header, a
|
|
104
114
|
* table's column header, a pinned corner — so what a short section pushes
|
|
@@ -189,7 +199,9 @@
|
|
|
189
199
|
[data-ui-page-header][data-variant='floating'] > * > [data-part-title-area] {
|
|
190
200
|
border-start-end-radius: calc(var(--_radius) - var(--_rule-size));
|
|
191
201
|
border-start-start-radius: calc(var(--_radius) - var(--_rule-size));
|
|
192
|
-
transition:
|
|
202
|
+
transition:
|
|
203
|
+
inset-block-start var(--_duration) var(--_easing),
|
|
204
|
+
var(--_ground-transition);
|
|
193
205
|
}
|
|
194
206
|
[data-ui-page-header][data-variant='floating'][data-stuck] {
|
|
195
207
|
--_sticky-inset: var(--slotted-page-header-inset, var(--slotted-space-4, 0.5rem));
|
|
@@ -231,6 +243,7 @@
|
|
|
231
243
|
overflow-anchor: none;
|
|
232
244
|
padding-block: var(--_padding-block) var(--slotted-space-4, 0.5rem);
|
|
233
245
|
position: sticky;
|
|
246
|
+
transition: var(--_ground-transition);
|
|
234
247
|
z-index: 2;
|
|
235
248
|
}
|
|
236
249
|
|
|
@@ -254,8 +267,24 @@
|
|
|
254
267
|
* transparent at rest, filters nothing at rest.
|
|
255
268
|
*/
|
|
256
269
|
[data-ui-page-header][data-stuck] {
|
|
257
|
-
-webkit-backdrop-filter: var(--slotted-page-header-backdrop-filter, none);
|
|
258
|
-
backdrop-filter: var(--slotted-page-header-backdrop-filter, none);
|
|
270
|
+
-webkit-backdrop-filter: var(--slotted-page-header-backdrop-filter, var(--_backdrop, none));
|
|
271
|
+
backdrop-filter: var(--slotted-page-header-backdrop-filter, var(--_backdrop, none));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* `material`: stuck, the chrome is the theme's material — the ground
|
|
276
|
+
* `--slotted-surface-material` and the filter `--slotted-material-backdrop`
|
|
277
|
+
* — in every variant. At rest each variant keeps its own ground. The family
|
|
278
|
+
* tokens still win, and the pill keeps the opaque surface, because half of
|
|
279
|
+
* it hangs below the root over content the root's filter does not reach.
|
|
280
|
+
* The theme makes both material tokens opaque under reduced transparency.
|
|
281
|
+
*/
|
|
282
|
+
[data-ui-page-header][data-material][data-stuck] {
|
|
283
|
+
--_ground: var(
|
|
284
|
+
--slotted-page-header-background,
|
|
285
|
+
var(--slotted-surface-material, var(--_surface))
|
|
286
|
+
);
|
|
287
|
+
--_backdrop: var(--slotted-material-backdrop, none);
|
|
259
288
|
}
|
|
260
289
|
|
|
261
290
|
/**
|
|
@@ -1138,6 +1167,30 @@
|
|
|
1138
1167
|
> [data-part-marks] {
|
|
1139
1168
|
grid-column: 1 / -1;
|
|
1140
1169
|
}
|
|
1170
|
+
/* A rich title — a visual, marks or a subheading — leaves a whole row free under it, and a toolbar
|
|
1171
|
+
that folds takes that row: beside the title it had the 40 per cent the title left, and
|
|
1172
|
+
folded every action on a 390 pixel phone. Beside a plain title it stays on the title row. */
|
|
1173
|
+
[data-ui-page-header]
|
|
1174
|
+
> *
|
|
1175
|
+
> [data-part-title-area]
|
|
1176
|
+
> [data-part-title-row]:has(
|
|
1177
|
+
> [data-part-actions] > [data-ui-toolbar][data-overflow='menu']
|
|
1178
|
+
):has(
|
|
1179
|
+
> [data-part-visual],
|
|
1180
|
+
> [data-part-title] > :is([data-part-subheading], [data-part-marks]:not(:empty))
|
|
1181
|
+
) {
|
|
1182
|
+
flex-wrap: wrap;
|
|
1183
|
+
}
|
|
1184
|
+
[data-ui-page-header]
|
|
1185
|
+
> *
|
|
1186
|
+
> [data-part-title-area]
|
|
1187
|
+
> [data-part-title-row]:has(
|
|
1188
|
+
> [data-part-visual],
|
|
1189
|
+
> [data-part-title] > :is([data-part-subheading], [data-part-marks]:not(:empty))
|
|
1190
|
+
)
|
|
1191
|
+
> [data-part-actions]:has(> [data-ui-toolbar][data-overflow='menu']) {
|
|
1192
|
+
flex: 1 1 100%;
|
|
1193
|
+
}
|
|
1141
1194
|
/* One line, as snapped: the phone has no second one to give it. */
|
|
1142
1195
|
[data-ui-page-header]
|
|
1143
1196
|
> *
|
|
@@ -31,12 +31,15 @@
|
|
|
31
31
|
"--slotted-line-height-md",
|
|
32
32
|
"--slotted-line-height-sm",
|
|
33
33
|
"--slotted-line-height-xl",
|
|
34
|
+
"--slotted-material-backdrop",
|
|
34
35
|
"--slotted-page-header-backdrop-filter",
|
|
35
36
|
"--slotted-page-header-background",
|
|
36
37
|
"--slotted-page-header-border",
|
|
37
38
|
"--slotted-page-header-control-size",
|
|
38
39
|
"--slotted-page-header-description-measure",
|
|
39
40
|
"--slotted-page-header-gap",
|
|
41
|
+
"--slotted-page-header-ground-duration",
|
|
42
|
+
"--slotted-page-header-ground-easing",
|
|
40
43
|
"--slotted-page-header-heading-size-lg",
|
|
41
44
|
"--slotted-page-header-heading-size-md",
|
|
42
45
|
"--slotted-page-header-heading-size-sm",
|
|
@@ -58,6 +61,7 @@
|
|
|
58
61
|
"--slotted-space-5",
|
|
59
62
|
"--slotted-space-6",
|
|
60
63
|
"--slotted-surface",
|
|
64
|
+
"--slotted-surface-material",
|
|
61
65
|
"--slotted-target-comfortable",
|
|
62
66
|
"--slotted-target-min",
|
|
63
67
|
"--slotted-text",
|
package/src/spinner/spinner.css
CHANGED
|
@@ -8,19 +8,25 @@
|
|
|
8
8
|
* chases itself around a faint track, growing from its head and closing
|
|
9
9
|
* from its tail, so the eye reads work rather than a wheel.
|
|
10
10
|
*
|
|
11
|
-
* The drawing is vector
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* nothing is cut at a fractional edge.
|
|
11
|
+
* The drawing is vector and inline: the host writes an `svg` of two circles
|
|
12
|
+
* inside the box, the track and the arc, stroked in the host's ink. No
|
|
13
|
+
* image is fetched. The ring was two SVG images used as masks, written as
|
|
14
|
+
* `data:` URLs, and a page whose policy allows images from its own origin
|
|
15
|
+
* alone refused both: the ring was absent.
|
|
17
16
|
*
|
|
18
|
-
*
|
|
19
|
-
* mask,
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
17
|
+
* The turn is the box's `rotate`, which the compositor runs: the arc used to
|
|
18
|
+
* turn inside the mask image, which is rasterised again on the main thread
|
|
19
|
+
* for every frame, and with the main thread busy for two seconds the ring
|
|
20
|
+
* drew no frame at all (`tools/harness/scenarios/spinner-busy.mjs`). The
|
|
21
|
+
* dash still opens and travels on the main thread; under load the arc keeps
|
|
22
|
+
* turning at the length it had.
|
|
23
|
+
*
|
|
24
|
+
* It was gradients before the masks — a conic arc, two radial caps and a
|
|
25
|
+
* radial mask, three angles animated as custom properties. A conic
|
|
26
|
+
* gradient's hard stop has no antialiasing, so the arc stepped from frame to
|
|
27
|
+
* frame like a GIF, and the half-pixel stops of the caps and the mask
|
|
28
|
+
* blurred a ring of thirteen pixels. A stroke has round caps and is
|
|
29
|
+
* antialiased at every size.
|
|
24
30
|
*
|
|
25
31
|
* The geometry is the icon set's: in a box of twenty-four units the ring is
|
|
26
32
|
* twenty across and the stroke is two and a quarter, so the swap with a
|
|
@@ -28,31 +34,20 @@
|
|
|
28
34
|
*/
|
|
29
35
|
[data-ui-spinner] {
|
|
30
36
|
--_size: var(--slotted-spinner-size, var(--slotted-control-icon-size-md, 16px));
|
|
31
|
-
--_track: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='8.875' fill='none' stroke='%23000' stroke-opacity='0.2' stroke-width='2.25'/%3E%3C/svg%3E");
|
|
32
|
-
/*
|
|
33
|
-
* The arc: a dash of one to seventy hundredths of the circle that opens
|
|
34
|
-
* in the first half of the cycle and travels on in the second, while the
|
|
35
|
-
* whole circle turns under it. Each half eases on its own.
|
|
36
|
-
*/
|
|
37
|
-
--_arc: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 12 12' to='360 12 12' dur='2s' repeatCount='indefinite'/%3E%3Ccircle cx='12' cy='12' r='8.875' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' pathLength='100' stroke-dasharray='1 150' transform='rotate(-90 12 12)'%3E%3Canimate attributeName='stroke-dasharray' values='1 150;70 150;70 150' keyTimes='0;0.5;1' calcMode='spline' keySplines='0.42 0 0.58 1;0.42 0 0.58 1' dur='1.5s' repeatCount='indefinite'/%3E%3Canimate attributeName='stroke-dashoffset' values='0;-28;-99' keyTimes='0;0.5;1' calcMode='spline' keySplines='0.42 0 0.58 1;0.42 0 0.58 1' dur='1.5s' repeatCount='indefinite'/%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
/* A turn and a dash out of step, so the arc never comes back to the same place. */
|
|
39
|
+
animation: slotted-spinner-turn calc(var(--slotted-duration-loop-slow) * 1.25) linear infinite;
|
|
40
40
|
block-size: var(--_size);
|
|
41
|
+
color: inherit;
|
|
41
42
|
display: inline-block;
|
|
42
43
|
/* A ring that shrinks is not a ring: it keeps its size in a flex row. */
|
|
43
44
|
flex: none;
|
|
44
45
|
/*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* the box stay. Not adjusting keeps `currentcolor`, the host's ink, which
|
|
48
|
-
* forced colours have already set.
|
|
46
|
+
* Not adjusting keeps `currentcolor`, the host's ink, which forced colours
|
|
47
|
+
* have already set, on a stroke the system would otherwise repaint.
|
|
49
48
|
*/
|
|
50
49
|
forced-color-adjust: none;
|
|
51
50
|
inline-size: var(--_size);
|
|
52
|
-
mask-image: var(--_arc), var(--_track);
|
|
53
|
-
mask-position: center;
|
|
54
|
-
mask-repeat: no-repeat;
|
|
55
|
-
mask-size: 100% 100%;
|
|
56
51
|
opacity: 1;
|
|
57
52
|
scale: 1;
|
|
58
53
|
transition:
|
|
@@ -61,6 +56,56 @@
|
|
|
61
56
|
vertical-align: middle;
|
|
62
57
|
}
|
|
63
58
|
|
|
59
|
+
[data-ui-spinner] > svg {
|
|
60
|
+
block-size: 100%;
|
|
61
|
+
display: block;
|
|
62
|
+
fill: none;
|
|
63
|
+
inline-size: 100%;
|
|
64
|
+
stroke: currentColor;
|
|
65
|
+
stroke-width: 2.25;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* The track: the whole circle at a fifth of the ink's strength. */
|
|
69
|
+
[data-ui-spinner] > svg > circle:first-child {
|
|
70
|
+
stroke-opacity: 0.2;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* The arc: a dash of one to seventy hundredths of the circle that opens in
|
|
75
|
+
* the first half of the cycle and travels on in the second, from the top.
|
|
76
|
+
* Each half eases on its own.
|
|
77
|
+
*/
|
|
78
|
+
[data-ui-spinner] > svg > circle:last-child {
|
|
79
|
+
animation: slotted-spinner-arc var(--slotted-duration-loop-slow) infinite;
|
|
80
|
+
rotate: -90deg;
|
|
81
|
+
stroke-dasharray: 1 150;
|
|
82
|
+
stroke-linecap: round;
|
|
83
|
+
transform-origin: center;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@keyframes slotted-spinner-turn {
|
|
87
|
+
to {
|
|
88
|
+
rotate: 360deg;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@keyframes slotted-spinner-arc {
|
|
93
|
+
0% {
|
|
94
|
+
animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
|
|
95
|
+
stroke-dasharray: 1 150;
|
|
96
|
+
stroke-dashoffset: 0;
|
|
97
|
+
}
|
|
98
|
+
50% {
|
|
99
|
+
animation-timing-function: cubic-bezier(0.42, 0, 0.58, 1);
|
|
100
|
+
stroke-dasharray: 70 150;
|
|
101
|
+
stroke-dashoffset: -28;
|
|
102
|
+
}
|
|
103
|
+
100% {
|
|
104
|
+
stroke-dasharray: 70 150;
|
|
105
|
+
stroke-dashoffset: -99;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
64
109
|
@starting-style {
|
|
65
110
|
[data-ui-spinner] {
|
|
66
111
|
opacity: 0;
|
|
@@ -68,14 +113,15 @@
|
|
|
68
113
|
}
|
|
69
114
|
}
|
|
70
115
|
|
|
71
|
-
|
|
72
|
-
* A frozen ring still communicates waiting: the track, and an arc of three
|
|
73
|
-
* quarters resting on it. Stopping it entirely is less distracting than
|
|
74
|
-
* replacing one continuous motion with a slower one.
|
|
75
|
-
*/
|
|
116
|
+
/* Still: a track with an arc of three quarters resting on it. */
|
|
76
117
|
@media (prefers-reduced-motion: reduce) {
|
|
77
|
-
[data-ui-spinner]
|
|
78
|
-
|
|
118
|
+
[data-ui-spinner],
|
|
119
|
+
[data-ui-spinner] > svg > circle:last-child {
|
|
120
|
+
animation: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
[data-ui-spinner] > svg > circle:last-child {
|
|
124
|
+
stroke-dasharray: 75 150;
|
|
79
125
|
}
|
|
80
126
|
}
|
|
81
127
|
}
|
package/src/tabs/tabs.css
CHANGED
|
@@ -464,10 +464,12 @@
|
|
|
464
464
|
* label it keeps a minimum length, centred on the content. It stands
|
|
465
465
|
* `--slotted-tabs-marker-offset` above the list's edge, over the track, and the axes are physical in this one rule
|
|
466
466
|
* because the measurement is: the position is from the list's left edge.
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
467
|
+
* At rest the bar is laid out by `left` and `inline-size`, so its ends keep
|
|
468
|
+
* their radius; it slides by `translate` and `scale` together, both on the
|
|
469
|
+
* compositor, so both edges advance in the same frame. A composited
|
|
470
|
+
* `translate` beside a main-thread `inline-size` drifted apart while the
|
|
471
|
+
* panel rendered, and a slide of `left` and `inline-size` lost every frame
|
|
472
|
+
* to a panel rendering on the same thread.
|
|
471
473
|
*/
|
|
472
474
|
[data-ui-tabs] > :where([data-part-list]) > [data-part-marker] {
|
|
473
475
|
--_start-inset: var(--_marker-inset);
|
|
@@ -503,28 +505,33 @@
|
|
|
503
505
|
}
|
|
504
506
|
|
|
505
507
|
/**
|
|
506
|
-
* It slides only when the selection moves: `
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
* duration on
|
|
512
|
-
*
|
|
513
|
-
*
|
|
508
|
+
* It slides only when the selection moves: `createIndicator` places the bar
|
|
509
|
+
* on the new tab, writes the shift and the scale from the box it was drawn
|
|
510
|
+
* in, and raises `data-moving`, which starts the slide from there back to
|
|
511
|
+
* nought; a re-measurement of the same tab drops it, so the first position,
|
|
512
|
+
* a font arriving and a resized list place the bar without motion. The slide
|
|
513
|
+
* takes the medium duration on a curve that starts and ends slowly,
|
|
514
|
+
* `--slotted-tabs-marker-easing`: the control duration on the theme's
|
|
515
|
+
* decelerating curve covered a third of the distance in its first frame and
|
|
516
|
+
* read as a jump. Under reduced motion it jumps.
|
|
514
517
|
*/
|
|
515
518
|
[data-ui-tabs] > :where([data-part-list]) > [data-part-marker][data-moving] {
|
|
516
519
|
--_marker-easing: var(--slotted-tabs-marker-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
517
520
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
521
|
+
animation: slotted-tabs-marker-slide var(--slotted-duration-medium) var(--_marker-easing);
|
|
522
|
+
transform-origin: 0 0;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
@keyframes slotted-tabs-marker-slide {
|
|
526
|
+
from {
|
|
527
|
+
translate: var(--_indicator-shift, 0px 0px);
|
|
528
|
+
scale: var(--_indicator-scale, 1 1);
|
|
529
|
+
}
|
|
523
530
|
}
|
|
524
531
|
|
|
525
532
|
@media (prefers-reduced-motion: reduce) {
|
|
526
533
|
[data-ui-tabs] > :where([data-part-list]) > [data-part-marker][data-moving] {
|
|
527
|
-
|
|
534
|
+
animation: none;
|
|
528
535
|
}
|
|
529
536
|
}
|
|
530
537
|
|
package/src/toast/toast.css
CHANGED
|
@@ -381,6 +381,25 @@
|
|
|
381
381
|
* tone is in the mark and in nothing else, which is enough — it is the
|
|
382
382
|
* silhouette that survives forced colours anyway.
|
|
383
383
|
*/
|
|
384
|
+
/**
|
|
385
|
+
* A theme that paints the raised message with a surface that has alpha blurs
|
|
386
|
+
* what passes under it: `--slotted-toast-backdrop-filter`, `none` unless set.
|
|
387
|
+
* Only `raised` floats over content it does not own; `soft` and `solid` are
|
|
388
|
+
* tone grounds. A reader who asked for less transparency gets no filter, and
|
|
389
|
+
* under forced colours the ground is the system's.
|
|
390
|
+
*/
|
|
391
|
+
[data-ui-toast] > [data-part-list] > [data-part-item][data-variant='raised'] {
|
|
392
|
+
-webkit-backdrop-filter: var(--slotted-toast-backdrop-filter, none);
|
|
393
|
+
backdrop-filter: var(--slotted-toast-backdrop-filter, none);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@media (prefers-reduced-transparency: reduce), (forced-colors: active) {
|
|
397
|
+
[data-ui-toast] > [data-part-list] > [data-part-item][data-variant='raised'] {
|
|
398
|
+
-webkit-backdrop-filter: none;
|
|
399
|
+
backdrop-filter: none;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
384
403
|
[data-ui-toast] > [data-part-list] > [data-part-item][data-variant='soft'] {
|
|
385
404
|
--_ground: var(--_tone-surface);
|
|
386
405
|
--_edge: var(--_tone-border);
|