@slotted/styles 0.0.0-stage → 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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,792 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* ── A scale, a rail and one thumb per value ────────────────────────────
|
|
4
|
+
*
|
|
5
|
+
* Every thumb is a real `input[type="range"]`, so the `slider` role, the
|
|
6
|
+
* value set, form submission, form reset and `disabled` come from the
|
|
7
|
+
* platform. The input is invisible and unhittable — `opacity: 0` and
|
|
8
|
+
* `pointer-events: none`, filling the thumb it lives in — because the thumb
|
|
9
|
+
* a reader sees is this family's own element and the drag is the family's
|
|
10
|
+
* own gesture.
|
|
11
|
+
*
|
|
12
|
+
* `track` is the containing block for everything that has a position on the
|
|
13
|
+
* scale: the fill, every mark and every thumb. It is inset by half a thumb
|
|
14
|
+
* at each end of the control, so a thumb at either bound is contained rather
|
|
15
|
+
* than half outside, and the focus ring around it is never clipped.
|
|
16
|
+
*
|
|
17
|
+
* Every position is a private custom property written by the binding —
|
|
18
|
+
* `--_position` on a thumb or a mark, `--_start` and `--_end` on the fill.
|
|
19
|
+
* A percentage of a track is geometry and geometry is not a token.
|
|
20
|
+
*/
|
|
21
|
+
[data-ui='slider'][data-part='root'] {
|
|
22
|
+
/**
|
|
23
|
+
* Type, glyph and gap come from the control scales — the only ones the
|
|
24
|
+
* theme restates per density — so a slider in a dense row shrinks whole
|
|
25
|
+
* rather than in parts.
|
|
26
|
+
*/
|
|
27
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
28
|
+
--_gap: var(--slotted-control-gap-md, 8px);
|
|
29
|
+
--_icon-size: var(--slotted-control-icon-size-md, 16px);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The thumb is the control glyph plus one space step. It is arithmetic
|
|
33
|
+
* over two scales rather than a literal, and it is not a component token:
|
|
34
|
+
* the component layer's bar is that a family may not restate a scale that
|
|
35
|
+
* already exists.
|
|
36
|
+
*/
|
|
37
|
+
--_thumb-size: var(
|
|
38
|
+
--slotted-slider-thumb-size,
|
|
39
|
+
calc(var(--_icon-size) + var(--slotted-space-2, 0.25rem))
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The rail's weight does not change with the size. A rail is a channel
|
|
44
|
+
* rather than a control, so only the thumb, the type and the target grow.
|
|
45
|
+
* Six pixels is a one-pixel edge on each side and four of interior, which
|
|
46
|
+
* is the smallest channel a fill can be seen inside.
|
|
47
|
+
*/
|
|
48
|
+
--_track-size: var(--slotted-slider-track-size, var(--slotted-space-3, 0.375rem));
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The band the pointer aims at, floored at the WCAG 2.2 minimum. A thumb
|
|
52
|
+
* at the tightest step is twenty pixels across, and the correction of a
|
|
53
|
+
* target short in one axis is the family's rather than the theme's.
|
|
54
|
+
*/
|
|
55
|
+
--_control-size: max(var(--slotted-target-min, 24px), var(--_thumb-size));
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Where a mark's tick begins: past the thumb, so a tick is never drawn
|
|
59
|
+
* under one. Marks are ruler ticks outside the rail rather than dots on
|
|
60
|
+
* it, because a dot on the rail has to be legible against the fill and
|
|
61
|
+
* against the empty channel at once, and in the `high-contrast` scheme —
|
|
62
|
+
* where the palette is two colours — it cannot be both.
|
|
63
|
+
*/
|
|
64
|
+
--_mark-gap: calc(
|
|
65
|
+
(var(--_thumb-size) - var(--_track-size)) / 2 + var(--slotted-space-1, 0.125rem)
|
|
66
|
+
);
|
|
67
|
+
--_mark-length: var(--slotted-space-2, 0.25rem);
|
|
68
|
+
--_mark-label-line: calc(
|
|
69
|
+
var(--slotted-font-size-xs, 0.75rem) * var(--slotted-line-height-xs, 1.4)
|
|
70
|
+
);
|
|
71
|
+
/**
|
|
72
|
+
* How wide a mark's label may be before it wraps: three thumbs, which is
|
|
73
|
+
* about two words at the medium step.
|
|
74
|
+
*
|
|
75
|
+
* The family declares no container and asks no query. One was written — a
|
|
76
|
+
* narrower cap for the labels below 320 pixels — and taken out again,
|
|
77
|
+
* because a label of one long word cannot wrap at any cap, so the query
|
|
78
|
+
* only ever moved the multi-word ones and a scale of five single words was
|
|
79
|
+
* unchanged by it. A slider is fluid rather than reflowing: the rail
|
|
80
|
+
* shrinks, the thumb and the type do not, and a label longer than the space
|
|
81
|
+
* between two ticks overflows its own box rather than being clipped or
|
|
82
|
+
* removed.
|
|
83
|
+
*/
|
|
84
|
+
--_mark-label-size: calc(var(--_thumb-size) * 3);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The room the bubble stands in, reserved whether or not it is showing.
|
|
88
|
+
* Reserved, the control does not move when a drag starts, and the bubble
|
|
89
|
+
* does not land on the read-out above it — which is what the first capture
|
|
90
|
+
* of the `content` scene showed, with a value printed over its own number.
|
|
91
|
+
*/
|
|
92
|
+
--_bubble-size: calc(
|
|
93
|
+
var(--slotted-font-size-xs, 0.75rem) * var(--slotted-line-height-xs, 1.4) +
|
|
94
|
+
var(--slotted-space-1, 0.125rem) * 2 + var(--slotted-space-2, 0.25rem)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
color: var(--slotted-slider-color, var(--slotted-text, CanvasText));
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
font-family: var(--slotted-control-font-family, system-ui, sans-serif);
|
|
101
|
+
font-size: var(--_font-size);
|
|
102
|
+
gap: var(--_gap);
|
|
103
|
+
/* A slider in a grid track narrower than its intrinsic width has to shrink. */
|
|
104
|
+
min-inline-size: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A horizontal slider takes the width it is offered, the way every other
|
|
109
|
+
* control in this library does. It has no intrinsic width of its own — the
|
|
110
|
+
* rail is a percentage of a box that is a percentage of the root — so in a
|
|
111
|
+
* shrink-to-fit column it collapsed to the width of its own read-out, and the
|
|
112
|
+
* React reference page showed three numbers with three bare thumbs under
|
|
113
|
+
* them and no rail at all. A vertical slider is left alone: its cross
|
|
114
|
+
* measurement is the band, and its length is its own.
|
|
115
|
+
*/
|
|
116
|
+
[data-ui='slider'][data-part='root'][data-orientation='horizontal'] {
|
|
117
|
+
inline-size: 100%;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
[data-ui='slider'][data-part='root'][data-size='sm'] {
|
|
121
|
+
--_font-size: var(--slotted-control-font-size-sm, 12px);
|
|
122
|
+
--_gap: var(--slotted-control-gap-sm, 6px);
|
|
123
|
+
--_icon-size: var(--slotted-control-icon-size-sm, 14px);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
[data-ui='slider'][data-part='root'][data-size='md'] {
|
|
127
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
128
|
+
--_gap: var(--slotted-control-gap-md, 8px);
|
|
129
|
+
--_icon-size: var(--slotted-control-icon-size-md, 16px);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
[data-ui='slider'][data-part='root'][data-size='lg'] {
|
|
133
|
+
--_font-size: var(--slotted-control-font-size-lg, 14px);
|
|
134
|
+
--_gap: var(--slotted-control-gap-lg, 8px);
|
|
135
|
+
--_icon-size: var(--slotted-control-icon-size-lg, 18px);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ── The read-out ─────────────────────────────────────────────────────
|
|
139
|
+
*
|
|
140
|
+
* The label is the field's; this is the value. It is set at full strength
|
|
141
|
+
* rather than muted, because it is the datum a reader came for, and in
|
|
142
|
+
* tabular figures because a number that changes under a drag must not change
|
|
143
|
+
* width while it does.
|
|
144
|
+
*/
|
|
145
|
+
[data-ui='slider'] > [data-part='output'] {
|
|
146
|
+
align-self: flex-end;
|
|
147
|
+
color: var(--slotted-slider-output-color, var(--slotted-text, CanvasText));
|
|
148
|
+
font-variant-numeric: tabular-nums;
|
|
149
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
150
|
+
line-height: var(--slotted-line-height-sm, 1.45);
|
|
151
|
+
/* Its own bidi run: a number has no strong character to order it. */
|
|
152
|
+
unicode-bidi: plaintext;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ── The band ─────────────────────────────────────────────────────────
|
|
156
|
+
*
|
|
157
|
+
* The whole of the pointer target, and the containing block the track is
|
|
158
|
+
* inset inside. It is `touch-action: none` because a drag along the scale
|
|
159
|
+
* and a scroll of the page are the same gesture, and the one the pointer
|
|
160
|
+
* started on the control is the drag.
|
|
161
|
+
*/
|
|
162
|
+
[data-ui='slider'] [data-part='control'] {
|
|
163
|
+
align-items: center;
|
|
164
|
+
/**
|
|
165
|
+
* The reserve for the two half thumbs comes out of the band rather than
|
|
166
|
+
* being added to it. Written as padding on a content box, a band told to
|
|
167
|
+
* fill its root measured a whole thumb wider than the root — 260px inside
|
|
168
|
+
* 240px — and the overflow travelled up through `stack` and `field` to the
|
|
169
|
+
* stage, which then scrolled. The band is what the root gives it; the
|
|
170
|
+
* scale inside is what is left after the reserve.
|
|
171
|
+
*/
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
display: flex;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
position: relative;
|
|
177
|
+
touch-action: none;
|
|
178
|
+
-webkit-tap-highlight-color: transparent;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='control'] {
|
|
182
|
+
block-size: var(--_control-size);
|
|
183
|
+
inline-size: 100%;
|
|
184
|
+
padding-inline: calc(var(--_thumb-size) / 2);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The room the bubble stands in, less the gap the root already put there.
|
|
189
|
+
* Added whole, the two stacked: the `marks` capture showed the read-out a
|
|
190
|
+
* finger's width above its own rail, reading as a separate line rather than
|
|
191
|
+
* as this control's value.
|
|
192
|
+
*/
|
|
193
|
+
[data-ui='slider'][data-orientation='horizontal']:not([data-value-label='none'])
|
|
194
|
+
[data-part='control'] {
|
|
195
|
+
margin-block-start: max(0px, calc(var(--_bubble-size) - var(--_gap)));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The vertical bubble reserves nothing. It stands beside its own thumb, and
|
|
200
|
+
* the read-out it could collide with is above the control rather than beside
|
|
201
|
+
* it; reserving four thumb widths of empty column on every vertical slider
|
|
202
|
+
* cost more than the overlap it prevented.
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='control'] {
|
|
206
|
+
/**
|
|
207
|
+
* A vertical slider has no intrinsic length, so it takes one: ten thumbs
|
|
208
|
+
* is a scale a reader can point at, and a consumer who wants another one
|
|
209
|
+
* writes it on the root. The value is arithmetic over the thumb, not a
|
|
210
|
+
* scale of its own.
|
|
211
|
+
*
|
|
212
|
+
* The token stays the scale. On a border box the reserve is inside the
|
|
213
|
+
* band, so the band is the scale plus the two half thumbs — which leaves
|
|
214
|
+
* the track measuring exactly what the consumer asked for, as it did
|
|
215
|
+
* before the box changed.
|
|
216
|
+
*/
|
|
217
|
+
block-size: calc(
|
|
218
|
+
var(--slotted-slider-length, calc(var(--_thumb-size) * 10)) + var(--_thumb-size)
|
|
219
|
+
);
|
|
220
|
+
inline-size: var(--_control-size);
|
|
221
|
+
padding-block: calc(var(--_thumb-size) / 2);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* The room a scale of marks takes outside the rail. It is reserved rather
|
|
226
|
+
* than discovered, so a family below the slider does not move when a label
|
|
227
|
+
* appears.
|
|
228
|
+
*/
|
|
229
|
+
[data-ui='slider'][data-orientation='horizontal'][data-marks='ticks'] [data-part='control'] {
|
|
230
|
+
margin-block-end: var(--_mark-length);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
[data-ui='slider'][data-orientation='horizontal'][data-marks='labelled'] [data-part='control'] {
|
|
234
|
+
margin-block-end: calc(
|
|
235
|
+
var(--_mark-length) + var(--slotted-space-1, 0.125rem) + var(--_mark-label-line)
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
[data-ui='slider'][data-orientation='vertical'][data-marks='ticks'] [data-part='control'] {
|
|
240
|
+
margin-inline-end: var(--_mark-length);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
[data-ui='slider'][data-orientation='vertical'][data-marks='labelled'] [data-part='control'] {
|
|
244
|
+
margin-inline-end: calc(
|
|
245
|
+
var(--_mark-length) + var(--slotted-space-1, 0.125rem) + var(--_mark-label-size)
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ── The rail ─────────────────────────────────────────────────────────
|
|
250
|
+
*
|
|
251
|
+
* A channel rather than a line: an edge that holds the 3:1 a non-text
|
|
252
|
+
* element needs against every surface, and an interior the fill is seen
|
|
253
|
+
* inside. A rail painted as one flat neutral cannot do both — in the
|
|
254
|
+
* `high-contrast` scheme every neutral is the same black, and the first
|
|
255
|
+
* capture showed a black rail with a nearly black fill on it.
|
|
256
|
+
*
|
|
257
|
+
* It is inset by half a thumb at each end of the control, so the scale's two
|
|
258
|
+
* bounds are the two places a thumb's centre can reach and the thumb itself
|
|
259
|
+
* stays inside the band.
|
|
260
|
+
*/
|
|
261
|
+
[data-ui='slider'] [data-part='track'] {
|
|
262
|
+
background-color: var(--slotted-slider-track-color, var(--slotted-surface-sunken, Canvas));
|
|
263
|
+
border: var(--slotted-control-border-width, 1px) solid
|
|
264
|
+
var(--slotted-slider-track-border-color, var(--slotted-control-border-color, ButtonBorder));
|
|
265
|
+
border-radius: var(--slotted-radius-full, 9999px);
|
|
266
|
+
box-sizing: border-box;
|
|
267
|
+
position: relative;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='track'] {
|
|
271
|
+
block-size: var(--_track-size);
|
|
272
|
+
inline-size: 100%;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='track'] {
|
|
276
|
+
block-size: 100%;
|
|
277
|
+
inline-size: var(--_track-size);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* The filled portion, between the origin and the value. `--_start` and
|
|
282
|
+
* `--_end` are two percentages rather than a length and an offset, so a
|
|
283
|
+
* range fills between its thumbs and a slider with a centred origin fills
|
|
284
|
+
* outward from the middle with the same two declarations.
|
|
285
|
+
*
|
|
286
|
+
* On the cross axis it is laid against the track's *border* box and not its
|
|
287
|
+
* padding box, which is one negative inset and the whole of SR1. An
|
|
288
|
+
* absolutely positioned box is placed inside the padding of its containing
|
|
289
|
+
* block, so a fill left at nought stopped a pixel short of each edge and the
|
|
290
|
+
* channel's own neutral line ran across the accent: on a track of six pixels
|
|
291
|
+
* the fill was four, with the edge painted over the top and the bottom of it.
|
|
292
|
+
* A filled scale is one solid band, and the rim belongs to the part of the
|
|
293
|
+
* scale that is still empty.
|
|
294
|
+
*
|
|
295
|
+
* The main axis keeps the padding box, so the two ends of the channel keep
|
|
296
|
+
* their rim: the fill runs from a percentage of the scale, and a fill that
|
|
297
|
+
* overhung there would leave a pixel of accent past the value at one end and
|
|
298
|
+
* cover the cap at the other.
|
|
299
|
+
*/
|
|
300
|
+
[data-ui='slider'] [data-part='indicator'] {
|
|
301
|
+
--_edge-overlap: calc(var(--slotted-control-border-width, 1px) * -1);
|
|
302
|
+
|
|
303
|
+
background-color: var(--slotted-slider-indicator-color, var(--slotted-tone-accent-solid));
|
|
304
|
+
border-radius: inherit;
|
|
305
|
+
position: absolute;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='indicator'] {
|
|
309
|
+
inset-block: var(--_edge-overlap);
|
|
310
|
+
inset-inline-start: calc(var(--_start, 0) * 1%);
|
|
311
|
+
inline-size: calc((var(--_end, 0) - var(--_start, 0)) * 1%);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='indicator'] {
|
|
315
|
+
inset-inline: var(--_edge-overlap);
|
|
316
|
+
inset-block-end: calc(var(--_start, 0) * 1%);
|
|
317
|
+
block-size: calc((var(--_end, 0) - var(--_start, 0)) * 1%);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* ── Marks ────────────────────────────────────────────────────────────
|
|
321
|
+
*
|
|
322
|
+
* Ruler ticks alongside the rail, with the label under each one. A tick on
|
|
323
|
+
* the rail would have to read against the fill and against the empty channel
|
|
324
|
+
* at once; beside it, it reads against the page in every scheme.
|
|
325
|
+
*/
|
|
326
|
+
[data-ui='slider'] [data-part='mark'] {
|
|
327
|
+
background-color: var(--slotted-slider-mark-color, var(--slotted-border-strong, CanvasText));
|
|
328
|
+
position: absolute;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='mark'] {
|
|
332
|
+
block-size: var(--_mark-length);
|
|
333
|
+
inline-size: var(--slotted-border-width-thin, 1px);
|
|
334
|
+
inset-block-start: calc(100% + var(--_mark-gap));
|
|
335
|
+
inset-inline-start: calc(var(--_position, 0) * 1%);
|
|
336
|
+
margin-inline-start: calc(var(--slotted-border-width-thin, 1px) / -2);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='mark'] {
|
|
340
|
+
block-size: var(--slotted-border-width-thin, 1px);
|
|
341
|
+
inline-size: var(--_mark-length);
|
|
342
|
+
inset-inline-start: calc(100% + var(--_mark-gap));
|
|
343
|
+
inset-block-end: calc(var(--_position, 0) * 1%);
|
|
344
|
+
margin-block-end: calc(var(--slotted-border-width-thin, 1px) / -2);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
[data-ui='slider'] [data-part='mark-label'] {
|
|
348
|
+
color: var(--slotted-slider-mark-label-color, var(--slotted-text-muted, GrayText));
|
|
349
|
+
display: block;
|
|
350
|
+
font-size: var(--slotted-font-size-xs, 0.75rem);
|
|
351
|
+
inline-size: max-content;
|
|
352
|
+
line-height: var(--slotted-line-height-xs, 1.4);
|
|
353
|
+
max-inline-size: var(--_mark-label-size);
|
|
354
|
+
/**
|
|
355
|
+
* The cap is three thumbs, and one word can be wider than three thumbs
|
|
356
|
+
* without a space to break at: `Reduzido` measured 55px inside 51px at
|
|
357
|
+
* `dense`, and those four pixels were read at the mark, which is one pixel
|
|
358
|
+
* wide and forgives only what the label's placement explains. A label
|
|
359
|
+
* breaks inside a word rather than standing outside its own box.
|
|
360
|
+
*/
|
|
361
|
+
overflow-wrap: anywhere;
|
|
362
|
+
position: absolute;
|
|
363
|
+
text-align: center;
|
|
364
|
+
unicode-bidi: plaintext;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='mark-label'] {
|
|
368
|
+
inset-block-start: calc(100% + var(--slotted-space-1, 0.125rem));
|
|
369
|
+
inset-inline-start: 50%;
|
|
370
|
+
translate: -50% 0;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* The label at either end of the scale is aligned inside rather than centred
|
|
375
|
+
* on its tick. Centred, half of it hangs off the control: the first capture
|
|
376
|
+
* of the `marks` scene showed "Máximo" clipped by the edge of the cell, and
|
|
377
|
+
* a scale whose last label cannot be read is a scale with four labels.
|
|
378
|
+
*/
|
|
379
|
+
[data-ui='slider'][data-orientation='horizontal']
|
|
380
|
+
[data-part='mark'][data-edge='start']
|
|
381
|
+
[data-part='mark-label'] {
|
|
382
|
+
inset-inline-start: 0;
|
|
383
|
+
text-align: start;
|
|
384
|
+
translate: 0 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* An edge label takes its own measure and grows inward. The shared cap makes
|
|
389
|
+
* a word longer than the cap overflow toward the inline end, which for the
|
|
390
|
+
* label at the end of the scale is off the control: the 240-pixel capture
|
|
391
|
+
* printed "Máximo" over the edge of its own cell.
|
|
392
|
+
*/
|
|
393
|
+
[data-ui='slider'][data-orientation='horizontal']
|
|
394
|
+
[data-part='mark'][data-edge]
|
|
395
|
+
[data-part='mark-label'] {
|
|
396
|
+
max-inline-size: none;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
[data-ui='slider'][data-orientation='horizontal']
|
|
400
|
+
[data-part='mark'][data-edge='end']
|
|
401
|
+
[data-part='mark-label'] {
|
|
402
|
+
inset-inline-end: 0;
|
|
403
|
+
inset-inline-start: auto;
|
|
404
|
+
text-align: end;
|
|
405
|
+
translate: 0 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* The one place this family names a side, and only in the mirrored document.
|
|
410
|
+
* `translate` is a physical transform: a percentage along the inline axis
|
|
411
|
+
* moves the box left in both directions, so a right-to-left page would hang
|
|
412
|
+
* every centred label half a box off its own tick.
|
|
413
|
+
*/
|
|
414
|
+
[data-ui='slider'][data-orientation='horizontal']:dir(rtl)
|
|
415
|
+
[data-part='mark']:not([data-edge])
|
|
416
|
+
[data-part='mark-label'] {
|
|
417
|
+
translate: 50% 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='mark-label'] {
|
|
421
|
+
inset-block-start: 50%;
|
|
422
|
+
inset-inline-start: calc(100% + var(--slotted-space-1, 0.125rem));
|
|
423
|
+
text-align: start;
|
|
424
|
+
translate: 0 -50%;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* ── The thumb ────────────────────────────────────────────────────────
|
|
428
|
+
*
|
|
429
|
+
* Centred on its position by a logical margin rather than by `translate`, so
|
|
430
|
+
* the mirrored document needs no rule of its own: `margin-inline-start`
|
|
431
|
+
* measures from whichever edge `inset-inline-start` measured from.
|
|
432
|
+
*/
|
|
433
|
+
[data-ui='slider'] [data-part='thumb'] {
|
|
434
|
+
background-color: var(--slotted-slider-thumb-color, var(--slotted-surface, Canvas));
|
|
435
|
+
block-size: var(--_thumb-size);
|
|
436
|
+
border: var(--slotted-border-width-thick, 2px) solid
|
|
437
|
+
var(--slotted-slider-thumb-border-color, var(--slotted-tone-accent-solid));
|
|
438
|
+
border-radius: var(--slotted-radius-full, 9999px);
|
|
439
|
+
box-shadow: var(--slotted-slider-thumb-shadow, var(--slotted-control-shadow, none));
|
|
440
|
+
box-sizing: border-box;
|
|
441
|
+
cursor: grab;
|
|
442
|
+
display: block;
|
|
443
|
+
inline-size: var(--_thumb-size);
|
|
444
|
+
position: absolute;
|
|
445
|
+
transition:
|
|
446
|
+
background-color var(--slotted-control-transition-duration)
|
|
447
|
+
var(--slotted-control-transition-easing),
|
|
448
|
+
border-color var(--slotted-control-transition-duration)
|
|
449
|
+
var(--slotted-control-transition-easing),
|
|
450
|
+
box-shadow var(--slotted-control-transition-duration) var(--slotted-control-transition-easing),
|
|
451
|
+
scale var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='thumb'] {
|
|
455
|
+
inset-block-start: 50%;
|
|
456
|
+
inset-inline-start: calc(var(--_position, 0) * 1%);
|
|
457
|
+
margin-block-start: calc(var(--_thumb-size) / -2);
|
|
458
|
+
margin-inline-start: calc(var(--_thumb-size) / -2);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='thumb'] {
|
|
462
|
+
inset-block-end: calc(var(--_position, 0) * 1%);
|
|
463
|
+
inset-inline-start: 50%;
|
|
464
|
+
margin-block-end: calc(var(--_thumb-size) / -2);
|
|
465
|
+
margin-inline-start: calc(var(--_thumb-size) / -2);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* The control itself, invisible and unhittable. It keeps focus, the role,
|
|
470
|
+
* the value set and its place in the form; the box around it is what a
|
|
471
|
+
* reader sees, and the family's own pointer handling is what moves it.
|
|
472
|
+
*/
|
|
473
|
+
[data-ui='slider'] [data-part='input'] {
|
|
474
|
+
appearance: none;
|
|
475
|
+
block-size: 100%;
|
|
476
|
+
inline-size: 100%;
|
|
477
|
+
inset: 0;
|
|
478
|
+
margin: 0;
|
|
479
|
+
opacity: 0;
|
|
480
|
+
/* The ring is drawn by the thumb, so two rings never nest. */
|
|
481
|
+
outline: none;
|
|
482
|
+
padding: 0;
|
|
483
|
+
pointer-events: none;
|
|
484
|
+
position: absolute;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The family draws its own thumb, so the browser's is not a second one on the
|
|
489
|
+
* screen — it goes with the input's `opacity` — but it keeps the intrinsic
|
|
490
|
+
* size the browser gives it, and that size is sixteen pixels while a thumb at
|
|
491
|
+
* `dense` is thirteen. `tools/harness/audit.mjs` read the difference as
|
|
492
|
+
* content that ran out of its box on every dense stage. The native parts are
|
|
493
|
+
* withdrawn to nothing, as `text-field` withdraws the search decorations.
|
|
494
|
+
*/
|
|
495
|
+
[data-ui='slider'] [data-part='input']::-webkit-slider-thumb {
|
|
496
|
+
appearance: none;
|
|
497
|
+
block-size: 0;
|
|
498
|
+
inline-size: 0;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
[data-ui='slider'] [data-part='input']::-webkit-slider-runnable-track {
|
|
502
|
+
block-size: 0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* ── The bubble ───────────────────────────────────────────────────────
|
|
506
|
+
*
|
|
507
|
+
* The same number as the read-out, on the thumb, where a reader's eye
|
|
508
|
+
* already is during a drag. It is out of the accessibility tree: the input
|
|
509
|
+
* beneath it already announces the value, and a second copy would announce
|
|
510
|
+
* it twice.
|
|
511
|
+
*/
|
|
512
|
+
[data-ui='slider'] [data-part='bubble'] {
|
|
513
|
+
background-color: var(--slotted-slider-bubble-background, var(--slotted-surface-inverse));
|
|
514
|
+
border-radius: var(--slotted-radius-sm, 4px);
|
|
515
|
+
color: var(--slotted-slider-bubble-color, var(--slotted-text-inverse));
|
|
516
|
+
font-size: var(--slotted-font-size-xs, 0.75rem);
|
|
517
|
+
font-variant-numeric: tabular-nums;
|
|
518
|
+
inline-size: max-content;
|
|
519
|
+
line-height: var(--slotted-line-height-xs, 1.4);
|
|
520
|
+
/**
|
|
521
|
+
* A long value wraps rather than running off the end of the scale. It can
|
|
522
|
+
* still extend past the control at either bound, which is what a bubble
|
|
523
|
+
* over a thumb does; a value that is a sentence rather than a number
|
|
524
|
+
* belongs in the read-out, which is what `valueLabel="none"` is for.
|
|
525
|
+
*/
|
|
526
|
+
max-inline-size: calc(var(--_thumb-size) * 4);
|
|
527
|
+
opacity: 0;
|
|
528
|
+
padding-block: var(--slotted-space-1, 0.125rem);
|
|
529
|
+
padding-inline: var(--slotted-space-3, 0.375rem);
|
|
530
|
+
pointer-events: none;
|
|
531
|
+
position: absolute;
|
|
532
|
+
text-align: center;
|
|
533
|
+
transition: opacity var(--slotted-control-transition-duration)
|
|
534
|
+
var(--slotted-control-transition-easing);
|
|
535
|
+
unicode-bidi: plaintext;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
[data-ui='slider'][data-orientation='horizontal'] [data-part='bubble'] {
|
|
539
|
+
inset-block-end: calc(100% + var(--slotted-space-2, 0.25rem));
|
|
540
|
+
inset-inline-start: 50%;
|
|
541
|
+
translate: -50% 0;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
[data-ui='slider'][data-orientation='horizontal']:dir(rtl) [data-part='bubble'] {
|
|
545
|
+
translate: 50% 0;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* A vertical bubble stands on the inline-start side, because the marks stand
|
|
550
|
+
* on the other one. Two overlays on one edge is a scale whose labels sit
|
|
551
|
+
* under its own values.
|
|
552
|
+
*/
|
|
553
|
+
[data-ui='slider'][data-orientation='vertical'] [data-part='bubble'] {
|
|
554
|
+
inset-block-start: 50%;
|
|
555
|
+
inset-inline-end: calc(100% + var(--slotted-space-2, 0.25rem));
|
|
556
|
+
translate: 0 -50%;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* `auto` shows the number while the value is moving or while the thumb has
|
|
561
|
+
* the caret; `always` shows it at rest as well. The transition is on opacity
|
|
562
|
+
* alone, so nothing moves under a reader who asked for stillness — the
|
|
563
|
+
* duration token collapses and the bubble simply appears.
|
|
564
|
+
*/
|
|
565
|
+
[data-ui='slider'][data-value-label='always'] [data-part='bubble'],
|
|
566
|
+
[data-ui='slider'][data-dragging] [data-part='thumb'][data-active] [data-part='bubble'],
|
|
567
|
+
[data-ui='slider']
|
|
568
|
+
[data-part='thumb']:has(> [data-part='input']:focus-visible)
|
|
569
|
+
[data-part='bubble'] {
|
|
570
|
+
opacity: 1;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
[data-ui='slider'][data-value-label='none'] [data-part='bubble'] {
|
|
574
|
+
display: none;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/* ── States ───────────────────────────────────────────────────────────
|
|
578
|
+
*
|
|
579
|
+
* Written strongest last, and each weaker one guarded against the stronger
|
|
580
|
+
* ones it can meet, which is the order `STATE_PRECEDENCE` sets.
|
|
581
|
+
*/
|
|
582
|
+
|
|
583
|
+
[data-ui='slider']:not([data-disabled]):not([data-readonly])
|
|
584
|
+
[data-part='thumb']:hover:not(:disabled) {
|
|
585
|
+
background-color: var(
|
|
586
|
+
--slotted-slider-thumb-hover-background,
|
|
587
|
+
var(--slotted-tone-accent-surface)
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* The thumb grows under the press rather than only changing colour. It is
|
|
593
|
+
* the one movement in the family that carries information — the control has
|
|
594
|
+
* taken the gesture — and it collapses with the duration token under reduced
|
|
595
|
+
* motion.
|
|
596
|
+
*/
|
|
597
|
+
[data-ui='slider']:not([data-disabled]):not([data-readonly])
|
|
598
|
+
[data-part='thumb']:active:not(:disabled),
|
|
599
|
+
[data-ui='slider'][data-dragging]:not([data-disabled]):not([data-readonly])
|
|
600
|
+
[data-part='thumb'][data-active] {
|
|
601
|
+
cursor: grabbing;
|
|
602
|
+
scale: 1.15;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* The ring belongs to the thumb and answers the input's focus. The input is
|
|
607
|
+
* `opacity: 0`, so nothing else in the family could draw it.
|
|
608
|
+
*/
|
|
609
|
+
[data-ui='slider'] [data-part='thumb']:has(> [data-part='input']:focus-visible) {
|
|
610
|
+
box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
|
|
611
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
612
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
613
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Invalid outranks hover and is written after it for that reason. The ring is
|
|
618
|
+
* retargeted rather than repainted: every rule that draws focus reads
|
|
619
|
+
* `--slotted-focus-ring-color`, so pointing that one name at the invalid
|
|
620
|
+
* colour moves the outline and the shadow together.
|
|
621
|
+
*/
|
|
622
|
+
[data-ui='slider'][data-part='root'][data-invalid] {
|
|
623
|
+
--slotted-focus-ring-color: var(
|
|
624
|
+
--slotted-slider-invalid-focus-ring-color,
|
|
625
|
+
var(--slotted-focus-ring-color-invalid, Highlight)
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
[data-ui='slider'][data-invalid] [data-part='indicator'] {
|
|
630
|
+
background-color: var(
|
|
631
|
+
--slotted-slider-invalid-indicator-color,
|
|
632
|
+
var(--slotted-tone-danger-solid)
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
[data-ui='slider'][data-invalid] [data-part='thumb'] {
|
|
637
|
+
--_invalid-edge-width: var(
|
|
638
|
+
--slotted-slider-invalid-edge-width,
|
|
639
|
+
var(--slotted-control-invalid-edge-width, 1px)
|
|
640
|
+
);
|
|
641
|
+
--_invalid-edge-color: var(
|
|
642
|
+
--slotted-slider-invalid-thumb-border-color,
|
|
643
|
+
var(--slotted-tone-danger-border)
|
|
644
|
+
);
|
|
645
|
+
--_invalid-edge: inset 0 0 0 var(--_invalid-edge-width) var(--_invalid-edge-color);
|
|
646
|
+
|
|
647
|
+
border-color: var(
|
|
648
|
+
--slotted-slider-invalid-thumb-border-color,
|
|
649
|
+
var(--slotted-tone-danger-border)
|
|
650
|
+
);
|
|
651
|
+
/*
|
|
652
|
+
* Width as well as colour (WCAG 1.4.1), the edge `text-field` draws: in
|
|
653
|
+
* `high-contrast` the danger fill and border are the accent's black. The
|
|
654
|
+
* thumb carries it, as a shadow inside its border, so the thumb keeps its
|
|
655
|
+
* size and its place on the track; it takes the resting lift's place.
|
|
656
|
+
*/
|
|
657
|
+
box-shadow: var(--_invalid-edge);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
[data-ui='slider'][data-invalid] [data-part='thumb']:has(> [data-part='input']:focus-visible) {
|
|
661
|
+
box-shadow:
|
|
662
|
+
var(--_invalid-edge),
|
|
663
|
+
var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
|
|
664
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Read-only stays focusable, stays announced and stays submitted, and must
|
|
669
|
+
* not be mistakable for disabled: the ink keeps its full strength, because
|
|
670
|
+
* the value is real. What changes is the tone — the scale steps off the
|
|
671
|
+
* accent and onto a neutral ink, which says "not yours to change" without
|
|
672
|
+
* saying "not readable". A read-only slider that painted nothing at all was
|
|
673
|
+
* the first capture's defect, and it is the one `number-field` found in the
|
|
674
|
+
* same state.
|
|
675
|
+
*/
|
|
676
|
+
[data-ui='slider'][data-part='root'][data-readonly] [data-part='control'],
|
|
677
|
+
[data-ui='slider'][data-part='root'][data-readonly] [data-part='thumb'] {
|
|
678
|
+
cursor: default;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
[data-ui='slider'][data-part='root'][data-readonly] [data-part='indicator'] {
|
|
682
|
+
background-color: var(--slotted-slider-readonly-indicator-color, var(--slotted-text-muted));
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* The thumb takes the control edge rather than the muted ink. Both read-only
|
|
687
|
+
* and disabled paint a neutral scale, and in the dark scheme the two neutrals
|
|
688
|
+
* sat within a step of each other; the control edge and the disabled edge are
|
|
689
|
+
* two tokens the theme keeps apart in every scheme, which is what makes the
|
|
690
|
+
* two states tell themselves apart.
|
|
691
|
+
*/
|
|
692
|
+
[data-ui='slider'][data-part='root'][data-readonly] [data-part='thumb'] {
|
|
693
|
+
border-color: var(
|
|
694
|
+
--slotted-slider-readonly-thumb-border-color,
|
|
695
|
+
var(--slotted-control-border-color, ButtonBorder)
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* `:disabled` on an input is matched beside `data-disabled` on the root,
|
|
701
|
+
* because a control can be disabled by something that never told it so: a
|
|
702
|
+
* disabled `fieldset` disables every control inside it.
|
|
703
|
+
*/
|
|
704
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='track'],
|
|
705
|
+
[data-ui='slider'][data-part='root']:has([data-part='input']:disabled) [data-part='track'] {
|
|
706
|
+
background-color: var(
|
|
707
|
+
--slotted-slider-disabled-track-color,
|
|
708
|
+
var(--slotted-disabled-background)
|
|
709
|
+
);
|
|
710
|
+
border-color: var(--slotted-slider-disabled-border-color, var(--slotted-disabled-border));
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='indicator'],
|
|
714
|
+
[data-ui='slider'][data-part='root']:has([data-part='input']:disabled) [data-part='indicator'] {
|
|
715
|
+
background-color: var(
|
|
716
|
+
--slotted-slider-disabled-indicator-color,
|
|
717
|
+
var(--slotted-disabled-foreground)
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='thumb'],
|
|
722
|
+
[data-ui='slider'][data-part='root']:has([data-part='input']:disabled) [data-part='thumb'] {
|
|
723
|
+
background-color: var(
|
|
724
|
+
--slotted-slider-disabled-thumb-color,
|
|
725
|
+
var(--slotted-disabled-background)
|
|
726
|
+
);
|
|
727
|
+
border-color: var(--slotted-slider-disabled-border-color, var(--slotted-disabled-border));
|
|
728
|
+
/* Nothing a person cannot reach is lifted off the page. */
|
|
729
|
+
box-shadow: none;
|
|
730
|
+
cursor: not-allowed;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='control'],
|
|
734
|
+
[data-ui='slider'][data-part='root'][data-disabled] > [data-part='output'],
|
|
735
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='mark-label'] {
|
|
736
|
+
color: var(--slotted-disabled-foreground);
|
|
737
|
+
cursor: not-allowed;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='mark'] {
|
|
741
|
+
background-color: var(--slotted-disabled-foreground);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* The one block the theme cannot write for the family. Under forced colours
|
|
746
|
+
* a background is repainted by the operating system, and the channel, the
|
|
747
|
+
* fill and the thumb are three backgrounds that have to stay three different
|
|
748
|
+
* things — a fill flattened to the channel's colour would leave a slider
|
|
749
|
+
* with no value on it at all.
|
|
750
|
+
*/
|
|
751
|
+
@media (forced-colors: active) {
|
|
752
|
+
[data-ui='slider'] [data-part='track'] {
|
|
753
|
+
background-color: ButtonFace;
|
|
754
|
+
border-color: ButtonBorder;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
[data-ui='slider'] [data-part='indicator'] {
|
|
758
|
+
background-color: Highlight;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
[data-ui='slider'] [data-part='thumb'] {
|
|
762
|
+
background-color: ButtonFace;
|
|
763
|
+
border-color: ButtonBorder;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
[data-ui='slider'] [data-part='mark'] {
|
|
767
|
+
background-color: CanvasText;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='indicator'],
|
|
771
|
+
[data-ui='slider'][data-part='root'][data-disabled] [data-part='thumb'] {
|
|
772
|
+
background-color: Canvas;
|
|
773
|
+
border-color: GrayText;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/* The invalid edge is a shadow, which forced colours remove: it comes back
|
|
777
|
+
as an outline inside the thumb's border, and a focused invalid thumb
|
|
778
|
+
draws its ring double. */
|
|
779
|
+
[data-ui='slider'][data-invalid] [data-part='thumb'] {
|
|
780
|
+
outline: var(--_invalid-edge-width) solid CanvasText;
|
|
781
|
+
outline-offset: calc(
|
|
782
|
+
-1 * (var(--slotted-border-width-thick, 2px) + var(--_invalid-edge-width))
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
[data-ui='slider'][data-invalid] [data-part='thumb']:has(> [data-part='input']:focus-visible) {
|
|
787
|
+
outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
|
|
788
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
789
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|