@slotted/styles 0.0.0-stage → 0.1.0-beta.1
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/LICENSE +21 -0
- package/README.md +10 -2
- package/package.json +276 -3
- package/src/accordion/accordion.css +96 -0
- package/src/accordion/accordion.tokens.json +14 -0
- package/src/action-bar/action-bar.css +455 -0
- package/src/action-bar/action-bar.tokens.json +50 -0
- package/src/action-sheet/action-sheet.css +462 -0
- package/src/action-sheet/action-sheet.tokens.json +59 -0
- package/src/alert/alert.css +764 -0
- package/src/alert/alert.tokens.json +77 -0
- package/src/app-shell/app-shell.css +1899 -0
- package/src/app-shell/app-shell.tokens.json +88 -0
- package/src/aspect-ratio/aspect-ratio.css +131 -0
- package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
- package/src/attachment/attachment.css +906 -0
- package/src/attachment/attachment.tokens.json +85 -0
- package/src/avatar/avatar.css +598 -0
- package/src/avatar/avatar.tokens.json +64 -0
- package/src/avatar-group/avatar-group.css +268 -0
- package/src/avatar-group/avatar-group.tokens.json +16 -0
- package/src/badge/badge.css +462 -0
- package/src/badge/badge.tokens.json +58 -0
- package/src/breadcrumb/breadcrumb.css +441 -0
- package/src/breadcrumb/breadcrumb.tokens.json +50 -0
- package/src/button/button.css +754 -0
- package/src/button/button.tokens.json +72 -0
- package/src/button-group/button-group.css +455 -0
- package/src/button-group/button-group.tokens.json +11 -0
- package/src/calendar/calendar.css +846 -0
- package/src/calendar/calendar.tokens.json +67 -0
- package/src/card/card.css +602 -0
- package/src/card/card.tokens.json +68 -0
- package/src/carousel/carousel.css +860 -0
- package/src/carousel/carousel.tokens.json +62 -0
- package/src/cascader/cascader.css +1320 -0
- package/src/cascader/cascader.tokens.json +103 -0
- package/src/chart/chart.css +1473 -0
- package/src/chart/chart.tokens.json +107 -0
- package/src/checkbox/checkbox.css +1011 -0
- package/src/checkbox/checkbox.tokens.json +102 -0
- package/src/checkbox-group/checkbox-group.css +70 -0
- package/src/checkbox-group/checkbox-group.tokens.json +6 -0
- package/src/code-block/code-block.css +555 -0
- package/src/code-block/code-block.tokens.json +69 -0
- package/src/collapsible/collapsible.css +546 -0
- package/src/collapsible/collapsible.tokens.json +55 -0
- package/src/color-picker/color-picker.css +607 -0
- package/src/color-picker/color-picker.tokens.json +58 -0
- package/src/column-manager/column-manager.css +452 -0
- package/src/column-manager/column-manager.tokens.json +43 -0
- package/src/combobox/combobox.css +1048 -0
- package/src/combobox/combobox.tokens.json +112 -0
- package/src/command-palette/command-palette.css +1000 -0
- package/src/command-palette/command-palette.tokens.json +75 -0
- package/src/container/container.css +198 -0
- package/src/container/container.tokens.json +18 -0
- package/src/context-menu/context-menu.css +104 -0
- package/src/context-menu/context-menu.tokens.json +11 -0
- package/src/currency-field/currency-field.css +787 -0
- package/src/currency-field/currency-field.tokens.json +80 -0
- package/src/dashboard-grid/dashboard-grid.css +748 -0
- package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
- package/src/data-grid/data-grid.css +2484 -0
- package/src/data-grid/data-grid.tokens.json +100 -0
- package/src/data-list/data-list.css +455 -0
- package/src/data-list/data-list.tokens.json +35 -0
- package/src/date-field/date-field.css +560 -0
- package/src/date-field/date-field.tokens.json +80 -0
- package/src/date-picker/date-picker.css +420 -0
- package/src/date-picker/date-picker.tokens.json +49 -0
- package/src/date-range-picker/date-range-picker.css +983 -0
- package/src/date-range-picker/date-range-picker.tokens.json +109 -0
- package/src/datetime-field/datetime-field.css +850 -0
- package/src/datetime-field/datetime-field.tokens.json +91 -0
- package/src/datetime-picker/datetime-picker.css +843 -0
- package/src/datetime-picker/datetime-picker.tokens.json +78 -0
- package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
- package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
- package/src/description-list/description-list.css +675 -0
- package/src/description-list/description-list.tokens.json +66 -0
- package/src/detail-panel/detail-panel.css +329 -0
- package/src/detail-panel/detail-panel.tokens.json +33 -0
- package/src/dialog/dialog.css +968 -0
- package/src/dialog/dialog.tokens.json +66 -0
- package/src/divider/divider.css +131 -0
- package/src/divider/divider.tokens.json +18 -0
- package/src/drawer/drawer.css +1303 -0
- package/src/drawer/drawer.tokens.json +75 -0
- package/src/entity-picker/entity-picker.css +1367 -0
- package/src/entity-picker/entity-picker.tokens.json +118 -0
- package/src/event-calendar/event-calendar.css +2148 -0
- package/src/event-calendar/event-calendar.tokens.json +87 -0
- package/src/field/field.css +707 -0
- package/src/field/field.tokens.json +58 -0
- package/src/field-group/field-group.css +226 -0
- package/src/field-group/field-group.tokens.json +33 -0
- package/src/filter-bar/filter-bar.css +1306 -0
- package/src/filter-bar/filter-bar.tokens.json +78 -0
- package/src/form/form.css +218 -0
- package/src/form/form.tokens.json +32 -0
- package/src/fullscreen/fullscreen.css +376 -0
- package/src/fullscreen/fullscreen.tokens.json +50 -0
- package/src/grid/grid.css +173 -0
- package/src/grid/grid.tokens.json +20 -0
- package/src/highlight/highlight.css +135 -0
- package/src/highlight/highlight.tokens.json +16 -0
- package/src/hover-card/hover-card.css +93 -0
- package/src/hover-card/hover-card.tokens.json +17 -0
- package/src/icon/icon.css +136 -0
- package/src/icon/icon.tokens.json +14 -0
- package/src/image/image.css +449 -0
- package/src/image/image.tokens.json +27 -0
- package/src/import-export-center/import-export-center.css +1175 -0
- package/src/import-export-center/import-export-center.tokens.json +84 -0
- package/src/inline/inline.css +149 -0
- package/src/inline/inline.tokens.json +14 -0
- package/src/inline-message/inline-message.css +396 -0
- package/src/inline-message/inline-message.tokens.json +19 -0
- package/src/kbd/kbd.css +490 -0
- package/src/kbd/kbd.tokens.json +40 -0
- package/src/link/link.css +237 -0
- package/src/link/link.tokens.json +25 -0
- package/src/list/list.css +240 -0
- package/src/list/list.tokens.json +42 -0
- package/src/list-item/list-item.css +937 -0
- package/src/list-item/list-item.tokens.json +114 -0
- package/src/listbox/listbox.css +674 -0
- package/src/listbox/listbox.tokens.json +72 -0
- package/src/loading-overlay/loading-overlay.css +730 -0
- package/src/loading-overlay/loading-overlay.tokens.json +48 -0
- package/src/markdown/markdown.css +168 -0
- package/src/markdown/markdown.tokens.json +18 -0
- package/src/menu/menu.css +817 -0
- package/src/menu/menu.tokens.json +78 -0
- package/src/menubar/menubar.css +170 -0
- package/src/menubar/menubar.tokens.json +32 -0
- package/src/message/message.css +1453 -0
- package/src/message/message.tokens.json +85 -0
- package/src/message-scroller/message-scroller.css +371 -0
- package/src/message-scroller/message-scroller.tokens.json +47 -0
- package/src/multi-select/multi-select.css +1427 -0
- package/src/multi-select/multi-select.tokens.json +114 -0
- package/src/navigation-menu/navigation-menu.css +1029 -0
- package/src/navigation-menu/navigation-menu.tokens.json +70 -0
- package/src/notification-center/notification-center.css +856 -0
- package/src/notification-center/notification-center.tokens.json +84 -0
- package/src/number-field/number-field.css +794 -0
- package/src/number-field/number-field.tokens.json +80 -0
- package/src/otp-input/otp-input.css +525 -0
- package/src/otp-input/otp-input.tokens.json +69 -0
- package/src/page/page.css +179 -0
- package/src/page/page.tokens.json +20 -0
- package/src/page-header/page-header.css +1181 -0
- package/src/page-header/page-header.tokens.json +71 -0
- package/src/pagination/pagination.css +500 -0
- package/src/pagination/pagination.tokens.json +56 -0
- package/src/popover/popover.css +526 -0
- package/src/popover/popover.tokens.json +60 -0
- package/src/progress-indicator/progress-indicator.css +1584 -0
- package/src/progress-indicator/progress-indicator.tokens.json +50 -0
- package/src/prompt-composer/prompt-composer.css +680 -0
- package/src/prompt-composer/prompt-composer.tokens.json +99 -0
- package/src/prose/prose.css +733 -0
- package/src/prose/prose.tokens.json +79 -0
- package/src/radio-group/radio-group.css +778 -0
- package/src/radio-group/radio-group.tokens.json +103 -0
- package/src/rating/rating.css +1071 -0
- package/src/rating/rating.tokens.json +88 -0
- package/src/result-state/result-state.css +980 -0
- package/src/result-state/result-state.tokens.json +63 -0
- package/src/runtime-properties.mjs +321 -0
- package/src/saved-views/saved-views.css +394 -0
- package/src/saved-views/saved-views.tokens.json +41 -0
- package/src/scroll-area/scroll-area.css +481 -0
- package/src/scroll-area/scroll-area.tokens.json +15 -0
- package/src/section/section.css +177 -0
- package/src/section/section.tokens.json +39 -0
- package/src/segmented-control/segmented-control.css +564 -0
- package/src/segmented-control/segmented-control.tokens.json +67 -0
- package/src/select/select.css +1593 -0
- package/src/select/select.tokens.json +110 -0
- package/src/side-navigation/side-navigation.css +1096 -0
- package/src/side-navigation/side-navigation.tokens.json +87 -0
- package/src/skeleton/skeleton.css +431 -0
- package/src/skeleton/skeleton.tokens.json +29 -0
- package/src/slider/slider.css +792 -0
- package/src/slider/slider.tokens.json +75 -0
- package/src/sparkline/sparkline.css +282 -0
- package/src/sparkline/sparkline.tokens.json +45 -0
- package/src/spinner/spinner.css +224 -0
- package/src/spinner/spinner.tokens.json +8 -0
- package/src/split-button/split-button.css +253 -0
- package/src/split-button/split-button.tokens.json +12 -0
- package/src/splitter/splitter.css +336 -0
- package/src/splitter/splitter.tokens.json +24 -0
- package/src/stack/stack.css +128 -0
- package/src/stack/stack.tokens.json +14 -0
- package/src/stat-card/stat-card.css +641 -0
- package/src/stat-card/stat-card.tokens.json +95 -0
- package/src/status-indicator/status-indicator.css +481 -0
- package/src/status-indicator/status-indicator.tokens.json +38 -0
- package/src/stepper/stepper.css +629 -0
- package/src/stepper/stepper.tokens.json +72 -0
- package/src/switch/switch.css +703 -0
- package/src/switch/switch.tokens.json +75 -0
- package/src/table/table.css +1482 -0
- package/src/table/table.tokens.json +69 -0
- package/src/table-of-contents/table-of-contents.css +533 -0
- package/src/table-of-contents/table-of-contents.tokens.json +53 -0
- package/src/tabs/tabs.css +998 -0
- package/src/tabs/tabs.tokens.json +82 -0
- package/src/tag/tag.css +768 -0
- package/src/tag/tag.tokens.json +85 -0
- package/src/tags-input/tags-input.css +757 -0
- package/src/tags-input/tags-input.tokens.json +84 -0
- package/src/text-field/text-field.css +900 -0
- package/src/text-field/text-field.tokens.json +87 -0
- package/src/textarea/textarea.css +365 -0
- package/src/textarea/textarea.tokens.json +59 -0
- package/src/time-field/time-field.css +719 -0
- package/src/time-field/time-field.tokens.json +86 -0
- package/src/time-picker/time-picker.css +665 -0
- package/src/time-picker/time-picker.tokens.json +66 -0
- package/src/time-range-picker/time-range-picker.css +1287 -0
- package/src/time-range-picker/time-range-picker.tokens.json +134 -0
- package/src/timeline/timeline.css +1596 -0
- package/src/timeline/timeline.tokens.json +96 -0
- package/src/toast/toast.css +943 -0
- package/src/toast/toast.tokens.json +90 -0
- package/src/toggle/toggle.css +290 -0
- package/src/toggle/toggle.tokens.json +54 -0
- package/src/toggle-group/toggle-group.css +463 -0
- package/src/toggle-group/toggle-group.tokens.json +54 -0
- package/src/toolbar/toolbar.css +434 -0
- package/src/toolbar/toolbar.tokens.json +49 -0
- package/src/tooltip/tooltip.css +368 -0
- package/src/tooltip/tooltip.tokens.json +39 -0
- package/src/top-navigation/top-navigation.css +1287 -0
- package/src/top-navigation/top-navigation.tokens.json +91 -0
- package/src/tour/tour.css +680 -0
- package/src/tour/tour.tokens.json +67 -0
- package/src/transfer/transfer.css +571 -0
- package/src/transfer/transfer.tokens.json +49 -0
- package/src/tree/tree.css +1000 -0
- package/src/tree/tree.tokens.json +80 -0
- package/src/typography/typography.css +211 -0
- package/src/typography/typography.tokens.json +31 -0
- package/src/upload/upload.css +1706 -0
- package/src/upload/upload.tokens.json +123 -0
- package/src/visually-hidden/visually-hidden.css +52 -0
- package/src/visually-hidden/visually-hidden.tokens.json +1 -0
- package/src/wizard/wizard.css +740 -0
- package/src/wizard/wizard.tokens.json +63 -0
|
@@ -0,0 +1,1584 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The percentage every part of an indicator reads, registered so it can be
|
|
3
|
+
* transitioned at all: an unregistered custom property has no type and
|
|
4
|
+
* interpolates by discrete jumps.
|
|
5
|
+
*
|
|
6
|
+
* `inherits: true` is the whole mechanism. One transition on the root moves
|
|
7
|
+
* the number, and the four things derived from it — the indicator's length,
|
|
8
|
+
* the trailing track's start, the arc's dash and the buffer's edge — recompute
|
|
9
|
+
* together on every frame. Transitioning each of them separately is what makes
|
|
10
|
+
* a bar whose fill arrives before its gap does, which is the defect this
|
|
11
|
+
* costs one declaration to prevent.
|
|
12
|
+
*/
|
|
13
|
+
@property --slotted-progress-indicator-percent {
|
|
14
|
+
syntax: '<number>';
|
|
15
|
+
inherits: true;
|
|
16
|
+
initial-value: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@property --slotted-progress-indicator-buffer-percent {
|
|
20
|
+
syntax: '<number>';
|
|
21
|
+
inherits: true;
|
|
22
|
+
initial-value: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Where the travelling bar of an indeterminate indicator starts and how long
|
|
27
|
+
* it is, as percentages of the track.
|
|
28
|
+
*
|
|
29
|
+
* The keyframes move these two numbers rather than the bar's own box, because
|
|
30
|
+
* two things read them: the plain bar sets its inset and its length from them,
|
|
31
|
+
* and the wavy bar cuts a window out of its path at the same two numbers. One
|
|
32
|
+
* clock, read twice, is what keeps a wavy bar and a plain one travelling the
|
|
33
|
+
* same journey.
|
|
34
|
+
*/
|
|
35
|
+
@property --slotted-progress-indicator-travel-start {
|
|
36
|
+
syntax: '<number>';
|
|
37
|
+
inherits: true;
|
|
38
|
+
initial-value: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@property --slotted-progress-indicator-travel-size {
|
|
42
|
+
syntax: '<number>';
|
|
43
|
+
inherits: true;
|
|
44
|
+
initial-value: 100;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Where the wave is in its own cycle, from nought to one.
|
|
49
|
+
*
|
|
50
|
+
* A registered number rather than an animated dash offset, because a keyframe
|
|
51
|
+
* moving `stroke-dashoffset` between two `var()`-bearing values interpolated
|
|
52
|
+
* discretely: the arc held still for half a cycle and then jumped 45 degrees.
|
|
53
|
+
* A registered `<number>` interpolates by its declared syntax, and every
|
|
54
|
+
* angle, length and dash derived from it recomputes each frame.
|
|
55
|
+
*
|
|
56
|
+
* It inherits, because the paths read it from the root.
|
|
57
|
+
*/
|
|
58
|
+
@property --slotted-progress-indicator-wave-phase {
|
|
59
|
+
syntax: '<number>';
|
|
60
|
+
inherits: true;
|
|
61
|
+
initial-value: 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* How high the crests stand, from nought to one.
|
|
66
|
+
*
|
|
67
|
+
* `WavyProgressIndicatorDefaults.indicatorAmplitude` is M3's own API for this:
|
|
68
|
+
* a function of the progress, whose default is a switch — nought at or below
|
|
69
|
+
* a tenth and at or above ninety-five hundredths — that a 500-millisecond
|
|
70
|
+
* animator then chases. That switch is what made the wave die all at once at
|
|
71
|
+
* ninety-five per cent while the fill still had a visible remainder, and
|
|
72
|
+
* arrive all at once at ten. The function here is a ramp instead: nought to
|
|
73
|
+
* six per cent, rising to one at sixteen, one until eighty-four, falling to
|
|
74
|
+
* nought at ninety-six. The fill's own spring is what moves it, so the crests
|
|
75
|
+
* settle as the bar arrives rather than on a timer of their own.
|
|
76
|
+
*
|
|
77
|
+
* It is registered so the paths read an interpolated number each frame, and so
|
|
78
|
+
* the ramp follows the transitioning percentage rather than the stated value.
|
|
79
|
+
*/
|
|
80
|
+
@property --slotted-progress-indicator-wave-amplitude {
|
|
81
|
+
syntax: '<number>';
|
|
82
|
+
inherits: true;
|
|
83
|
+
initial-value: 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@layer slotted.components {
|
|
87
|
+
/* ── The box ────────────────────────────────────────────────────────────
|
|
88
|
+
*
|
|
89
|
+
* A quantity a consumer states and this family draws. It is never a
|
|
90
|
+
* command: it answers no hover, gives no press feedback, takes no focus and
|
|
91
|
+
* has nothing to disable — a component that moved its own value would be
|
|
92
|
+
* reporting a task it cannot see.
|
|
93
|
+
*
|
|
94
|
+
* Three geometries share this box, and `data-shape` is what tells them
|
|
95
|
+
* apart. It is written by the component rather than chosen by a consumer,
|
|
96
|
+
* for the reason `button` writes `data-shape` for its icon member: one
|
|
97
|
+
* authored stylesheet has to know which of three things it is painting, and
|
|
98
|
+
* a prop would be a fourth way to pick a component already picked.
|
|
99
|
+
*/
|
|
100
|
+
[data-ui='progress-indicator'][data-part='root'] {
|
|
101
|
+
/**
|
|
102
|
+
* The ink, and it is the tone's `text` role rather than its `solid` one.
|
|
103
|
+
* Two reasons, and the second is the one that decides it. The indicator is
|
|
104
|
+
* a graphic bearing meaning, so WCAG 2.2 1.4.11 binds it at 3:1; the tone
|
|
105
|
+
* `text` roles are the steps the theme's contrast test holds to the 4.5:1
|
|
106
|
+
* reading ratio against every surface, which clears it with room over.
|
|
107
|
+
* And `--slotted-tone-secondary-solid` is the surface's own colour in
|
|
108
|
+
* `light` and the page's own white in `high-contrast` — a secondary bar
|
|
109
|
+
* painted from it would be an invisible bar in two schemes out of three,
|
|
110
|
+
* which is the deviation `button` recorded and could not fix inside its
|
|
111
|
+
* own family. `status-indicator` reached the same role for the same
|
|
112
|
+
* measurement.
|
|
113
|
+
*/
|
|
114
|
+
--_ink: var(--slotted-progress-indicator-indicator-color, var(--slotted-tone-accent-text));
|
|
115
|
+
/**
|
|
116
|
+
* The ground, computed rather than taken from the tone's `surface` role,
|
|
117
|
+
* and the three schemes are why. That role is `#dbeafe` in `light` — a
|
|
118
|
+
* pale blue, exactly right — and then `#181b22` in `dark`, one step off a
|
|
119
|
+
* `#131316` page, and `#ffffff` in `high-contrast`, which *is* the page.
|
|
120
|
+
* A track painted from it disappears in two schemes.
|
|
121
|
+
*
|
|
122
|
+
* Mixing the ink toward the surface moves away from the ground in every
|
|
123
|
+
* scheme instead, because the ink is the far end of each scheme's own
|
|
124
|
+
* range. Twenty-four per cent is measured rather than chosen: it is the
|
|
125
|
+
* lowest ratio at which the track separates from the page in all three
|
|
126
|
+
* schemes at the 2-pixel `sm` thickness, and low enough that a column of
|
|
127
|
+
* bars does not read as a column of filled bars.
|
|
128
|
+
*/
|
|
129
|
+
--_track-color: var(
|
|
130
|
+
--slotted-progress-indicator-track-color,
|
|
131
|
+
color-mix(in oklab, var(--_ink) 24%, var(--slotted-surface))
|
|
132
|
+
);
|
|
133
|
+
/**
|
|
134
|
+
* The second quantity, halfway between the two: received but not yet
|
|
135
|
+
* processed. It has to be legible as *neither* — a buffer the colour of
|
|
136
|
+
* the track says nothing has arrived, and a buffer the colour of the
|
|
137
|
+
* indicator says the work is done.
|
|
138
|
+
*/
|
|
139
|
+
--_buffer-color: var(--slotted-progress-indicator-buffer-color, transparent);
|
|
140
|
+
--_percent: var(--slotted-progress-indicator-percent, 0);
|
|
141
|
+
--_buffer-percent: var(--slotted-progress-indicator-buffer-percent, 0);
|
|
142
|
+
/** The further of the two edges, which is where the remaining track starts. */
|
|
143
|
+
--_lead: max(var(--_percent), var(--_buffer-percent));
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Type from the control scale, the only one the theme restates per
|
|
147
|
+
* density, so a bar in a dense table shrinks its words and keeps its bar.
|
|
148
|
+
* The gap between the words comes from the space scale: a density step
|
|
149
|
+
* inside a distance this small would be sub-pixel, and density already
|
|
150
|
+
* moves the type.
|
|
151
|
+
*/
|
|
152
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
153
|
+
--_text-gap: var(--slotted-space-4, 0.5rem);
|
|
154
|
+
--_row-gap: var(--slotted-space-3, 0.375rem);
|
|
155
|
+
--_thickness: var(--slotted-progress-indicator-thickness, var(--slotted-space-2, 0.25rem));
|
|
156
|
+
--_size: var(--slotted-progress-indicator-size, var(--slotted-control-height-md, 34px));
|
|
157
|
+
--_radius: var(--slotted-progress-indicator-radius, var(--slotted-radius-full, 9999px));
|
|
158
|
+
/**
|
|
159
|
+
* M3's indicator–track gap, and the stop indicator's diameter, are both
|
|
160
|
+
* 4dp at the 4dp track. Making them one thickness is the proportional form
|
|
161
|
+
* of that decision rather than a copy of the number: a 4-pixel gap in a
|
|
162
|
+
* 2-pixel bar would be wider than the bar is tall.
|
|
163
|
+
*/
|
|
164
|
+
--_gap: var(--slotted-progress-indicator-gap, var(--_thickness));
|
|
165
|
+
|
|
166
|
+
font-family: var(--slotted-control-font-family, sans-serif);
|
|
167
|
+
font-size: var(--_font-size);
|
|
168
|
+
line-height: var(--slotted-line-height-md, 1.5);
|
|
169
|
+
/**
|
|
170
|
+
* The indicator never widens the box that holds it: its own minimum is
|
|
171
|
+
* the longest word of a label it did not choose, and a grid or flex parent
|
|
172
|
+
* sizes its track from that minimum. Zero hands the decision back to the
|
|
173
|
+
* container, and the label breaks instead — the correction
|
|
174
|
+
* `status-indicator` recorded after a container digest pushed a 220-pixel
|
|
175
|
+
* column out to 420.
|
|
176
|
+
*/
|
|
177
|
+
min-inline-size: 0;
|
|
178
|
+
/**
|
|
179
|
+
* The one transition, and everything derived from the number moves with
|
|
180
|
+
* it: the fill, the gap, the arc, the buffer's edge and the wave's window.
|
|
181
|
+
*
|
|
182
|
+
* The curve is M3's own. `ProgressIndicatorDefaults.ProgressAnimationSpec`
|
|
183
|
+
* is a critically damped spring at `StiffnessVeryLow` — stiffness 50, no
|
|
184
|
+
* bounce — which settles to a thousandth in 1.3 seconds and has covered
|
|
185
|
+
* nine tenths of the distance after half of one. `linear()` writes that
|
|
186
|
+
* spring out: `1 - (1 + ωt)·e^(-ωt)` sampled at twenty steps, with `ωT`
|
|
187
|
+
* at 9.2. A bar that arrives fast and eases into place over the last
|
|
188
|
+
* second is what makes the wave's flatten, which starts at ninety-five per
|
|
189
|
+
* cent, land while the fill is still settling rather than after it has
|
|
190
|
+
* stopped.
|
|
191
|
+
*
|
|
192
|
+
* Four times `--slotted-duration-long` is the 1.3 seconds of that spring,
|
|
193
|
+
* from the scale rather than a literal, and the theme collapses the scale
|
|
194
|
+
* under `prefers-reduced-motion`, so a reader who asked for stillness gets
|
|
195
|
+
* the number without the travel.
|
|
196
|
+
*/
|
|
197
|
+
--_settle: calc(4 * var(--slotted-duration-long));
|
|
198
|
+
--_spring: linear(
|
|
199
|
+
0,
|
|
200
|
+
0.078,
|
|
201
|
+
0.235,
|
|
202
|
+
0.401,
|
|
203
|
+
0.549,
|
|
204
|
+
0.669,
|
|
205
|
+
0.762,
|
|
206
|
+
0.831,
|
|
207
|
+
0.882,
|
|
208
|
+
0.918,
|
|
209
|
+
0.944,
|
|
210
|
+
0.962,
|
|
211
|
+
0.974,
|
|
212
|
+
0.982,
|
|
213
|
+
0.988,
|
|
214
|
+
0.992,
|
|
215
|
+
0.995,
|
|
216
|
+
0.996,
|
|
217
|
+
0.998,
|
|
218
|
+
0.998,
|
|
219
|
+
1
|
|
220
|
+
);
|
|
221
|
+
transition:
|
|
222
|
+
--slotted-progress-indicator-percent var(--_settle) var(--_spring),
|
|
223
|
+
--slotted-progress-indicator-buffer-percent var(--_settle) var(--_spring);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The withheld indicator. `delay` has not elapsed, so there is nothing to
|
|
228
|
+
* report yet and nothing is drawn — no box, no role, no reserved band. The
|
|
229
|
+
* rule exists because the root's own `display` would otherwise win over the
|
|
230
|
+
* user agent's `[hidden]`, and a family that painted through its own
|
|
231
|
+
* withdrawal would flash exactly what the delay exists to prevent.
|
|
232
|
+
*/
|
|
233
|
+
[data-ui='progress-indicator'][hidden] {
|
|
234
|
+
display: none;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* ── Tone ─────────────────────────────────────────────────────────────
|
|
238
|
+
*
|
|
239
|
+
* Five colours the theme owns, and the family adds none. Only the ink is
|
|
240
|
+
* stated: the track and the buffer are derived from it, so a sixth tone
|
|
241
|
+
* added by an application is one declaration rather than three.
|
|
242
|
+
*/
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* The one tone whose ink is not its own `text` role, and the capture is what
|
|
246
|
+
* decided it. `--slotted-tone-secondary-text` is `#172033` in `light` and
|
|
247
|
+
* `#000000` in `high-contrast`: a background job drawn from it was the
|
|
248
|
+
* darkest thing on the page, which is the opposite of what `secondary`
|
|
249
|
+
* means. `--slotted-border-strong` is the neutral the theme holds to 3:1
|
|
250
|
+
* against every surface it separates — the ratio a meaningful graphic needs
|
|
251
|
+
* and no more — so a secondary indicator reads as grey rather than as ink.
|
|
252
|
+
* It is the same substitution `badge` and `status-indicator` make for their
|
|
253
|
+
* own neutral marks, for the same reason.
|
|
254
|
+
*/
|
|
255
|
+
[data-ui='progress-indicator'][data-part='root'][data-tone='secondary'] {
|
|
256
|
+
--_ink: var(--slotted-progress-indicator-indicator-color, var(--slotted-border-strong));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
[data-ui='progress-indicator'][data-part='root'][data-tone='success'] {
|
|
260
|
+
--_ink: var(--slotted-progress-indicator-indicator-color, var(--slotted-tone-success-text));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
[data-ui='progress-indicator'][data-part='root'][data-tone='warning'] {
|
|
264
|
+
--_ink: var(--slotted-progress-indicator-indicator-color, var(--slotted-tone-warning-text));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
[data-ui='progress-indicator'][data-part='root'][data-tone='danger'] {
|
|
268
|
+
--_ink: var(--slotted-progress-indicator-indicator-color, var(--slotted-tone-danger-text));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
[data-ui='progress-indicator'][data-part='root'][data-buffered] {
|
|
272
|
+
--_buffer-color: var(
|
|
273
|
+
--slotted-progress-indicator-buffer-color,
|
|
274
|
+
color-mix(in oklab, var(--_ink) 52%, var(--slotted-surface))
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* ── Size ─────────────────────────────────────────────────────────────
|
|
279
|
+
*
|
|
280
|
+
* One axis, three geometries. The bar reads a thickness from the space
|
|
281
|
+
* scale — 2, 4 and 8 pixels, and M3's own default track is the middle one —
|
|
282
|
+
* while the circle and the loader read the control height scale, so a
|
|
283
|
+
* spinner standing beside a button is the same height as the button at
|
|
284
|
+
* every density. Neither needs a scale of this family's own, and the
|
|
285
|
+
* component layer of the token contract stays as `avatar` left it.
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
[data-ui='progress-indicator'][data-part='root'][data-size='sm'] {
|
|
289
|
+
--_font-size: var(--slotted-control-font-size-sm, 12px);
|
|
290
|
+
--_text-gap: var(--slotted-space-3, 0.375rem);
|
|
291
|
+
--_thickness: var(--slotted-progress-indicator-thickness, var(--slotted-space-1, 0.125rem));
|
|
292
|
+
--_size: var(--slotted-progress-indicator-size, var(--slotted-control-height-sm, 30px));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
[data-ui='progress-indicator'][data-part='root'][data-size='lg'] {
|
|
296
|
+
--_font-size: var(--slotted-control-font-size-lg, 14px);
|
|
297
|
+
--_row-gap: var(--slotted-space-4, 0.5rem);
|
|
298
|
+
--_thickness: var(--slotted-progress-indicator-thickness, var(--slotted-space-4, 0.5rem));
|
|
299
|
+
--_size: var(--slotted-progress-indicator-size, var(--slotted-control-height-lg, 38px));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* ── The words ────────────────────────────────────────────────────────
|
|
303
|
+
*
|
|
304
|
+
* The label wraps and the value does not. A label is a sentence a consumer
|
|
305
|
+
* wrote in a language this family does not know — “Verificando assinaturas
|
|
306
|
+
* do pacote” is four words that have to break somewhere — and a number is
|
|
307
|
+
* never improved by being broken in half.
|
|
308
|
+
*
|
|
309
|
+
* `overflow-wrap: break-word` rather than `anywhere`, which is the
|
|
310
|
+
* distinction `status-indicator` was caught by: both break the unbreakable
|
|
311
|
+
* token, and only `anywhere` also reports a min-content size of one
|
|
312
|
+
* character, so a grid column sized to its content collapses to that
|
|
313
|
+
* character.
|
|
314
|
+
*/
|
|
315
|
+
[data-ui='progress-indicator'] [data-part='label'] {
|
|
316
|
+
color: var(--slotted-text, CanvasText);
|
|
317
|
+
min-inline-size: 0;
|
|
318
|
+
overflow-wrap: break-word;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Tabular figures, and the reason is the whole point of the part: the value
|
|
323
|
+
* changes while the reader is looking at it, and a proportional `1` is
|
|
324
|
+
* narrower than a `7`, so a counting bar jitters its own label. The colour
|
|
325
|
+
* is the muted step, because the number annotates the bar rather than
|
|
326
|
+
* naming it.
|
|
327
|
+
*/
|
|
328
|
+
[data-ui='progress-indicator'] [data-part='value'] {
|
|
329
|
+
color: var(--slotted-text-muted, GrayText);
|
|
330
|
+
font-variant-numeric: tabular-nums;
|
|
331
|
+
white-space: nowrap;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* ── Linear ───────────────────────────────────────────────────────────
|
|
335
|
+
*
|
|
336
|
+
* Two rows of a grid: the label and the value share the first, and the
|
|
337
|
+
* track spans both columns of the second. The empty row costs nothing when
|
|
338
|
+
* neither word is rendered, because a part a consumer did not ask for is
|
|
339
|
+
* absent from the DOM rather than present and empty — so auto-placement
|
|
340
|
+
* puts the track in the first row and the row gap never applies.
|
|
341
|
+
*
|
|
342
|
+
* `justify-self: end` and `grid-column` are logical: the value sits at the
|
|
343
|
+
* inline end, which is the right edge of an English page and the left edge
|
|
344
|
+
* of an Arabic one, with no mirrored rule to write.
|
|
345
|
+
*/
|
|
346
|
+
[data-ui='progress-indicator'][data-part='root'][data-shape='linear'] {
|
|
347
|
+
align-items: baseline;
|
|
348
|
+
column-gap: var(--_text-gap);
|
|
349
|
+
display: grid;
|
|
350
|
+
grid-template-columns: 1fr auto;
|
|
351
|
+
row-gap: var(--_row-gap);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
[data-ui='progress-indicator'][data-shape='linear'] > [data-part='label'] {
|
|
355
|
+
grid-column: 1;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
[data-ui='progress-indicator'][data-shape='linear'] > [data-part='value'] {
|
|
359
|
+
grid-column: 2;
|
|
360
|
+
justify-self: end;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
[data-ui='progress-indicator'][data-shape='linear'] > [data-part='track'] {
|
|
364
|
+
grid-column: 1 / -1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* The track, which paints the buffer and nothing else. The remaining track
|
|
369
|
+
* is a pseudo-element rather than this element's own background, because
|
|
370
|
+
* M3's gap is air between two rounded bars: a background that ran the whole
|
|
371
|
+
* length would fill it, and a gradient stopped at a percentage would need a
|
|
372
|
+
* mirrored copy for every right-to-left document.
|
|
373
|
+
*
|
|
374
|
+
* `overflow: clip` is what the indeterminate indicator travels inside, and
|
|
375
|
+
* it is what rounds the travelling bar's ends against the track's own. It is
|
|
376
|
+
* stated per axis rather than once, because a wave is taller than the band
|
|
377
|
+
* it belongs to: the inline axis still holds the travelling bar, and the
|
|
378
|
+
* block axis has to let a crest out. A single `clip` is what sliced the
|
|
379
|
+
* crests flat in the first capture of this family.
|
|
380
|
+
*/
|
|
381
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track'] {
|
|
382
|
+
background-color: var(--_buffer-color);
|
|
383
|
+
block-size: var(--_thickness);
|
|
384
|
+
border-radius: var(--_radius);
|
|
385
|
+
inline-size: 100%;
|
|
386
|
+
isolation: isolate;
|
|
387
|
+
overflow-x: clip;
|
|
388
|
+
overflow-y: visible;
|
|
389
|
+
position: relative;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* The track that is left, from one gap past the further of the two edges to
|
|
394
|
+
* the end. It carries the same radius, so the indicator and the remainder
|
|
395
|
+
* read as two bars with air between them rather than as one bar with a
|
|
396
|
+
* notch — the shape M3 took in 2024 and the one no other surveyed
|
|
397
|
+
* implementation draws.
|
|
398
|
+
*/
|
|
399
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::before {
|
|
400
|
+
background-color: var(--_track-color);
|
|
401
|
+
border-radius: inherit;
|
|
402
|
+
content: '';
|
|
403
|
+
inset-block: 0;
|
|
404
|
+
inset-inline-end: 0;
|
|
405
|
+
inset-inline-start: calc(1% * var(--_lead) + var(--_gap));
|
|
406
|
+
position: absolute;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* The stop indicator: a dot of one thickness at the end of the track, in the
|
|
411
|
+
* indicator's own ink. It is what tells a reader where the bar is going,
|
|
412
|
+
* and it is the detail that makes a bar at four per cent read as four per
|
|
413
|
+
* cent of something rather than as a stray mark.
|
|
414
|
+
*/
|
|
415
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::after {
|
|
416
|
+
background-color: var(--_ink);
|
|
417
|
+
border-radius: var(--slotted-radius-full, 9999px);
|
|
418
|
+
content: '';
|
|
419
|
+
inline-size: var(--_thickness);
|
|
420
|
+
inset-block: 0;
|
|
421
|
+
inset-inline-end: 0;
|
|
422
|
+
position: absolute;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='indicator'] {
|
|
426
|
+
background-color: var(--_ink);
|
|
427
|
+
block-size: 100%;
|
|
428
|
+
border-radius: inherit;
|
|
429
|
+
inline-size: calc(1% * var(--_percent));
|
|
430
|
+
/* Above the remaining track, which is painted by the pseudo-element the
|
|
431
|
+
browser draws before this element's own box. */
|
|
432
|
+
position: relative;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Complete, and there is nothing left to separate. The remaining track goes
|
|
437
|
+
* and the stop indicator goes with it: a dot in the indicator's colour on
|
|
438
|
+
* top of a full indicator is a dot nobody can see, and leaving the gap
|
|
439
|
+
* would put a notch a whole thickness wide at the end of a finished bar.
|
|
440
|
+
*
|
|
441
|
+
* The switch reads the transitioning percentage rather than `data-complete`.
|
|
442
|
+
* The attribute is written from the stated value the moment it reaches the
|
|
443
|
+
* top of the range, and the fill takes 1.3 seconds to get there: keyed on
|
|
444
|
+
* the attribute, the remaining track vanished while the fill was still half
|
|
445
|
+
* way along it. Keyed on the number, it goes when the fill arrives.
|
|
446
|
+
*/
|
|
447
|
+
@container style(--slotted-progress-indicator-percent: 100) {
|
|
448
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::before,
|
|
449
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::after {
|
|
450
|
+
content: none;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Indeterminate: the whole track shows, there is no end to mark, and the
|
|
456
|
+
* indicator becomes a short bar travelling the length of it. It is absolutely
|
|
457
|
+
* positioned so the travel is one property — the decision the family this
|
|
458
|
+
* one replaces recorded, and `inset-inline-start` is why a translation runs
|
|
459
|
+
* the way the document reads instead of the way the screen does.
|
|
460
|
+
*/
|
|
461
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-indeterminate]
|
|
462
|
+
[data-part='track']::before {
|
|
463
|
+
inset-inline-start: 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-indeterminate]
|
|
467
|
+
[data-part='track']::after {
|
|
468
|
+
content: none;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-indeterminate] [data-part='indicator'] {
|
|
472
|
+
animation: slotted-progress-indicator-travel var(--slotted-duration-loop-slow)
|
|
473
|
+
var(--slotted-easing-standard) infinite;
|
|
474
|
+
inline-size: calc(1% * var(--slotted-progress-indicator-travel-size));
|
|
475
|
+
inset-block: 0;
|
|
476
|
+
inset-inline-start: calc(1% * var(--slotted-progress-indicator-travel-start));
|
|
477
|
+
position: absolute;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* A short bar that grows as it crosses and shrinks as it leaves, which is
|
|
482
|
+
* M3's disjoint indicator drawn with one bar rather than two. The width
|
|
483
|
+
* changes because a bar of constant length reads as a scrollbar being
|
|
484
|
+
* dragged; a bar that swells in the middle of its journey reads as
|
|
485
|
+
* something in progress.
|
|
486
|
+
*
|
|
487
|
+
* The keyframes move the two registered numbers rather than the box, so the
|
|
488
|
+
* wavy bar can cut its window at the same two numbers.
|
|
489
|
+
*/
|
|
490
|
+
@keyframes slotted-progress-indicator-travel {
|
|
491
|
+
0% {
|
|
492
|
+
--slotted-progress-indicator-travel-size: 14;
|
|
493
|
+
--slotted-progress-indicator-travel-start: -14;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
45% {
|
|
497
|
+
--slotted-progress-indicator-travel-size: 46;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
100% {
|
|
501
|
+
--slotted-progress-indicator-travel-size: 14;
|
|
502
|
+
--slotted-progress-indicator-travel-start: 100;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/* ── The page-level bar ───────────────────────────────────────────────
|
|
507
|
+
*
|
|
508
|
+
* The whole of what `loading-bar` was. It is pinned to the top edge of the
|
|
509
|
+
* viewport, it has no corner to round because it has no corner, and its
|
|
510
|
+
* track is transparent: a permanent grey band across the top of a page
|
|
511
|
+
* reads as a rule under the header rather than as a wait — the decision
|
|
512
|
+
* that family recorded.
|
|
513
|
+
*
|
|
514
|
+
* The stacking layer is a token, so an application's own stacking contract
|
|
515
|
+
* still decides. Every router progress bar in the field types a number here.
|
|
516
|
+
*/
|
|
517
|
+
[data-ui='progress-indicator'][data-part='root'][data-placement='page'] {
|
|
518
|
+
--_radius: var(--slotted-progress-indicator-radius, var(--slotted-radius-none, 0px));
|
|
519
|
+
--_track-color: var(--slotted-progress-indicator-track-color, transparent);
|
|
520
|
+
--_gap: var(--slotted-progress-indicator-gap, 0);
|
|
521
|
+
|
|
522
|
+
inset-block-start: 0;
|
|
523
|
+
inset-inline: 0;
|
|
524
|
+
position: fixed;
|
|
525
|
+
z-index: var(--slotted-z-index-sticky, 100);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
[data-ui='progress-indicator'][data-placement='page'] [data-part='track']::after {
|
|
529
|
+
content: none;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* ── The edge bar ─────────────────────────────────────────────────────
|
|
533
|
+
*
|
|
534
|
+
* The page-level bar on the edge of any box instead of the viewport's: the
|
|
535
|
+
* block-start edge under `edge-start`, the block-end edge under `edge-end`,
|
|
536
|
+
* the whole inline size of the nearest positioned box. It is drawn over the
|
|
537
|
+
* line that edge already draws — a seam, a card's border, a header's
|
|
538
|
+
* hairline — so it reserves nothing and nothing moves when it comes or
|
|
539
|
+
* goes. The box is the placer's, and its corners clip the bar: `app-shell`
|
|
540
|
+
* and `page-header` each render one as their `progress` part.
|
|
541
|
+
*
|
|
542
|
+
* No stacking layer of its own. The bar is the last thing its box paints,
|
|
543
|
+
* and the box decides where it stands among its neighbours.
|
|
544
|
+
*
|
|
545
|
+
* `--slotted-progress-indicator-position` is the box's answer when the box
|
|
546
|
+
* is taller than the screen: `sticky` keeps the bar on the visible part of
|
|
547
|
+
* the edge. `app-shell` writes it for a content region that scrolls with
|
|
548
|
+
* the document. It is a composition value, not a design token.
|
|
549
|
+
*/
|
|
550
|
+
[data-ui='progress-indicator'][data-part='root']:is(
|
|
551
|
+
[data-placement='edge-start'],
|
|
552
|
+
[data-placement='edge-end']
|
|
553
|
+
) {
|
|
554
|
+
--_radius: var(--slotted-progress-indicator-radius, var(--slotted-radius-none, 0px));
|
|
555
|
+
--_track-color: var(--slotted-progress-indicator-track-color, transparent);
|
|
556
|
+
--_gap: var(--slotted-progress-indicator-gap, 0);
|
|
557
|
+
|
|
558
|
+
inset-inline: 0;
|
|
559
|
+
position: var(--slotted-progress-indicator-position, absolute);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
[data-ui='progress-indicator'][data-part='root'][data-placement='edge-start'] {
|
|
563
|
+
inset-block-start: 0;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
[data-ui='progress-indicator'][data-part='root'][data-placement='edge-end'] {
|
|
567
|
+
inset-block-end: 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
[data-ui='progress-indicator']:is([data-placement='edge-start'], [data-placement='edge-end'])
|
|
571
|
+
[data-part='track']::after {
|
|
572
|
+
content: none;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* A bar standing on an edge grows out of the line it stands on and goes
|
|
577
|
+
* back into it, which is M3's `outward` show and `inward` hide for a linear
|
|
578
|
+
* indicator. It is a clip rather than a scale: the root holds the label,
|
|
579
|
+
* clipped but read, and a box that holds text is never scaled. The clip
|
|
580
|
+
* starts from no thickness rather than from most of one, because the line
|
|
581
|
+
* it grows out of is already drawn, so the bar never comes from nowhere,
|
|
582
|
+
* and a bar that began at nine tenths of two pixels would be a bar that
|
|
583
|
+
* blinked on. The opacity travels with it so the first frames are not a
|
|
584
|
+
* hard sliver of ink.
|
|
585
|
+
*
|
|
586
|
+
* `inset()` takes physical sides and has no logical form; the top and the
|
|
587
|
+
* bottom are the block-start and block-end edges in every horizontal
|
|
588
|
+
* writing mode, which is every mode the library lays out. The page-level
|
|
589
|
+
* bar shares the motion, as the edge bar of the viewport.
|
|
590
|
+
*
|
|
591
|
+
* Enter is the medium step on the entering curve; exit is the short step on
|
|
592
|
+
* the leaving one, so a wait that has ended is gone before the eye returns
|
|
593
|
+
* to it. `display` is transitioned as a discrete property, so `hidden` —
|
|
594
|
+
* the withheld and withdrawn state — takes effect once the bar has gone
|
|
595
|
+
* back into its edge rather than on the frame it is asked to. The theme
|
|
596
|
+
* collapses both steps under `prefers-reduced-motion`.
|
|
597
|
+
*/
|
|
598
|
+
[data-ui='progress-indicator'][data-part='root']:is(
|
|
599
|
+
[data-placement='page'],
|
|
600
|
+
[data-placement='edge-start'],
|
|
601
|
+
[data-placement='edge-end']
|
|
602
|
+
) {
|
|
603
|
+
--_withdrawn: inset(0 0 100% 0);
|
|
604
|
+
|
|
605
|
+
clip-path: inset(0);
|
|
606
|
+
transition:
|
|
607
|
+
--slotted-progress-indicator-percent var(--_settle) var(--_spring),
|
|
608
|
+
--slotted-progress-indicator-buffer-percent var(--_settle) var(--_spring),
|
|
609
|
+
clip-path var(--slotted-duration-medium) var(--slotted-easing-enter),
|
|
610
|
+
opacity var(--slotted-duration-medium) var(--slotted-easing-enter);
|
|
611
|
+
|
|
612
|
+
@starting-style {
|
|
613
|
+
clip-path: var(--_withdrawn);
|
|
614
|
+
opacity: 0;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
[data-ui='progress-indicator'][data-part='root'][data-placement='edge-end'] {
|
|
619
|
+
--_withdrawn: inset(100% 0 0 0);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
[data-ui='progress-indicator'][data-part='root']:is(
|
|
623
|
+
[data-placement='page'],
|
|
624
|
+
[data-placement='edge-start'],
|
|
625
|
+
[data-placement='edge-end']
|
|
626
|
+
)[hidden] {
|
|
627
|
+
clip-path: var(--_withdrawn);
|
|
628
|
+
opacity: 0;
|
|
629
|
+
transition:
|
|
630
|
+
clip-path var(--slotted-duration-short) var(--slotted-easing-exit),
|
|
631
|
+
opacity var(--slotted-duration-short) var(--slotted-easing-exit),
|
|
632
|
+
display var(--slotted-duration-short) allow-discrete;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/* ── Circular ─────────────────────────────────────────────────────────
|
|
636
|
+
*
|
|
637
|
+
* The ring, the name and the number on one line. The number sits beside the
|
|
638
|
+
* ring rather than inside it, and that is a measurement rather than a
|
|
639
|
+
* preference: the largest ring this family draws is 38 pixels across with a
|
|
640
|
+
* 4.75-pixel stroke, which leaves 28 pixels of hole, and a percentage
|
|
641
|
+
* centred in it would be four-pixel type. Ant Design and MUI both put it
|
|
642
|
+
* inside because both draw rings twice this size.
|
|
643
|
+
*/
|
|
644
|
+
[data-ui='progress-indicator'][data-part='root'][data-shape='circular'],
|
|
645
|
+
[data-ui='progress-indicator'][data-part='root'][data-shape='morph'] {
|
|
646
|
+
align-items: center;
|
|
647
|
+
column-gap: var(--_text-gap);
|
|
648
|
+
display: inline-flex;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* The stroke is stated in the viewBox's own units, and six of forty-eight is
|
|
653
|
+
* one eighth of the diameter at every size. It is the ratio `button` derived
|
|
654
|
+
* for its own loading ring — “two pixels is a sixth of the ring at the dense
|
|
655
|
+
* small step and a ninth of it at the large one” — so the ring in a button
|
|
656
|
+
* and this family's circle are the same object, and Button can stop drawing
|
|
657
|
+
* its own.
|
|
658
|
+
*/
|
|
659
|
+
[data-ui='progress-indicator'][data-shape='circular'] svg {
|
|
660
|
+
--_stroke: var(--slotted-progress-indicator-stroke, 6);
|
|
661
|
+
|
|
662
|
+
block-size: var(--_size);
|
|
663
|
+
flex: none;
|
|
664
|
+
inline-size: var(--_size);
|
|
665
|
+
/* The arc starts at twelve o'clock. An SVG angle is measured from three,
|
|
666
|
+
and rotating the whole box is what keeps one dash arithmetic for the
|
|
667
|
+
plain ring and the wavy one. */
|
|
668
|
+
rotate: -90deg;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='track'],
|
|
672
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='indicator'] {
|
|
673
|
+
fill: none;
|
|
674
|
+
stroke-linecap: round;
|
|
675
|
+
stroke-width: var(--_stroke);
|
|
676
|
+
/* `pathLength="100"` is on the element, so a dash is a percentage and the
|
|
677
|
+
transition on the number moves the arc. The dash itself is not
|
|
678
|
+
transitioned: smoothing a value that is already on the spring would lag
|
|
679
|
+
it by a second smoothing. */
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='indicator'] {
|
|
683
|
+
stroke: var(--_ink);
|
|
684
|
+
stroke-dasharray: var(--_percent) 100;
|
|
685
|
+
/**
|
|
686
|
+
* A round cap on a dash of zero length is a dot, and a dot at twelve
|
|
687
|
+
* o'clock on an empty ring reads as a rendering fault. There is no `if` in
|
|
688
|
+
* CSS and nothing to compare against, so the opacity is a clamp: nought at
|
|
689
|
+
* nought per cent, one at anything above a thousandth of a per cent.
|
|
690
|
+
*/
|
|
691
|
+
stroke-opacity: clamp(0, calc(var(--_percent) * 1000), 1);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* The track is drawn only where the indicator is not, one gap short at each
|
|
696
|
+
* end — M3's indicator–track gap, in a circle. Three and two tenths of the
|
|
697
|
+
* path is four device pixels of a 44-pixel ring, which is the gap M3
|
|
698
|
+
* specifies for the bar.
|
|
699
|
+
*/
|
|
700
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='track'] {
|
|
701
|
+
/**
|
|
702
|
+
* Three and two tenths of the path is four device pixels of a 44-pixel
|
|
703
|
+
* ring, and it collapses to nothing at nought per cent by the same clamp
|
|
704
|
+
* the indicator's opacity uses. The first capture is why: an empty ring
|
|
705
|
+
* carried a gap at twelve o'clock, which is a bite out of a circle for an
|
|
706
|
+
* indicator that is not there.
|
|
707
|
+
*/
|
|
708
|
+
--_arc-gap: calc(3.2 * clamp(0, calc(var(--_percent) * 1000), 1));
|
|
709
|
+
|
|
710
|
+
stroke: var(--_track-color);
|
|
711
|
+
stroke-dasharray: calc(100 - var(--_percent) - 2 * var(--_arc-gap)) 100;
|
|
712
|
+
stroke-dashoffset: calc(-1 * (var(--_percent) + var(--_arc-gap)));
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Complete, and the ring closes: the gap goes, so a finished circle is a
|
|
717
|
+
* ring rather than a ring with a bite out of it. It reads the transitioning
|
|
718
|
+
* percentage for the reason the bar does: the track has to outlast the arc's
|
|
719
|
+
* travel, not the stated value.
|
|
720
|
+
*/
|
|
721
|
+
@container style(--slotted-progress-indicator-percent: 100) {
|
|
722
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='track'] {
|
|
723
|
+
stroke: transparent;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Indeterminate: no track at all, which is M3's own answer — its circular
|
|
729
|
+
* track colour is transparent — and the reason is sound. An arc with no
|
|
730
|
+
* value has no remainder to show, and a ring behind it would claim there is
|
|
731
|
+
* one.
|
|
732
|
+
*
|
|
733
|
+
* The arc grows and shrinks while the whole ring turns, at two periods that
|
|
734
|
+
* do not divide into each other, so the sweep never repeats the same shape
|
|
735
|
+
* in the same orientation.
|
|
736
|
+
*/
|
|
737
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-indeterminate] [data-part='track'] {
|
|
738
|
+
stroke: transparent;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-indeterminate] svg {
|
|
742
|
+
animation: slotted-progress-indicator-turn var(--slotted-duration-loop) linear infinite;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-indeterminate]
|
|
746
|
+
[data-part='indicator'] {
|
|
747
|
+
animation: slotted-progress-indicator-sweep var(--slotted-duration-loop-slow)
|
|
748
|
+
var(--slotted-easing-standard) infinite;
|
|
749
|
+
stroke-opacity: 1;
|
|
750
|
+
/* The transition belongs to a value that changes; a sweep changes every
|
|
751
|
+
frame, and interpolating an interpolation is what makes it stutter. */
|
|
752
|
+
transition: none;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
@keyframes slotted-progress-indicator-turn {
|
|
756
|
+
from {
|
|
757
|
+
rotate: -90deg;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
to {
|
|
761
|
+
rotate: 270deg;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
@keyframes slotted-progress-indicator-sweep {
|
|
766
|
+
0% {
|
|
767
|
+
stroke-dasharray: 4 100;
|
|
768
|
+
stroke-dashoffset: 0;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
50% {
|
|
772
|
+
stroke-dasharray: 62 100;
|
|
773
|
+
stroke-dashoffset: -18;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
100% {
|
|
777
|
+
stroke-dasharray: 4 100;
|
|
778
|
+
stroke-dashoffset: -100;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/* ── The wavy indicator ───────────────────────────────────────────────
|
|
783
|
+
*
|
|
784
|
+
* M3 Expressive's wavy active indicator, on the bar and on the ring, and
|
|
785
|
+
* the one capability in this family no headless library and no other
|
|
786
|
+
* design system surveyed ships at all.
|
|
787
|
+
*
|
|
788
|
+
* Both are drawn the way M3 draws them: the indicator is a stroked path,
|
|
789
|
+
* and what is shown of it is a window cut along its length with round caps
|
|
790
|
+
* at both ends. `LinearWavyProgressModifiers` and
|
|
791
|
+
* `CircularWavyProgressModifiers` cut that window with a `PathMeasure`; a
|
|
792
|
+
* stylesheet cuts it with a dash. Nothing is masked and nothing is clipped
|
|
793
|
+
* square, which is why the bar ends in its own crest at every value and the
|
|
794
|
+
* ring's arc keeps its cap on the wave.
|
|
795
|
+
*
|
|
796
|
+
* Three things move, and each is one number:
|
|
797
|
+
*
|
|
798
|
+
* the phase — `--slotted-progress-indicator-wave-phase`, a clock from
|
|
799
|
+
* nought to one that the root carries and the paths read;
|
|
800
|
+
* the amplitude — `--slotted-progress-indicator-wave-amplitude`, a ramp
|
|
801
|
+
* the value sets, that a paused animation scrubs into a
|
|
802
|
+
* position on `d`;
|
|
803
|
+
* the value — `--slotted-progress-indicator-percent`, which the dash
|
|
804
|
+
* reads as it already does for the plain shapes.
|
|
805
|
+
*/
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* The clock. It runs on the root and the paths inherit it, and its travel
|
|
809
|
+
* is `linear`, which is M3's own answer: `waveSpeed` defaults to one
|
|
810
|
+
* wavelength per second with no easing. A crest that accelerated and slowed
|
|
811
|
+
* would read as a wobble rather than as a wave moving past.
|
|
812
|
+
*
|
|
813
|
+
* The crests travel toward the start of the track — against the fill — on
|
|
814
|
+
* both shapes. Drawn the other way, toward the finish, the wave read on
|
|
815
|
+
* screen as sliding back against the fill; drawn this way it reads as the
|
|
816
|
+
* fill flowing forward. The reading was checked on the bar and on the ring
|
|
817
|
+
* at fast and slow loads, and the geometry below carries the sign once per
|
|
818
|
+
* shape.
|
|
819
|
+
*/
|
|
820
|
+
[data-ui='progress-indicator'][data-part='root'][data-wave] {
|
|
821
|
+
--slotted-progress-indicator-wave-amplitude: min(
|
|
822
|
+
clamp(0, calc((var(--_percent) - 6) / 10), 1),
|
|
823
|
+
clamp(0, calc((96 - var(--_percent)) / 12), 1)
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
animation: slotted-progress-indicator-wave var(--slotted-duration-loop) linear infinite;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* An indeterminate wave has no value to ramp against and is wavy
|
|
831
|
+
* throughout, which is what M3 draws: `hasWavyEffect(isDeterminate)` is the
|
|
832
|
+
* flag that separates the two.
|
|
833
|
+
*/
|
|
834
|
+
[data-ui='progress-indicator'][data-part='root'][data-wave][data-indeterminate] {
|
|
835
|
+
--slotted-progress-indicator-wave-amplitude: 1;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
@keyframes slotted-progress-indicator-wave {
|
|
839
|
+
from {
|
|
840
|
+
--slotted-progress-indicator-wave-phase: 0;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
to {
|
|
844
|
+
--slotted-progress-indicator-wave-phase: 1;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/* ── The wavy bar ─────────────────────────────────────────────────────
|
|
849
|
+
*
|
|
850
|
+
* The indicator is an `svg` laid over the whole track, and inside it one
|
|
851
|
+
* path from `@slotted/core/progress`: M3's sine, in a user space where one
|
|
852
|
+
* unit is one thickness. A 40dp wavelength and a 3dp amplitude on a 4dp
|
|
853
|
+
* stroke are ten thicknesses and three quarters of one, and the viewBox is
|
|
854
|
+
* sized so a unit *is* a thickness at every size and density — the box is
|
|
855
|
+
* twelve hundred thicknesses long and two and a half tall, which is the
|
|
856
|
+
* crest plus half the stroke either side of the centre line.
|
|
857
|
+
*
|
|
858
|
+
* The crest needs room the band does not have. `margin-block` reserves it on
|
|
859
|
+
* the track, and the track's block axis does not clip, so the wave is
|
|
860
|
+
* bounded by its own geometry rather than by a box. The track is also the
|
|
861
|
+
* container the path measures itself against: `cqi` is how a dash stated in
|
|
862
|
+
* thicknesses learns how many thicknesses the track is.
|
|
863
|
+
*/
|
|
864
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='track'] {
|
|
865
|
+
container-type: inline-size;
|
|
866
|
+
margin-block: calc(0.75 * var(--_thickness));
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='indicator'] {
|
|
870
|
+
/** One wavelength, in thicknesses. */
|
|
871
|
+
--_wave-length: 10;
|
|
872
|
+
|
|
873
|
+
background-color: transparent;
|
|
874
|
+
block-size: calc(2.5 * var(--_thickness));
|
|
875
|
+
/* The reach is `PROGRESS_WAVE_BAR_REACH`, and the viewBox in the markup
|
|
876
|
+
states the same number; `progress.test.ts` holds the two together. */
|
|
877
|
+
inline-size: calc(1200 * var(--_thickness));
|
|
878
|
+
inset-block: calc(-0.75 * var(--_thickness)) auto;
|
|
879
|
+
inset-inline-start: 0;
|
|
880
|
+
overflow: visible;
|
|
881
|
+
position: absolute;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* The crest travels with the text. The path is drawn from its own left, so
|
|
886
|
+
* a right-to-left document mirrors the box about its centre — the box is
|
|
887
|
+
* anchored to the inline start, and its centre is the one point that stays
|
|
888
|
+
* inside the track.
|
|
889
|
+
*/
|
|
890
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='indicator']:dir(rtl) {
|
|
891
|
+
transform: scaleX(-1);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* The window, and the three numbers that place it.
|
|
896
|
+
*
|
|
897
|
+
* The path carries `pathLength` equal to its extent along the inline axis,
|
|
898
|
+
* so a dash of one unit is one thickness of travel whatever the amplitude —
|
|
899
|
+
* the arc length of a sine is longer than its span, and normalising the
|
|
900
|
+
* length to the span is what lets the end sit at the value while `d` is
|
|
901
|
+
* mid-transition between flat and wavy.
|
|
902
|
+
*
|
|
903
|
+
* The phase moves the path back by one wavelength over the cycle, and the
|
|
904
|
+
* dash offset hides the same distance, so the window always begins at the
|
|
905
|
+
* track's start whatever crest happens to be there. The crests therefore
|
|
906
|
+
* pass toward the start, and the cycle closes on itself because the path
|
|
907
|
+
* has moved exactly one period. The half unit either
|
|
908
|
+
* side is the cap: the dash starts half a thickness in and ends half a
|
|
909
|
+
* thickness short, so the round caps land on the track's edges exactly where
|
|
910
|
+
* the plain bar's rounded box does — which is how M3 insets the segment by
|
|
911
|
+
* the stroke's radius before capping it.
|
|
912
|
+
*
|
|
913
|
+
* The dash is at least nought. Below one thickness the window is a dot of
|
|
914
|
+
* one thickness, and at nought it is not painted at all, by the same clamp
|
|
915
|
+
* the ring uses on its own cap.
|
|
916
|
+
*/
|
|
917
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='indicator'] path {
|
|
918
|
+
/** The track's length, in thicknesses: a ratio of two lengths, read as a number. */
|
|
919
|
+
--_track-units: tan(atan2(100cqi, var(--_thickness)));
|
|
920
|
+
--_window-start: 0;
|
|
921
|
+
--_window-size: var(--_percent);
|
|
922
|
+
--_hidden: calc(var(--slotted-progress-indicator-wave-phase) * var(--_wave-length));
|
|
923
|
+
|
|
924
|
+
fill: none;
|
|
925
|
+
stroke: var(--_ink);
|
|
926
|
+
stroke-dasharray: max(0, calc(var(--_window-size) * var(--_track-units) / 100 - 1)) 100000;
|
|
927
|
+
stroke-dashoffset: calc(
|
|
928
|
+
-1 * (var(--_hidden) + var(--_window-start) * var(--_track-units) / 100 + 0.5)
|
|
929
|
+
);
|
|
930
|
+
stroke-linecap: round;
|
|
931
|
+
stroke-opacity: clamp(0, calc(var(--_window-size) * 1000), 1);
|
|
932
|
+
stroke-width: 1;
|
|
933
|
+
transform: translateX(calc(-1 * var(--_hidden) * 1px));
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* The amplitude, scrubbed. The keyframes below run `d` from the wave to the
|
|
938
|
+
* flat fitting; the animation is paused and a negative delay picks the frame
|
|
939
|
+
* that the amplitude names, so the crests stand exactly as high as the value
|
|
940
|
+
* says at every moment of the fill's own transition. An indeterminate bar
|
|
941
|
+
* carries a different path and is left to the markup.
|
|
942
|
+
*/
|
|
943
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave]:not([data-indeterminate])
|
|
944
|
+
[data-part='indicator']
|
|
945
|
+
path {
|
|
946
|
+
animation: slotted-progress-indicator-flatten-bar var(--_scrub) var(--_taper) both paused;
|
|
947
|
+
animation-delay: calc(
|
|
948
|
+
-1 * var(--_scrub) * (1 - var(--slotted-progress-indicator-wave-amplitude))
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* The travelling wave. M3 tightens the wavelength to 20dp while the value
|
|
954
|
+
* is unknown — `IndeterminateActiveWaveWavelength` — so the markup carries
|
|
955
|
+
* the tighter path, and the window is the travelling bar's own two numbers.
|
|
956
|
+
*/
|
|
957
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave][data-indeterminate]
|
|
958
|
+
[data-part='indicator'] {
|
|
959
|
+
--_wave-length: 5;
|
|
960
|
+
|
|
961
|
+
animation: slotted-progress-indicator-travel var(--slotted-duration-loop-slow)
|
|
962
|
+
var(--slotted-easing-standard) infinite;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave][data-indeterminate]
|
|
966
|
+
[data-part='indicator']
|
|
967
|
+
path {
|
|
968
|
+
--_window-start: var(--slotted-progress-indicator-travel-start);
|
|
969
|
+
--_window-size: var(--slotted-progress-indicator-travel-size);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/* ── The wavy ring ────────────────────────────────────────────────────
|
|
973
|
+
*
|
|
974
|
+
* The track stays a circle and the indicator becomes the wave, which is
|
|
975
|
+
* what `CircularWavyProgressModifiers` draws: its track polygon is
|
|
976
|
+
* `RoundedPolygon.circle` and only the active indicator morphs.
|
|
977
|
+
*
|
|
978
|
+
* The ring is drawn a fifth again as wide as its step, with the stroke it
|
|
979
|
+
* had. That is M3's own measurement — `WaveSize` is 48dp where `Size` is
|
|
980
|
+
* 40dp, both at a 4dp stroke — because a crest needs radial room a plain
|
|
981
|
+
* stroke does not. Five of forty-eight in a box a fifth larger is the same
|
|
982
|
+
* pixel stroke as six of forty-eight in the plain box, so a ring that turns
|
|
983
|
+
* wavy keeps its weight, and the crest may pass the viewBox by the tenth of
|
|
984
|
+
* a unit the stroke needs.
|
|
985
|
+
*/
|
|
986
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-wave] svg {
|
|
987
|
+
--_stroke: var(--slotted-progress-indicator-stroke, 5);
|
|
988
|
+
|
|
989
|
+
block-size: calc(1.2 * var(--_size));
|
|
990
|
+
inline-size: calc(1.2 * var(--_size));
|
|
991
|
+
overflow: visible;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/**
|
|
995
|
+
* The phase is a rotation, and that is not an approximation. A travelling
|
|
996
|
+
* wave `R + A·sin(Nθ + ωt)` is the standing one rotated by `-ωt/N`, so
|
|
997
|
+
* rotating the path by one crest — 45 degrees at eight — returns the
|
|
998
|
+
* identical shape and the loop has no seam. `CircularWavyProgressModifiers`
|
|
999
|
+
* rotates its own progress path by the same offset angle. The rotation is
|
|
1000
|
+
* anticlockwise, against the arc: the crests travel toward the arc's start,
|
|
1001
|
+
* as the bar's do.
|
|
1002
|
+
*
|
|
1003
|
+
* The dash follows the rotation back, so the arc stays where the value put
|
|
1004
|
+
* it while the crests travel under it. One crest is 12.5 of the hundred
|
|
1005
|
+
* units `pathLength` declares, and a negative offset moves the pattern
|
|
1006
|
+
* away from the path's start — the direction that cancels a rotation
|
|
1007
|
+
* carrying it the other way. The gap is restated as `100 - dash` so the pattern
|
|
1008
|
+
* repeats exactly once per revolution: with the plain ring's gap of 100 the
|
|
1009
|
+
* far end fell into the gap as the pattern shifted, and a full ring opened
|
|
1010
|
+
* a hole at twelve o'clock.
|
|
1011
|
+
*/
|
|
1012
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-wave] [data-part='indicator'] {
|
|
1013
|
+
rotate: calc(-45deg * var(--slotted-progress-indicator-wave-phase));
|
|
1014
|
+
stroke-dasharray: var(--_percent) calc(100 - var(--_percent));
|
|
1015
|
+
stroke-dashoffset: calc(-12.5 * var(--slotted-progress-indicator-wave-phase));
|
|
1016
|
+
/* The rotation is about the viewBox's own centre, which is where the ring
|
|
1017
|
+
is; a fill box would turn it about the path's bounding box instead. */
|
|
1018
|
+
transform-box: view-box;
|
|
1019
|
+
transform-origin: 50% 50%;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-wave]:not([data-indeterminate])
|
|
1023
|
+
[data-part='indicator'] {
|
|
1024
|
+
animation: slotted-progress-indicator-flatten-ring var(--_scrub) var(--_taper) both paused;
|
|
1025
|
+
animation-delay: calc(
|
|
1026
|
+
-1 * var(--_scrub) * (1 - var(--slotted-progress-indicator-wave-amplitude))
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/* ── The amplitude ────────────────────────────────────────────────────
|
|
1031
|
+
*
|
|
1032
|
+
* Two keyframes per shape, from the wave the markup draws to the same
|
|
1033
|
+
* fitting at amplitude nought, and a paused animation the two rules above
|
|
1034
|
+
* scrub with a negative delay. The frame shown is the amplitude, so the
|
|
1035
|
+
* flatten is not an animator of its own with a duration and an easing that
|
|
1036
|
+
* can land early or late: it is the fill's spring, read through the ramp.
|
|
1037
|
+
*
|
|
1038
|
+
* `--_scrub` is the length of the timeline being scrubbed, and any length
|
|
1039
|
+
* would draw the same frames: the delay is the same fraction of it. It is
|
|
1040
|
+
* taken from the scale rather than written as a literal so the stylesheet
|
|
1041
|
+
* states no duration of its own, and the collapsed scale under reduced motion
|
|
1042
|
+
* scrubs a shorter timeline to the same frame. `--_taper` is the shape of
|
|
1043
|
+
* the ramp, not its speed — an S-curve, so the crests leave and return gently
|
|
1044
|
+
* at both ends of the ramp rather than at a constant rate. The two paths of
|
|
1045
|
+
* each pair must share a command list, and `progress.test.ts` holds both
|
|
1046
|
+
* copies to `@slotted/core/progress`.
|
|
1047
|
+
*/
|
|
1048
|
+
[data-ui='progress-indicator'][data-part='root'][data-wave] {
|
|
1049
|
+
--_scrub: var(--slotted-duration-long);
|
|
1050
|
+
--_taper: cubic-bezier(0.45, 0, 0.55, 1);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
@keyframes slotted-progress-indicator-flatten-bar {
|
|
1054
|
+
from {
|
|
1055
|
+
d: path(
|
|
1056
|
+
'M0-0.75c1.82 0 3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5s3.18 1.5 5 1.5s3.18-1.5 5-1.5'
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
to {
|
|
1061
|
+
d: path(
|
|
1062
|
+
'M0 0c1.82 0 3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0s3.18 0 5 0'
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
@keyframes slotted-progress-indicator-flatten-ring {
|
|
1068
|
+
from {
|
|
1069
|
+
d: path(
|
|
1070
|
+
'M45.6 24C45.6 26.83 41.92 28.82 41 31.04C40.08 33.27 41.27 37.27 39.27 39.27C37.27 41.27 33.27 40.08 31.04 41C28.82 41.92 26.83 45.6 24 45.6C21.17 45.6 19.18 41.92 16.96 41C14.73 40.08 10.73 41.27 8.73 39.27C6.73 37.27 7.92 33.27 7 31.04C6.08 28.82 2.4 26.83 2.4 24C2.4 21.17 6.08 19.18 7 16.96C7.92 14.73 6.73 10.73 8.73 8.73C10.73 6.73 14.73 7.92 16.96 7C19.18 6.08 21.17 2.4 24 2.4C26.83 2.4 28.82 6.08 31.04 7C33.27 7.92 37.27 6.73 39.27 8.73C41.27 10.73 40.08 14.73 41 16.96C41.92 19.18 45.6 21.17 45.6 24Z'
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
to {
|
|
1075
|
+
d: path(
|
|
1076
|
+
'M44 24C44 26.62 43.48 29.23 42.48 31.65C41.48 34.07 39.99 36.29 38.14 38.14C36.29 39.99 34.07 41.48 31.65 42.48C29.23 43.48 26.62 44 24 44C21.38 44 18.77 43.48 16.35 42.48C13.93 41.48 11.71 39.99 9.86 38.14C8.01 36.29 6.52 34.07 5.52 31.65C4.52 29.23 4 26.62 4 24C4 21.38 4.52 18.77 5.52 16.35C6.52 13.93 8.01 11.71 9.86 9.86C11.71 8.01 13.93 6.52 16.35 5.52C18.77 4.52 21.38 4 24 4C26.62 4 29.23 4.52 31.65 5.52C34.07 6.52 36.29 8.01 38.14 9.86C39.99 11.71 41.48 13.93 42.48 16.35C43.48 18.77 44 21.38 44 24Z'
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/* ── The loader ───────────────────────────────────────────────────────
|
|
1082
|
+
*
|
|
1083
|
+
* M3 Expressive's loading indicator, which Google recommends *instead of* an
|
|
1084
|
+
* indeterminate circular indicator for a wait under five seconds. Nothing
|
|
1085
|
+
* else surveyed ships it.
|
|
1086
|
+
*
|
|
1087
|
+
* A shape morphs through a sequence while it turns. The two are separate
|
|
1088
|
+
* animations at periods that do not divide into each other, so the sequence
|
|
1089
|
+
* never shows the same shape in the same orientation twice — which is what
|
|
1090
|
+
* makes a five-second wait bearable to watch and a spinning ring not.
|
|
1091
|
+
*/
|
|
1092
|
+
[data-ui='progress-indicator'][data-shape='morph'] [data-part='track'] {
|
|
1093
|
+
block-size: var(--_size);
|
|
1094
|
+
border-radius: var(--slotted-radius-full, 9999px);
|
|
1095
|
+
display: grid;
|
|
1096
|
+
flex: none;
|
|
1097
|
+
inline-size: var(--_size);
|
|
1098
|
+
place-items: center;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* The container M3 draws behind the shape, and the ratio is M3's own: a
|
|
1103
|
+
* 38-point indicator inside a 48-point container. The contrast between the
|
|
1104
|
+
* two is the family's derived track tint against the ink, which is the same
|
|
1105
|
+
* pair the bar's own track holds and clears the 3:1 the loading indicator
|
|
1106
|
+
* documentation asks for between a contained shape and its container.
|
|
1107
|
+
*/
|
|
1108
|
+
[data-ui='progress-indicator'][data-shape='morph'][data-contained] [data-part='track'] {
|
|
1109
|
+
background-color: var(--_track-color);
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* The rotation, and it is two parcels summed — which is the whole mechanism
|
|
1114
|
+
* and the thing a constant spin gets wrong.
|
|
1115
|
+
*
|
|
1116
|
+
* `LoadingIndicatorAnimatorDelegate.java` decomposes it:
|
|
1117
|
+
* `CONSTANT_ROTATION_PER_SHAPE_DEGREES = 50` advances with a linear clock,
|
|
1118
|
+
* `EXTRA_ROTATION_PER_SHAPE_DEGREES = 90` is driven by the *same*
|
|
1119
|
+
* `SpringAnimation` that drives the morph, and the two are added. Ninety of
|
|
1120
|
+
* every hundred and forty degrees therefore lurch with the shape: the object
|
|
1121
|
+
* throws itself around as it changes form and settles as it arrives. The
|
|
1122
|
+
* fifty is the minority parcel and exists so it never freezes between forms.
|
|
1123
|
+
*
|
|
1124
|
+
* A single constant turn — this family's first answer — is the *old*
|
|
1125
|
+
* circular indicator's behaviour, and it is what the loading indicator was
|
|
1126
|
+
* introduced to replace.
|
|
1127
|
+
*
|
|
1128
|
+
* CSS has no way to add two animations of one property without
|
|
1129
|
+
* `animation-composition`, so the sum is expressed geometrically instead: the
|
|
1130
|
+
* container carries the linear parcel and the shape inside it carries the
|
|
1131
|
+
* sprung one, and nested rotations multiply. The container is a circle with a
|
|
1132
|
+
* flat fill, so turning it is invisible — it is turning its child.
|
|
1133
|
+
*
|
|
1134
|
+
* `--slotted-easing-emphasized` is `cubic-bezier(0.3, 0, 0, 1.3)`, and the
|
|
1135
|
+
* `1.3` is the spring: the shape and its rotation both carry a little past
|
|
1136
|
+
* each target and settle. Both animations take it, at the same period and on
|
|
1137
|
+
* the same keyframe boundaries, because in M3 they are one spring.
|
|
1138
|
+
*/
|
|
1139
|
+
[data-ui='progress-indicator'][data-shape='morph'] [data-part='track'] {
|
|
1140
|
+
animation: slotted-progress-indicator-drift calc(2 * var(--slotted-duration-loop-slow)) linear
|
|
1141
|
+
infinite;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
* Two times the slow loop is 3.2 seconds over five shapes — 640 milliseconds
|
|
1146
|
+
* each, which is `DURATION_PER_SHAPE_IN_MS = 650` to within the scale's own
|
|
1147
|
+
* resolution. Multiplying a loop token is deliberate rather than a shortcut
|
|
1148
|
+
* around the motion scale: the three loop durations are the ones the theme
|
|
1149
|
+
* does not collapse, because an endless animation has to stop rather than
|
|
1150
|
+
* hurry, and a multiple of one inherits that where a fourth token would be a
|
|
1151
|
+
* scale step added for a single family.
|
|
1152
|
+
*/
|
|
1153
|
+
[data-ui='progress-indicator'][data-shape='morph'] [data-part='indicator'] {
|
|
1154
|
+
animation:
|
|
1155
|
+
slotted-progress-indicator-morph calc(2 * var(--slotted-duration-loop-slow))
|
|
1156
|
+
var(--slotted-easing-emphasized) infinite,
|
|
1157
|
+
slotted-progress-indicator-lurch calc(2 * var(--slotted-duration-loop-slow))
|
|
1158
|
+
var(--slotted-easing-emphasized) infinite;
|
|
1159
|
+
background-color: var(--_ink);
|
|
1160
|
+
block-size: 100%;
|
|
1161
|
+
inline-size: 100%;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* M3's 38-in-48, rounded to an even number of pixels — and the rounding is
|
|
1166
|
+
* the whole rule rather than a tidy-up.
|
|
1167
|
+
*
|
|
1168
|
+
* A grid centres a box by splitting the remainder in half, so a shape whose
|
|
1169
|
+
* size leaves an odd remainder inside its container sits half a pixel off
|
|
1170
|
+
* centre and the browser rasterises that half-pixel to one side. At `lg` the
|
|
1171
|
+
* ratio happens to land on 30 inside 38 and the shape is centred; at `md` it
|
|
1172
|
+
* lands on 26.86 inside 34, and the capture showed it low and to one side.
|
|
1173
|
+
*
|
|
1174
|
+
* Every control height this family reads is an even number at every density,
|
|
1175
|
+
* so an even shape leaves an even remainder and the two halves are whole
|
|
1176
|
+
* pixels. `round()` is what states that, and it states it once for the three
|
|
1177
|
+
* steps rather than as three numbers.
|
|
1178
|
+
*/
|
|
1179
|
+
[data-ui='progress-indicator'][data-shape='morph'][data-contained] [data-part='indicator'] {
|
|
1180
|
+
--_shape: round(nearest, calc(0.79 * var(--_size)), 2px);
|
|
1181
|
+
|
|
1182
|
+
block-size: var(--_shape);
|
|
1183
|
+
inline-size: var(--_shape);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
/** Fifty degrees a shape, five shapes, one linear turn of the container. */
|
|
1187
|
+
@keyframes slotted-progress-indicator-drift {
|
|
1188
|
+
to {
|
|
1189
|
+
rotate: 250deg;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/**
|
|
1194
|
+
* Ninety degrees a shape, on the morph's own boundaries and the morph's own
|
|
1195
|
+
* curve, so the throw and the change of form are one movement.
|
|
1196
|
+
*/
|
|
1197
|
+
@keyframes slotted-progress-indicator-lurch {
|
|
1198
|
+
0% {
|
|
1199
|
+
rotate: 0deg;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
20% {
|
|
1203
|
+
rotate: 90deg;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
40% {
|
|
1207
|
+
rotate: 180deg;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
60% {
|
|
1211
|
+
rotate: 270deg;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
80% {
|
|
1215
|
+
rotate: 360deg;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
100% {
|
|
1219
|
+
rotate: 450deg;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
@keyframes slotted-progress-indicator-morph {
|
|
1224
|
+
0% {
|
|
1225
|
+
clip-path: polygon(
|
|
1226
|
+
50% 0%,
|
|
1227
|
+
59.8% 1%,
|
|
1228
|
+
69.1% 3.8%,
|
|
1229
|
+
77.8% 8.4%,
|
|
1230
|
+
85.4% 14.6%,
|
|
1231
|
+
91.6% 22.2%,
|
|
1232
|
+
96.2% 30.9%,
|
|
1233
|
+
99% 40.2%,
|
|
1234
|
+
100% 50%,
|
|
1235
|
+
99% 59.8%,
|
|
1236
|
+
96.2% 69.1%,
|
|
1237
|
+
91.6% 77.8%,
|
|
1238
|
+
85.4% 85.4%,
|
|
1239
|
+
77.8% 91.6%,
|
|
1240
|
+
69.1% 96.2%,
|
|
1241
|
+
59.8% 99%,
|
|
1242
|
+
50% 100%,
|
|
1243
|
+
40.2% 99%,
|
|
1244
|
+
30.9% 96.2%,
|
|
1245
|
+
22.2% 91.6%,
|
|
1246
|
+
14.6% 85.4%,
|
|
1247
|
+
8.4% 77.8%,
|
|
1248
|
+
3.8% 69.1%,
|
|
1249
|
+
1% 59.8%,
|
|
1250
|
+
0% 50%,
|
|
1251
|
+
1% 40.2%,
|
|
1252
|
+
3.8% 30.9%,
|
|
1253
|
+
8.4% 22.2%,
|
|
1254
|
+
14.6% 14.6%,
|
|
1255
|
+
22.2% 8.4%,
|
|
1256
|
+
30.9% 3.8%,
|
|
1257
|
+
40.2% 1%
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
20% {
|
|
1262
|
+
clip-path: polygon(
|
|
1263
|
+
50% 0%,
|
|
1264
|
+
59.3% 3.4%,
|
|
1265
|
+
65.9% 11.5%,
|
|
1266
|
+
69.9% 20.3%,
|
|
1267
|
+
73.6% 26.4%,
|
|
1268
|
+
79.7% 30.1%,
|
|
1269
|
+
88.5% 34.1%,
|
|
1270
|
+
96.6% 40.7%,
|
|
1271
|
+
100% 50%,
|
|
1272
|
+
96.6% 59.3%,
|
|
1273
|
+
88.5% 65.9%,
|
|
1274
|
+
79.7% 69.9%,
|
|
1275
|
+
73.6% 73.6%,
|
|
1276
|
+
69.9% 79.7%,
|
|
1277
|
+
65.9% 88.5%,
|
|
1278
|
+
59.3% 96.6%,
|
|
1279
|
+
50% 100%,
|
|
1280
|
+
40.7% 96.6%,
|
|
1281
|
+
34.1% 88.5%,
|
|
1282
|
+
30.1% 79.7%,
|
|
1283
|
+
26.4% 73.6%,
|
|
1284
|
+
20.3% 69.9%,
|
|
1285
|
+
11.5% 65.9%,
|
|
1286
|
+
3.4% 59.3%,
|
|
1287
|
+
0% 50%,
|
|
1288
|
+
3.4% 40.7%,
|
|
1289
|
+
11.5% 34.1%,
|
|
1290
|
+
20.3% 30.1%,
|
|
1291
|
+
26.4% 26.4%,
|
|
1292
|
+
30.1% 20.3%,
|
|
1293
|
+
34.1% 11.5%,
|
|
1294
|
+
40.7% 3.4%
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
40% {
|
|
1299
|
+
clip-path: polygon(
|
|
1300
|
+
50% 6.9%,
|
|
1301
|
+
59.5% 2.1%,
|
|
1302
|
+
68.9% 4.3%,
|
|
1303
|
+
74.7% 13%,
|
|
1304
|
+
77% 23%,
|
|
1305
|
+
80.2% 29.8%,
|
|
1306
|
+
87.4% 34.5%,
|
|
1307
|
+
96% 40.8%,
|
|
1308
|
+
100% 50%,
|
|
1309
|
+
96% 59.2%,
|
|
1310
|
+
87.4% 65.5%,
|
|
1311
|
+
80.2% 70.2%,
|
|
1312
|
+
77% 77%,
|
|
1313
|
+
74.7% 87%,
|
|
1314
|
+
68.9% 95.7%,
|
|
1315
|
+
59.5% 97.9%,
|
|
1316
|
+
50% 93.1%,
|
|
1317
|
+
42.7% 86.7%,
|
|
1318
|
+
35.9% 83.9%,
|
|
1319
|
+
26.8% 84.7%,
|
|
1320
|
+
16.1% 83.9%,
|
|
1321
|
+
8.5% 77.7%,
|
|
1322
|
+
7.7% 67.5%,
|
|
1323
|
+
11.5% 57.7%,
|
|
1324
|
+
13.8% 50%,
|
|
1325
|
+
11.5% 42.3%,
|
|
1326
|
+
7.7% 32.5%,
|
|
1327
|
+
8.5% 22.3%,
|
|
1328
|
+
16.1% 16.1%,
|
|
1329
|
+
26.8% 15.3%,
|
|
1330
|
+
35.9% 16.1%,
|
|
1331
|
+
42.7% 13.3%
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
60% {
|
|
1336
|
+
clip-path: polygon(
|
|
1337
|
+
50% 9.7%,
|
|
1338
|
+
56.8% 15.7%,
|
|
1339
|
+
62% 21%,
|
|
1340
|
+
67.1% 24.4%,
|
|
1341
|
+
73.7% 26.3%,
|
|
1342
|
+
82% 28.6%,
|
|
1343
|
+
90.7% 33.2%,
|
|
1344
|
+
97.4% 40.6%,
|
|
1345
|
+
100% 50%,
|
|
1346
|
+
97.4% 59.4%,
|
|
1347
|
+
90.7% 66.8%,
|
|
1348
|
+
82% 71.4%,
|
|
1349
|
+
73.7% 73.7%,
|
|
1350
|
+
67.1% 75.6%,
|
|
1351
|
+
62% 79%,
|
|
1352
|
+
56.8% 84.3%,
|
|
1353
|
+
50% 90.3%,
|
|
1354
|
+
41.1% 94.8%,
|
|
1355
|
+
31.1% 95.5%,
|
|
1356
|
+
22.3% 91.4%,
|
|
1357
|
+
16.6% 83.4%,
|
|
1358
|
+
14.9% 73.5%,
|
|
1359
|
+
16.2% 64%,
|
|
1360
|
+
18.3% 56.3%,
|
|
1361
|
+
19.4% 50%,
|
|
1362
|
+
18.3% 43.7%,
|
|
1363
|
+
16.2% 36%,
|
|
1364
|
+
14.9% 26.5%,
|
|
1365
|
+
16.6% 16.6%,
|
|
1366
|
+
22.3% 8.6%,
|
|
1367
|
+
31.1% 4.5%,
|
|
1368
|
+
41.1% 5.2%
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
80% {
|
|
1373
|
+
clip-path: polygon(
|
|
1374
|
+
50% 23.1%,
|
|
1375
|
+
55.4% 22.7%,
|
|
1376
|
+
61.6% 22%,
|
|
1377
|
+
68.9% 21.7%,
|
|
1378
|
+
77.2% 22.8%,
|
|
1379
|
+
85.7% 26.2%,
|
|
1380
|
+
93.1% 32.2%,
|
|
1381
|
+
98.2% 40.4%,
|
|
1382
|
+
100% 50%,
|
|
1383
|
+
98.2% 59.6%,
|
|
1384
|
+
93.1% 67.8%,
|
|
1385
|
+
85.7% 73.8%,
|
|
1386
|
+
77.2% 77.2%,
|
|
1387
|
+
68.9% 78.3%,
|
|
1388
|
+
61.6% 78%,
|
|
1389
|
+
55.4% 77.3%,
|
|
1390
|
+
50% 76.9%,
|
|
1391
|
+
44.6% 77.3%,
|
|
1392
|
+
38.4% 78%,
|
|
1393
|
+
31.1% 78.3%,
|
|
1394
|
+
22.8% 77.2%,
|
|
1395
|
+
14.3% 73.8%,
|
|
1396
|
+
6.9% 67.8%,
|
|
1397
|
+
1.8% 59.6%,
|
|
1398
|
+
0% 50%,
|
|
1399
|
+
1.8% 40.4%,
|
|
1400
|
+
6.9% 32.2%,
|
|
1401
|
+
14.3% 26.2%,
|
|
1402
|
+
22.8% 22.8%,
|
|
1403
|
+
31.1% 21.7%,
|
|
1404
|
+
38.4% 22%,
|
|
1405
|
+
44.6% 22.7%
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
100% {
|
|
1410
|
+
clip-path: polygon(
|
|
1411
|
+
50% 0%,
|
|
1412
|
+
59.8% 1%,
|
|
1413
|
+
69.1% 3.8%,
|
|
1414
|
+
77.8% 8.4%,
|
|
1415
|
+
85.4% 14.6%,
|
|
1416
|
+
91.6% 22.2%,
|
|
1417
|
+
96.2% 30.9%,
|
|
1418
|
+
99% 40.2%,
|
|
1419
|
+
100% 50%,
|
|
1420
|
+
99% 59.8%,
|
|
1421
|
+
96.2% 69.1%,
|
|
1422
|
+
91.6% 77.8%,
|
|
1423
|
+
85.4% 85.4%,
|
|
1424
|
+
77.8% 91.6%,
|
|
1425
|
+
69.1% 96.2%,
|
|
1426
|
+
59.8% 99%,
|
|
1427
|
+
50% 100%,
|
|
1428
|
+
40.2% 99%,
|
|
1429
|
+
30.9% 96.2%,
|
|
1430
|
+
22.2% 91.6%,
|
|
1431
|
+
14.6% 85.4%,
|
|
1432
|
+
8.4% 77.8%,
|
|
1433
|
+
3.8% 69.1%,
|
|
1434
|
+
1% 59.8%,
|
|
1435
|
+
0% 50%,
|
|
1436
|
+
1% 40.2%,
|
|
1437
|
+
3.8% 30.9%,
|
|
1438
|
+
8.4% 22.2%,
|
|
1439
|
+
14.6% 14.6%,
|
|
1440
|
+
22.2% 8.4%,
|
|
1441
|
+
30.9% 3.8%,
|
|
1442
|
+
40.2% 1%
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
/* ── Reduced motion ───────────────────────────────────────────────────
|
|
1448
|
+
*
|
|
1449
|
+
* Stopped, not slowed. `spinner` slowed its ring on the grounds that a
|
|
1450
|
+
* stopped ring says nothing, and the token foundation now refuses that
|
|
1451
|
+
* reading in as many words: an animation that repeats forever needs to stop
|
|
1452
|
+
* rather than to hurry.
|
|
1453
|
+
*
|
|
1454
|
+
* The cost is paid rather than hidden. An indeterminate indicator that does
|
|
1455
|
+
* not move is a static graphic, so its meaning has to come from somewhere
|
|
1456
|
+
* else — the `progressbar` role, the accessible name both bindings require,
|
|
1457
|
+
* and the visible label the reference page recommends for the loader. The
|
|
1458
|
+
* three loop durations are the ones the theme deliberately does not
|
|
1459
|
+
* shorten, which is what makes stopping the only available answer.
|
|
1460
|
+
*/
|
|
1461
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1462
|
+
/**
|
|
1463
|
+
* Important, and that is the point of the rule: the preference outranks
|
|
1464
|
+
* every animated rule in the family whatever its specificity. Without it
|
|
1465
|
+
* the travelling bar, the turning ring, the sweep, the drift and the
|
|
1466
|
+
* morph all kept moving, because each is started by a selector that names
|
|
1467
|
+
* its shape and its state and so outweighs one that names the part. A
|
|
1468
|
+
* `path` is left out: the wave's paths carry the paused ramp below, which
|
|
1469
|
+
* is a value and survives.
|
|
1470
|
+
*/
|
|
1471
|
+
[data-ui='progress-indicator'][data-part='root'],
|
|
1472
|
+
[data-ui='progress-indicator'] [data-part='indicator']:not(path),
|
|
1473
|
+
[data-ui='progress-indicator'] [data-part='track'],
|
|
1474
|
+
[data-ui='progress-indicator'] svg {
|
|
1475
|
+
animation: none !important;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
* The travelling bar has nowhere to be when it stops. Halfway along the
|
|
1480
|
+
* track at its widest is the one position that reads as a wait rather
|
|
1481
|
+
* than as a value: pinned to either end it would read as nought per cent
|
|
1482
|
+
* or as a hundred, which is a number this indicator does not have.
|
|
1483
|
+
*/
|
|
1484
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-indeterminate]
|
|
1485
|
+
[data-part='indicator'] {
|
|
1486
|
+
--slotted-progress-indicator-travel-size: 46;
|
|
1487
|
+
--slotted-progress-indicator-travel-start: 27;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/**
|
|
1491
|
+
* The same question for the arc, and the same answer: a third of the ring
|
|
1492
|
+
* is unmistakably a fraction of something rather than a full circle or an
|
|
1493
|
+
* empty one.
|
|
1494
|
+
*/
|
|
1495
|
+
[data-ui='progress-indicator'][data-shape='circular'][data-indeterminate]
|
|
1496
|
+
[data-part='indicator'] {
|
|
1497
|
+
stroke-dasharray: 34 100;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/**
|
|
1501
|
+
* The wave stands still. The ramp that flattens it at either end of the
|
|
1502
|
+
* range survives, because it is a value rather than motion: a ring at four
|
|
1503
|
+
* per cent is a circle whether or not anything moves.
|
|
1504
|
+
*/
|
|
1505
|
+
[data-ui='progress-indicator'][data-part='root'][data-wave] {
|
|
1506
|
+
animation: none;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/* ── Forced colours ───────────────────────────────────────────────────
|
|
1511
|
+
*
|
|
1512
|
+
* The operating system replaces every author colour, so the tone is gone
|
|
1513
|
+
* whatever the family writes and the five tones become one indicator. What
|
|
1514
|
+
* is left to decide is whether the geometry survives, and three things do
|
|
1515
|
+
* not survive on their own: a `color-mix` of two forced colours is still a
|
|
1516
|
+
* mix and paints an author colour the system did not choose; a masked
|
|
1517
|
+
* indicator is masked by artwork the system does not replace; and a
|
|
1518
|
+
* `clip-path` shape has no edge of its own to be seen by.
|
|
1519
|
+
*
|
|
1520
|
+
* The remaining track therefore moves from the pseudo-element to the track
|
|
1521
|
+
* itself, which is a real element the system palette reaches — a decorative
|
|
1522
|
+
* rule may not name a system colour at all, and
|
|
1523
|
+
* `packages/styles/src/fallbacks.test.mjs` is what holds that. The gap goes
|
|
1524
|
+
* with it, and a gap is a refinement rather than a meaning.
|
|
1525
|
+
*/
|
|
1526
|
+
@media (forced-colors: active) {
|
|
1527
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track'] {
|
|
1528
|
+
background-color: Canvas;
|
|
1529
|
+
outline: var(--slotted-border-width-thin, 1px) solid ButtonBorder;
|
|
1530
|
+
outline-offset: calc(-1 * var(--slotted-border-width-thin, 1px));
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::before,
|
|
1534
|
+
[data-ui='progress-indicator'][data-shape='linear'] [data-part='track']::after {
|
|
1535
|
+
content: none;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
/**
|
|
1539
|
+
* An edge bar keeps no track of its own. The box it stands on already
|
|
1540
|
+
* draws its edge in a system colour, and an outline here would be a
|
|
1541
|
+
* second line beside the first.
|
|
1542
|
+
*/
|
|
1543
|
+
[data-ui='progress-indicator']:is([data-placement='edge-start'], [data-placement='edge-end'])
|
|
1544
|
+
[data-part='track'] {
|
|
1545
|
+
background-color: transparent;
|
|
1546
|
+
outline: none;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
[data-ui='progress-indicator'] [data-part='indicator'] {
|
|
1550
|
+
background-color: Highlight;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* The wavy bar is a stroke, so it keeps its crests under the palette the
|
|
1555
|
+
* way the ring does: the box behind it stays clear and the path takes
|
|
1556
|
+
* the highlight.
|
|
1557
|
+
*/
|
|
1558
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='indicator'] {
|
|
1559
|
+
background-color: transparent;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
[data-ui='progress-indicator'][data-shape='linear'][data-wave] [data-part='indicator'] path {
|
|
1563
|
+
stroke: Highlight;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='indicator'] {
|
|
1567
|
+
background-color: transparent;
|
|
1568
|
+
stroke: Highlight;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
[data-ui='progress-indicator'][data-shape='circular'] [data-part='track'] {
|
|
1572
|
+
stroke: ButtonBorder;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
/**
|
|
1576
|
+
* The morphing shape keeps its silhouette — that is the whole reason the
|
|
1577
|
+
* loader exists — and loses the container behind it, which in a forced
|
|
1578
|
+
* palette would be a `Canvas` disc on a `Canvas` page.
|
|
1579
|
+
*/
|
|
1580
|
+
[data-ui='progress-indicator'][data-shape='morph'][data-contained] [data-part='track'] {
|
|
1581
|
+
background-color: Canvas;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
}
|