@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,1048 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* ── A text input with a list of options filtered by what was typed ──────
|
|
4
|
+
*
|
|
5
|
+
* The family is two subtrees, as `select`'s is: the **control**, where the
|
|
6
|
+
* consumer wrote it, and the **popup**, portalled to the end of the document
|
|
7
|
+
* so it escapes every clipping ancestor between them. Nothing selects one
|
|
8
|
+
* from the other, so `data-ui='combobox'` is written on both roots — the
|
|
9
|
+
* contract records it under `portalledIdentity`.
|
|
10
|
+
*
|
|
11
|
+
* ┌─ root ─ the control ───────────────────────────────────────┐
|
|
12
|
+
* │ input ─ role="combobox" clear trigger ▸ arrow │
|
|
13
|
+
* └────────────────────────────────────────────────────────────┘
|
|
14
|
+
*
|
|
15
|
+
* ┌─ positioner ─ the layer ───────────────────────────────────┐
|
|
16
|
+
* │ ┌─ content ─ role="listbox" ─ scrolls ───────────────┐ │
|
|
17
|
+
* │ │ group ▸ group-label │ │
|
|
18
|
+
* │ │ item ▸ icon │ label ▸ match │ indicator │ │
|
|
19
|
+
* │ │ description │ │
|
|
20
|
+
* │ │ separator · empty · status │ │
|
|
21
|
+
* │ └────────────────────────────────────────────────────┘ │
|
|
22
|
+
* └────────────────────────────────────────────────────────────┘
|
|
23
|
+
*
|
|
24
|
+
* ── What this sheet does not decide ──────────────────────────────────
|
|
25
|
+
*
|
|
26
|
+
* The frame, the three columns, the subgrid, the check in the last column,
|
|
27
|
+
* the highlight on `data-current`, the two-line label clamp and the bounded
|
|
28
|
+
* scrolling surface are all `select`'s decisions, taken in the same session
|
|
29
|
+
* and written out in `packages/styles/src/select/select.css`. They are
|
|
30
|
+
* repeated here rather than shared because the two families have two public
|
|
31
|
+
* identifiers, and a stylesheet that painted `[data-ui='select']` from a
|
|
32
|
+
* combobox would make one family's selector match the other's DOM. The
|
|
33
|
+
* duplication is the price of that boundary and it is paid on purpose.
|
|
34
|
+
*
|
|
35
|
+
* ── What this sheet decides on its own ───────────────────────────────
|
|
36
|
+
*
|
|
37
|
+
* **The control holds a real `input`**, so every text-editing key, the caret,
|
|
38
|
+
* the selection, IME and autofill stay the browser's — the pattern's own
|
|
39
|
+
* IMPORTANT note asks for exactly that. The frame draws the ring from the
|
|
40
|
+
* input's `:focus-visible`, which a browser matches for a pointer press as
|
|
41
|
+
* well as for a Tab, and that is right for a control whose caret is the thing
|
|
42
|
+
* that moved.
|
|
43
|
+
*
|
|
44
|
+
* **The trigger is a button and not a tab stop.** The pattern's Keyboard
|
|
45
|
+
* Interaction note excludes the popup indicator from the page tab sequence by
|
|
46
|
+
* name, so it carries `tabindex="-1"` and the input keeps the stop.
|
|
47
|
+
*
|
|
48
|
+
* **`match` marks what the query found.** It is a `mark` element filled from
|
|
49
|
+
* `matchRanges`, so the span the filter matched is the span the reader sees
|
|
50
|
+
* tinted. No surveyed implementation draws it, and it is the only visual
|
|
51
|
+
* answer to "why is this option in my results" when the filter is fuzzy or
|
|
52
|
+
* remote.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/* ── The control ──────────────────────────────────────────────────────── */
|
|
56
|
+
|
|
57
|
+
[data-ui='combobox'][data-part='root'] {
|
|
58
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
59
|
+
--_height: var(--slotted-control-height-md, 34px);
|
|
60
|
+
--_padding-inline: var(--slotted-control-padding-inline-md, 13px);
|
|
61
|
+
--_gap: var(--slotted-control-gap-md, 8px);
|
|
62
|
+
/** The floor under the glyph scale at the dense step (SL3); a family token so a theme can retune it. */
|
|
63
|
+
--_icon-floor: var(--slotted-combobox-icon-size-min, 14px);
|
|
64
|
+
--_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-md, 16px));
|
|
65
|
+
--_inner-size: var(--slotted-control-inner-size-md, 24px);
|
|
66
|
+
|
|
67
|
+
/* `text-field`'s arithmetic, because these are the same buttons in the same
|
|
68
|
+
frame and a second answer would drift from the first. */
|
|
69
|
+
--_action-size: var(
|
|
70
|
+
--slotted-combobox-action-size,
|
|
71
|
+
min(calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)), var(--_inner-size))
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
align-items: center;
|
|
75
|
+
background-color: var(--slotted-combobox-background, var(--slotted-control-surface, Field));
|
|
76
|
+
border: var(--slotted-control-border-width, 1px) solid
|
|
77
|
+
var(--slotted-combobox-border-color, var(--slotted-control-border-color, ButtonBorder));
|
|
78
|
+
border-radius: var(--slotted-combobox-radius, var(--slotted-control-radius, 4px));
|
|
79
|
+
box-shadow: var(--slotted-combobox-shadow, var(--slotted-control-shadow, none));
|
|
80
|
+
box-sizing: border-box;
|
|
81
|
+
color: var(--slotted-combobox-color, var(--slotted-text, CanvasText));
|
|
82
|
+
display: flex;
|
|
83
|
+
font-family: var(--slotted-control-font-family, system-ui, sans-serif);
|
|
84
|
+
font-size: var(--_font-size);
|
|
85
|
+
gap: var(--slotted-space-1, 0.125rem);
|
|
86
|
+
inline-size: 100%;
|
|
87
|
+
min-inline-size: 0;
|
|
88
|
+
min-block-size: var(--_height);
|
|
89
|
+
padding-inline-start: var(--_padding-inline);
|
|
90
|
+
/* The end padding is the buttons' gutter rather than the frame's, so the
|
|
91
|
+
glyph — not the button's box — ends where the text begins on the other
|
|
92
|
+
side. `text-field` states the same arithmetic. */
|
|
93
|
+
padding-inline-end: max(
|
|
94
|
+
0px,
|
|
95
|
+
calc(var(--_padding-inline) - (var(--_action-size) - var(--_icon-size)) / 2)
|
|
96
|
+
);
|
|
97
|
+
transition:
|
|
98
|
+
background-color var(--slotted-control-transition-duration)
|
|
99
|
+
var(--slotted-control-transition-easing),
|
|
100
|
+
border-color var(--slotted-control-transition-duration)
|
|
101
|
+
var(--slotted-control-transition-easing),
|
|
102
|
+
box-shadow var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
[data-ui='combobox'][data-part='root']:not([data-full-width]) {
|
|
106
|
+
inline-size: auto;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The control. It gives up its own frame entirely and keeps everything that
|
|
111
|
+
* makes it a text control: the value, the caret, the selection and every
|
|
112
|
+
* native attribute the consumer wrote — including the completion string
|
|
113
|
+
* `autocomplete="both"` writes as a selected range rather than as text, so
|
|
114
|
+
* the next character typed replaces it.
|
|
115
|
+
*/
|
|
116
|
+
[data-ui='combobox'] > [data-part='input'] {
|
|
117
|
+
background-color: transparent;
|
|
118
|
+
/* The frame's border box, not its content box: on a coarse pointer the frame
|
|
119
|
+
is the touch target's height and the control it holds is too. Stretched
|
|
120
|
+
rather than a percentage of the frame, which is indefinite wherever the
|
|
121
|
+
frame is not stretched itself — a search field in a bar measured 17
|
|
122
|
+
pixels. The control paints no ground, so the frame's edge still shows. */
|
|
123
|
+
align-self: stretch;
|
|
124
|
+
margin-block: calc(var(--slotted-control-border-width, 1px) * -1);
|
|
125
|
+
border: 0;
|
|
126
|
+
color: inherit;
|
|
127
|
+
flex: 1 1 auto;
|
|
128
|
+
font: inherit;
|
|
129
|
+
/* The frame draws the ring for it, so two rings never nest. */
|
|
130
|
+
outline: none;
|
|
131
|
+
padding: 0;
|
|
132
|
+
/* The intrinsic width of an `input` is about twenty characters, and a flex
|
|
133
|
+
item refuses to shrink below it without this. */
|
|
134
|
+
min-inline-size: 0;
|
|
135
|
+
text-overflow: ellipsis;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[data-ui='combobox'] > [data-part='input']::placeholder {
|
|
139
|
+
color: var(--slotted-combobox-placeholder-color, var(--slotted-text-muted, GrayText));
|
|
140
|
+
text-overflow: ellipsis;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The completion string. `autocomplete="both"` writes it into the input and
|
|
145
|
+
* selects it, so the platform's own selection paint is what shows it — and
|
|
146
|
+
* the theme's accent tone is what that paint should be, rather than the
|
|
147
|
+
* browser's blue in a form that is not blue.
|
|
148
|
+
*/
|
|
149
|
+
[data-ui='combobox'] > [data-part='input']::selection {
|
|
150
|
+
background-color: var(
|
|
151
|
+
--slotted-combobox-completion-background,
|
|
152
|
+
var(--slotted-tone-accent-surface)
|
|
153
|
+
);
|
|
154
|
+
color: var(--slotted-combobox-completion-color, var(--slotted-tone-accent-text));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Autofill. Chrome paints its own ground over the control's, and a
|
|
159
|
+
* hundred-pixel inset shadow is the only way to reach it. The signal is kept
|
|
160
|
+
* rather than erased, in the accent surface the theme owns — the repair
|
|
161
|
+
* `text-field` makes, for the same reason.
|
|
162
|
+
*/
|
|
163
|
+
[data-ui='combobox'] > [data-part='input']:autofill {
|
|
164
|
+
box-shadow: inset 0 0 0 100px
|
|
165
|
+
var(--slotted-combobox-autofill-background, var(--slotted-tone-accent-surface));
|
|
166
|
+
-webkit-text-fill-color: var(--slotted-combobox-color, var(--slotted-text, CanvasText));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* ── The two buttons inside the frame ─────────────────────────────────── */
|
|
170
|
+
|
|
171
|
+
[data-ui='combobox'] > :is([data-part='clear'], [data-part='trigger']) {
|
|
172
|
+
align-items: center;
|
|
173
|
+
appearance: none;
|
|
174
|
+
background-color: transparent;
|
|
175
|
+
block-size: var(--_action-size);
|
|
176
|
+
border: 0;
|
|
177
|
+
border-radius: var(--slotted-combobox-radius, var(--slotted-control-radius, 4px));
|
|
178
|
+
color: var(--slotted-combobox-action-color, var(--slotted-text-muted, GrayText));
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
display: inline-flex;
|
|
181
|
+
flex: 0 0 auto;
|
|
182
|
+
inline-size: var(--_action-size);
|
|
183
|
+
justify-content: center;
|
|
184
|
+
/* The user agent pads a button, and inside a box sized to its glyph that
|
|
185
|
+
padding squeezed the glyph to twelve pixels. */
|
|
186
|
+
padding: 0;
|
|
187
|
+
/* The containing block of the hit area below. */
|
|
188
|
+
position: relative;
|
|
189
|
+
touch-action: manipulation;
|
|
190
|
+
transition:
|
|
191
|
+
background-color var(--slotted-control-transition-duration)
|
|
192
|
+
var(--slotted-control-transition-easing),
|
|
193
|
+
color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
|
|
194
|
+
-webkit-tap-highlight-color: transparent;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The hit area, recovered outside the paint. At `sm` with `dense` the whole
|
|
199
|
+
* control is 24 pixels tall — the WCAG 2.2 minimum — so nothing drawn inside
|
|
200
|
+
* it can also be 24.
|
|
201
|
+
*/
|
|
202
|
+
[data-ui='combobox'] > :is([data-part='clear'], [data-part='trigger'])::after {
|
|
203
|
+
content: '';
|
|
204
|
+
inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
|
|
205
|
+
position: absolute;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* On a finger the target is the comfortable size in both axes and the box
|
|
209
|
+
is the one a mouse sees: the ground and the focus ring stay square, and
|
|
210
|
+
the hit area above grows to 44 pixels around them. Side by side, neither
|
|
211
|
+
button reaches across the edge the two share. */
|
|
212
|
+
@media (pointer: coarse) {
|
|
213
|
+
[data-ui='combobox'] > :is([data-part='clear'], [data-part='trigger'])::after {
|
|
214
|
+
inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
[data-ui='combobox'] > [data-part='clear']:has(+ [data-part='trigger']:not([hidden]))::after {
|
|
218
|
+
inset-inline-end: 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
[data-ui='combobox'] > [data-part='clear']:not([hidden]) + [data-part='trigger']::after {
|
|
222
|
+
inset-inline-start: 0;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* The cross and the chevron are `Glyph` elements the binding draws, sized
|
|
227
|
+
here to the control's icon step. */
|
|
228
|
+
[data-ui='combobox'] > :is([data-part='clear'], [data-part='trigger']) {
|
|
229
|
+
--slotted-icon-size: var(--_icon-size);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* The chevron, drawn by its own part rather than by the button, because the
|
|
234
|
+
* button is what a reader presses and the arrow is what turns over. The
|
|
235
|
+
* library's own `Glyph` in an `icon` box; a character is never an icon.
|
|
236
|
+
*/
|
|
237
|
+
[data-ui='combobox'] [data-part='arrow'] {
|
|
238
|
+
align-items: center;
|
|
239
|
+
block-size: var(--_icon-size);
|
|
240
|
+
display: flex;
|
|
241
|
+
inline-size: var(--_icon-size);
|
|
242
|
+
justify-content: center;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
[data-ui='combobox'] [data-part='arrow'] > [data-ui='icon'] {
|
|
246
|
+
transition: rotate var(--slotted-control-transition-duration)
|
|
247
|
+
var(--slotted-control-transition-easing);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
[data-ui='combobox'][data-open] [data-part='arrow'] > [data-ui='icon'] {
|
|
251
|
+
rotate: 180deg;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The ring, where the chevron stands. `select`'s decision and `select`'s
|
|
256
|
+
* reasons (SL6/CB5): while an answer is travelling the control shows the
|
|
257
|
+
* ring rather than the chevron, and the arc is the one `spinner/spinner.css`
|
|
258
|
+
* draws for every family that waits, worn as `data-ui='spinner'` beside this
|
|
259
|
+
* family's own part.
|
|
260
|
+
*/
|
|
261
|
+
[data-ui='combobox'] [data-part='busy'] {
|
|
262
|
+
--slotted-spinner-size: var(--_icon-size);
|
|
263
|
+
|
|
264
|
+
color: var(--slotted-combobox-arrow-color, var(--slotted-text-muted, GrayText));
|
|
265
|
+
flex: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* ── Size ─────────────────────────────────────────────────────────────── */
|
|
269
|
+
|
|
270
|
+
[data-ui='combobox'][data-part='root'][data-size='sm'] {
|
|
271
|
+
--_font-size: var(--slotted-control-font-size-sm, 12px);
|
|
272
|
+
--_height: var(--slotted-control-height-sm, 30px);
|
|
273
|
+
--_padding-inline: var(--slotted-control-padding-inline-sm, 10px);
|
|
274
|
+
--_gap: var(--slotted-control-gap-sm, 6px);
|
|
275
|
+
--_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-sm, 14px));
|
|
276
|
+
--_inner-size: var(--slotted-control-inner-size-sm, 22px);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
[data-ui='combobox'][data-part='root'][data-size='md'] {
|
|
280
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
281
|
+
--_height: var(--slotted-control-height-md, 34px);
|
|
282
|
+
--_padding-inline: var(--slotted-control-padding-inline-md, 13px);
|
|
283
|
+
--_gap: var(--slotted-control-gap-md, 8px);
|
|
284
|
+
--_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-md, 16px));
|
|
285
|
+
--_inner-size: var(--slotted-control-inner-size-md, 24px);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
[data-ui='combobox'][data-part='root'][data-size='lg'] {
|
|
289
|
+
--_font-size: var(--slotted-control-font-size-lg, 14px);
|
|
290
|
+
--_height: var(--slotted-control-height-lg, 38px);
|
|
291
|
+
--_padding-inline: var(--slotted-control-padding-inline-lg, 16px);
|
|
292
|
+
--_gap: var(--slotted-control-gap-lg, 8px);
|
|
293
|
+
--_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-lg, 18px));
|
|
294
|
+
--_inner-size: var(--slotted-control-inner-size-lg, 28px);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* ── Variant ──────────────────────────────────────────────────────────── */
|
|
298
|
+
|
|
299
|
+
[data-ui='combobox'][data-part='root'][data-variant='subtle'] {
|
|
300
|
+
background-color: var(
|
|
301
|
+
--slotted-combobox-subtle-background,
|
|
302
|
+
var(--slotted-surface-sunken, Canvas)
|
|
303
|
+
);
|
|
304
|
+
border-color: var(
|
|
305
|
+
--slotted-combobox-subtle-border-color,
|
|
306
|
+
var(--slotted-border-subtle, ButtonBorder)
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* No edge, no lift, no ground and no corner of its own: the cell it sits in
|
|
311
|
+
is the box, the row is the ground, a cell has no corner, and the resting
|
|
312
|
+
shadow would draw the cell where there is none. */
|
|
313
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain'] {
|
|
314
|
+
background-color: transparent;
|
|
315
|
+
border-color: transparent;
|
|
316
|
+
border-radius: var(--slotted-radius-none, 0px);
|
|
317
|
+
box-shadow: none;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@media (forced-colors: active) {
|
|
321
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain'] {
|
|
322
|
+
border-color: ButtonBorder;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* ── States on the control ────────────────────────────────────────────── */
|
|
327
|
+
|
|
328
|
+
[data-ui='combobox'][data-part='root']:hover:not([data-disabled]):not([data-readonly]):not(
|
|
329
|
+
[data-invalid]
|
|
330
|
+
) {
|
|
331
|
+
border-color: var(--slotted-combobox-hover-border-color, var(--slotted-tone-accent-border));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
[data-ui='combobox'][data-part='root'][data-variant='subtle']:hover:not([data-disabled]):not(
|
|
335
|
+
[data-readonly]
|
|
336
|
+
):not([data-invalid]) {
|
|
337
|
+
background-color: var(
|
|
338
|
+
--slotted-combobox-subtle-hover-background,
|
|
339
|
+
var(--slotted-tone-secondary-subtle-hover)
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain']:hover:not([data-disabled]):not(
|
|
344
|
+
[data-readonly]
|
|
345
|
+
):not([data-invalid]) {
|
|
346
|
+
background-color: var(
|
|
347
|
+
--slotted-combobox-plain-hover-background,
|
|
348
|
+
var(--slotted-tone-secondary-subtle-hover)
|
|
349
|
+
);
|
|
350
|
+
/* The accent edge the other variants take would draw the cell's outline. */
|
|
351
|
+
border-color: transparent;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
[data-ui='combobox'][data-part='root']:has(> [data-part='input']:focus-visible) {
|
|
355
|
+
box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
|
|
356
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
357
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
358
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* The ring of a control whose box is not its own is drawn inside that box,
|
|
363
|
+
* the way the inner controls draw theirs inside the frame: two pixels past
|
|
364
|
+
* the control is two pixels over the next row's rule. No lift either — a
|
|
365
|
+
* shadow that appears only under focus is a cell that changes size when it
|
|
366
|
+
* is used.
|
|
367
|
+
*/
|
|
368
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain']:has(
|
|
369
|
+
> [data-part='input']:focus-visible
|
|
370
|
+
) {
|
|
371
|
+
box-shadow: none;
|
|
372
|
+
outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
[data-ui='combobox'][data-part='root'][data-open]:not([data-disabled]) {
|
|
376
|
+
border-color: var(--slotted-combobox-open-border-color, var(--slotted-tone-accent-border));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
[data-ui='combobox'][data-part='root'][data-invalid] {
|
|
380
|
+
--slotted-focus-ring-color: var(
|
|
381
|
+
--slotted-combobox-invalid-focus-ring-color,
|
|
382
|
+
var(--slotted-focus-ring-color-invalid, Highlight)
|
|
383
|
+
);
|
|
384
|
+
--_invalid-edge-width: var(
|
|
385
|
+
--slotted-combobox-invalid-edge-width,
|
|
386
|
+
var(--slotted-control-invalid-edge-width, 1px)
|
|
387
|
+
);
|
|
388
|
+
--_invalid-edge-color: var(
|
|
389
|
+
--slotted-combobox-invalid-border-color,
|
|
390
|
+
var(--slotted-tone-danger-border)
|
|
391
|
+
);
|
|
392
|
+
--_invalid-edge: inset 0 0 0 var(--_invalid-edge-width) var(--_invalid-edge-color);
|
|
393
|
+
|
|
394
|
+
border-color: var(--slotted-combobox-invalid-border-color, var(--slotted-tone-danger-border));
|
|
395
|
+
/*
|
|
396
|
+
* Width as well as colour (WCAG 1.4.1), the edge `text-field` draws: in
|
|
397
|
+
* `high-contrast` the danger border is the resting edge's black. The line
|
|
398
|
+
* is a shadow inside the border, so neither box nor text moves, and it
|
|
399
|
+
* takes the resting lift's place.
|
|
400
|
+
*/
|
|
401
|
+
box-shadow: var(--_invalid-edge);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
[data-ui='combobox'][data-part='root'][data-invalid]:has(> [data-part='input']:focus-visible) {
|
|
405
|
+
box-shadow:
|
|
406
|
+
var(--_invalid-edge),
|
|
407
|
+
var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
|
|
408
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain'][data-invalid]:has(
|
|
412
|
+
> [data-part='input']:focus-visible
|
|
413
|
+
) {
|
|
414
|
+
/* The ring lies inside the box here, over the border and an edge as wide as
|
|
415
|
+
it; the edge reaches past the ring. */
|
|
416
|
+
box-shadow: inset 0 0 0
|
|
417
|
+
calc(
|
|
418
|
+
var(--slotted-focus-ring-offset, 2px) - var(--slotted-control-border-width, 1px) +
|
|
419
|
+
var(--_invalid-edge-width)
|
|
420
|
+
)
|
|
421
|
+
var(--_invalid-edge-color);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/*
|
|
425
|
+
* Forced colours remove every box shadow, and the edge with them. The
|
|
426
|
+
* width comes back as an outline inside the border, and a focused invalid
|
|
427
|
+
* control draws its ring double, which a valid ring is not.
|
|
428
|
+
*/
|
|
429
|
+
@media (forced-colors: active) {
|
|
430
|
+
[data-ui='combobox'][data-part='root'][data-invalid] {
|
|
431
|
+
outline: var(--_invalid-edge-width) solid CanvasText;
|
|
432
|
+
outline-offset: calc(
|
|
433
|
+
-1 * (var(--slotted-control-border-width, 1px) + var(--_invalid-edge-width))
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
[data-ui='combobox'][data-part='root'][data-invalid]:has(> [data-part='input']:focus-visible) {
|
|
438
|
+
outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
|
|
439
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
440
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
[data-ui='combobox'][data-part='root'][data-variant='plain'][data-invalid]:has(
|
|
444
|
+
> [data-part='input']:focus-visible
|
|
445
|
+
) {
|
|
446
|
+
outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
|
|
447
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
448
|
+
outline-offset: calc(
|
|
449
|
+
-1 * (var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width))
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Read-only keeps the caret, the selection and the copy, and withholds the
|
|
456
|
+
* popup. The native `readonly` gives the first three; the second is the
|
|
457
|
+
* family's, because the pattern has no readonly for a combobox.
|
|
458
|
+
*/
|
|
459
|
+
[data-ui='combobox'][data-part='root'][data-readonly] {
|
|
460
|
+
background-color: var(
|
|
461
|
+
--slotted-combobox-readonly-background,
|
|
462
|
+
var(--slotted-tone-secondary-subtle-hover)
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
[data-ui='combobox'][data-part='root'][data-readonly] [data-part='arrow'] {
|
|
467
|
+
opacity: 0.5;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* `:disabled` on the input is matched beside `data-disabled` on the frame,
|
|
472
|
+
* because a disabled `fieldset` disables every control inside it and the
|
|
473
|
+
* control has no way to say so.
|
|
474
|
+
*/
|
|
475
|
+
[data-ui='combobox'][data-part='root'][data-disabled],
|
|
476
|
+
[data-ui='combobox'][data-part='root']:has(> [data-part='input']:disabled) {
|
|
477
|
+
background-color: var(
|
|
478
|
+
--slotted-combobox-disabled-background,
|
|
479
|
+
var(--slotted-disabled-background)
|
|
480
|
+
);
|
|
481
|
+
border-color: var(--slotted-combobox-disabled-border-color, var(--slotted-disabled-border));
|
|
482
|
+
box-shadow: none;
|
|
483
|
+
color: var(--slotted-combobox-disabled-color, var(--slotted-disabled-foreground));
|
|
484
|
+
cursor: not-allowed;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
[data-ui='combobox']
|
|
488
|
+
> :is([data-part='clear'], [data-part='trigger']):hover:not(:disabled):not([data-disabled]) {
|
|
489
|
+
background-color: var(
|
|
490
|
+
--slotted-combobox-action-hover-background,
|
|
491
|
+
var(--slotted-tone-secondary-subtle-hover)
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
[data-ui='combobox']
|
|
496
|
+
> :is([data-part='clear'], [data-part='trigger']):active:not(:disabled):not([data-disabled]) {
|
|
497
|
+
background-color: var(
|
|
498
|
+
--slotted-combobox-action-active-background,
|
|
499
|
+
var(--slotted-tone-secondary-subtle-active)
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Each button carries its own ring rather than borrowing the frame's.
|
|
505
|
+
* Tabbing from the input to the clear button has to move something visible,
|
|
506
|
+
* and a ring around the whole frame would sit still while focus moved inside
|
|
507
|
+
* it. The trigger is not in the tab sequence and takes the same rule anyway,
|
|
508
|
+
* because a script may focus it.
|
|
509
|
+
*/
|
|
510
|
+
[data-ui='combobox'] > :is([data-part='clear'], [data-part='trigger']):focus-visible {
|
|
511
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
512
|
+
outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/* ── The layer ────────────────────────────────────────────────────────── */
|
|
516
|
+
|
|
517
|
+
[data-ui='combobox'][data-part='positioner'] {
|
|
518
|
+
--_surface: var(--slotted-combobox-surface, var(--slotted-surface-raised, #ffffff));
|
|
519
|
+
--_text: var(--slotted-combobox-content-text, var(--slotted-text, #0f172a));
|
|
520
|
+
--_muted: var(--slotted-combobox-content-text-muted, var(--slotted-text-muted, #5b6b7f));
|
|
521
|
+
--_border-color: var(
|
|
522
|
+
--slotted-combobox-content-border-color,
|
|
523
|
+
var(--slotted-border-subtle, #e2e8f0)
|
|
524
|
+
);
|
|
525
|
+
--_border-width: var(--slotted-border-width-thin, 1px);
|
|
526
|
+
--_radius: var(--slotted-combobox-content-radius, var(--slotted-radius-lg, 8px));
|
|
527
|
+
--_shadow: var(--slotted-combobox-content-shadow, var(--slotted-shadow-md));
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* The stronger step of the neutral tone, for the reason
|
|
531
|
+
* `packages/styles/src/select/select.css` writes out in full: in the dark
|
|
532
|
+
* scheme `--slotted-tone-secondary-subtle-hover` is `#18181b` where the
|
|
533
|
+
* raised popup is `#1c1c20`, so the usual highlight resolves *darker* than
|
|
534
|
+
* its own ground and reads as a hole. The `-active` step is the only member
|
|
535
|
+
* of the pair that lifts in all three schemes.
|
|
536
|
+
*/
|
|
537
|
+
--_highlight: var(--slotted-combobox-highlight, var(--slotted-tone-secondary-subtle-active));
|
|
538
|
+
--_highlight-active: var(
|
|
539
|
+
--slotted-combobox-highlight-active,
|
|
540
|
+
var(--slotted-tone-accent-surface)
|
|
541
|
+
);
|
|
542
|
+
--_selected-color: var(--slotted-combobox-selected-color, var(--slotted-tone-accent-text));
|
|
543
|
+
|
|
544
|
+
--_inset-block: var(--slotted-combobox-content-padding-block, var(--slotted-space-2, 0.25rem));
|
|
545
|
+
--_inset-inline: var(
|
|
546
|
+
--slotted-combobox-content-padding-inline,
|
|
547
|
+
var(--slotted-space-2, 0.25rem)
|
|
548
|
+
);
|
|
549
|
+
--_item-inset: var(--slotted-control-padding-inline-md, 0.8125rem);
|
|
550
|
+
--_item-height: var(--slotted-control-height-md, 34px);
|
|
551
|
+
--_item-radius: var(--slotted-combobox-item-radius, var(--slotted-control-radius));
|
|
552
|
+
--_content-font-size: var(--slotted-control-font-size-md, 13px);
|
|
553
|
+
--_secondary-font-size: var(--slotted-control-font-size-sm, 12px);
|
|
554
|
+
--_content-icon-size: var(--slotted-control-icon-size-md, 16px);
|
|
555
|
+
--_column-gap: var(--slotted-control-gap-md, 0.5rem);
|
|
556
|
+
|
|
557
|
+
--_measure: var(--slotted-combobox-measure, 24rem);
|
|
558
|
+
|
|
559
|
+
/* Only the block inset: the positioner writes `left` and never `right`, and
|
|
560
|
+
`inset-inline-start` would resolve to `right` in a right-to-left document
|
|
561
|
+
and win over the measured value. */
|
|
562
|
+
position: absolute;
|
|
563
|
+
inset-block-start: 0;
|
|
564
|
+
|
|
565
|
+
z-index: calc(var(--slotted-z-index-popover, 1100) + var(--slotted-layer-depth, 0));
|
|
566
|
+
isolation: isolate;
|
|
567
|
+
|
|
568
|
+
box-sizing: border-box;
|
|
569
|
+
pointer-events: none;
|
|
570
|
+
|
|
571
|
+
opacity: 0;
|
|
572
|
+
/**
|
|
573
|
+
* R7: the layer arrives along the axis it opens on — from one space step
|
|
574
|
+
* above its place when it opens downward, from one step below when it
|
|
575
|
+
* opens upward — and never along the inline axis. A `scale` from the
|
|
576
|
+
* corner the positioner named as origin moved the far edge by four per
|
|
577
|
+
* cent of the width, which read as an entrance from the left.
|
|
578
|
+
*/
|
|
579
|
+
--_enter-distance: var(--slotted-space-2, 0.25rem);
|
|
580
|
+
translate: 0 calc(-1 * var(--_enter-distance));
|
|
581
|
+
transition:
|
|
582
|
+
opacity var(--slotted-duration-short) var(--slotted-easing-exit),
|
|
583
|
+
translate var(--slotted-duration-short) var(--slotted-easing-exit);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
[data-ui='combobox'][data-part='positioner'][data-side='top'] {
|
|
587
|
+
translate: 0 var(--_enter-distance);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/* A lateral side has no block direction to arrive from, so it only fades. */
|
|
591
|
+
[data-ui='combobox'][data-part='positioner']:is([data-side='left'], [data-side='right']) {
|
|
592
|
+
translate: 0 0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* The entrance is a keyframe animation and not a transition. A transition
|
|
597
|
+
* starts from the style the browser computed last, and the positioner
|
|
598
|
+
* writes `data-side` in the same style update as the family opens the
|
|
599
|
+
* layer, so a transition set out from the closed style of the side the
|
|
600
|
+
* layer had before it had one — the bottom's — whatever side it opens on.
|
|
601
|
+
* A keyframe states where it starts. The exit stays a transition: it
|
|
602
|
+
* leaves from wherever the layer is, on the closed rule's durations.
|
|
603
|
+
*/
|
|
604
|
+
[data-ui='combobox'][data-part='positioner'][data-open] {
|
|
605
|
+
opacity: 1;
|
|
606
|
+
translate: 0 0;
|
|
607
|
+
transition: none;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Only a layer the positioner placed arrives: it writes `data-positioned`
|
|
612
|
+
* with the side, and a layer written open in static markup — the harness,
|
|
613
|
+
* a docs snippet — is simply there, and is photographed where it stands.
|
|
614
|
+
*/
|
|
615
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned] {
|
|
616
|
+
animation: slotted-combobox-enter-down var(--slotted-duration-medium)
|
|
617
|
+
var(--slotted-easing-enter);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned][data-side='top'] {
|
|
621
|
+
animation-name: slotted-combobox-enter-up;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned]:is(
|
|
625
|
+
[data-side='left'],
|
|
626
|
+
[data-side='right']
|
|
627
|
+
) {
|
|
628
|
+
animation-name: slotted-combobox-fade;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
@keyframes slotted-combobox-enter-down {
|
|
632
|
+
from {
|
|
633
|
+
opacity: 0;
|
|
634
|
+
translate: 0 calc(-1 * var(--_enter-distance));
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
@keyframes slotted-combobox-enter-up {
|
|
639
|
+
from {
|
|
640
|
+
opacity: 0;
|
|
641
|
+
translate: 0 var(--_enter-distance);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
@keyframes slotted-combobox-fade {
|
|
646
|
+
from {
|
|
647
|
+
opacity: 0;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/* Stillness keeps the fade and drops the movement (R7). */
|
|
652
|
+
@media (prefers-reduced-motion: reduce) {
|
|
653
|
+
[data-ui='combobox'][data-part='positioner'],
|
|
654
|
+
[data-ui='combobox'][data-part='positioner'][data-side='top'],
|
|
655
|
+
[data-ui='combobox'][data-part='positioner'][data-side='left'],
|
|
656
|
+
[data-ui='combobox'][data-part='positioner'][data-side='right'] {
|
|
657
|
+
translate: 0 0;
|
|
658
|
+
transition: opacity var(--slotted-duration-short) var(--slotted-easing-exit);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned],
|
|
662
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned][data-side='top'],
|
|
663
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned][data-side='left'],
|
|
664
|
+
[data-ui='combobox'][data-part='positioner'][data-open][data-positioned][data-side='right'] {
|
|
665
|
+
animation-name: slotted-combobox-fade;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
[data-ui='combobox'][data-part='positioner'][data-detached] {
|
|
670
|
+
visibility: hidden;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
[data-ui='combobox'][data-part='positioner'][data-width='anchor'] {
|
|
674
|
+
inline-size: var(--slotted-positioner-anchor-width, auto);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
[data-ui='combobox'][data-part='positioner'][data-width='content'] {
|
|
678
|
+
inline-size: max-content;
|
|
679
|
+
max-inline-size: min(var(--_measure), var(--slotted-positioner-available-width, 100vw));
|
|
680
|
+
min-inline-size: var(--slotted-positioner-anchor-width, auto);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
[data-ui='combobox'][data-part='positioner'][data-size='sm'] {
|
|
684
|
+
--_item-inset: var(--slotted-control-padding-inline-sm, 0.625rem);
|
|
685
|
+
--_item-height: var(--slotted-control-height-sm, 30px);
|
|
686
|
+
--_content-font-size: var(--slotted-control-font-size-sm, 12px);
|
|
687
|
+
--_secondary-font-size: var(--slotted-font-size-xs, 0.75rem);
|
|
688
|
+
--_content-icon-size: var(--slotted-control-icon-size-sm, 14px);
|
|
689
|
+
--_column-gap: var(--slotted-control-gap-sm, 0.375rem);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
[data-ui='combobox'][data-part='positioner'][data-size='lg'] {
|
|
693
|
+
--_item-inset: var(--slotted-control-padding-inline-lg, 1rem);
|
|
694
|
+
--_item-height: var(--slotted-control-height-lg, 38px);
|
|
695
|
+
--_content-font-size: var(--slotted-control-font-size-lg, 14px);
|
|
696
|
+
--_secondary-font-size: var(--slotted-control-font-size-sm, 12px);
|
|
697
|
+
--_content-icon-size: var(--slotted-control-icon-size-lg, 18px);
|
|
698
|
+
--_column-gap: var(--slotted-control-gap-lg, 0.5rem);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/* ── The surface ──────────────────────────────────────────────────────── */
|
|
702
|
+
|
|
703
|
+
[data-ui='combobox'] > [data-part='content'] {
|
|
704
|
+
background: var(--_surface);
|
|
705
|
+
border: var(--_border-width) solid var(--_border-color);
|
|
706
|
+
border-radius: var(--_radius);
|
|
707
|
+
box-shadow: var(--_shadow);
|
|
708
|
+
box-sizing: border-box;
|
|
709
|
+
color: var(--_text);
|
|
710
|
+
display: grid;
|
|
711
|
+
font-family: var(--slotted-font-family-sans);
|
|
712
|
+
font-size: var(--_content-font-size);
|
|
713
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
714
|
+
max-block-size: calc(
|
|
715
|
+
var(--slotted-positioner-available-height, 100vh) - var(--slotted-space-5, 0.75rem)
|
|
716
|
+
);
|
|
717
|
+
outline: none;
|
|
718
|
+
overflow-y: auto;
|
|
719
|
+
overscroll-behavior: contain;
|
|
720
|
+
padding-block: var(--_inset-block);
|
|
721
|
+
padding-inline: var(--_inset-inline);
|
|
722
|
+
pointer-events: auto;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
[data-ui='combobox'] > [data-part='content']:focus-visible {
|
|
726
|
+
outline: none;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/* ── Groups ───────────────────────────────────────────────────────────── */
|
|
730
|
+
|
|
731
|
+
[data-ui='combobox'] [data-part='group'] {
|
|
732
|
+
display: grid;
|
|
733
|
+
grid-column: 1 / -1;
|
|
734
|
+
grid-template-columns: subgrid;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
[data-ui='combobox'] [data-part='group-label'] {
|
|
738
|
+
color: var(--_muted);
|
|
739
|
+
font-size: var(--_secondary-font-size);
|
|
740
|
+
font-weight: var(--slotted-font-weight-semibold, 600);
|
|
741
|
+
grid-column: 1 / -1;
|
|
742
|
+
line-height: var(--slotted-line-height-sm, 1.45);
|
|
743
|
+
padding-block: var(--slotted-space-2, 0.25rem);
|
|
744
|
+
padding-inline: var(--_item-inset);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/* ── Options ──────────────────────────────────────────────────────────── */
|
|
748
|
+
|
|
749
|
+
[data-ui='combobox'] [data-part='item'] {
|
|
750
|
+
align-content: center;
|
|
751
|
+
border-radius: var(--_item-radius);
|
|
752
|
+
box-sizing: border-box;
|
|
753
|
+
/**
|
|
754
|
+
* The hand (CB12). A row that commits a value and closes the surface is a
|
|
755
|
+
* press, and this popup is not a platform menu: `select` draws the same
|
|
756
|
+
* cursor on the same row, and the pair says one thing about one gesture.
|
|
757
|
+
*/
|
|
758
|
+
cursor: pointer;
|
|
759
|
+
display: grid;
|
|
760
|
+
grid-column: 1 / -1;
|
|
761
|
+
grid-template-columns: subgrid;
|
|
762
|
+
line-height: var(--slotted-line-height-md, 1.5);
|
|
763
|
+
min-block-size: var(--_item-height);
|
|
764
|
+
padding-block: var(--slotted-space-2, 0.25rem);
|
|
765
|
+
padding-inline: var(--_item-inset);
|
|
766
|
+
row-gap: var(--slotted-space-1, 0.125rem);
|
|
767
|
+
user-select: none;
|
|
768
|
+
transition:
|
|
769
|
+
background-color var(--slotted-control-transition-duration, var(--slotted-duration-short))
|
|
770
|
+
var(--slotted-control-transition-easing, var(--slotted-easing-standard)),
|
|
771
|
+
color var(--slotted-control-transition-duration, var(--slotted-duration-short))
|
|
772
|
+
var(--slotted-control-transition-easing, var(--slotted-easing-standard));
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
[data-ui='combobox'] [data-part='item'][data-current] {
|
|
776
|
+
background-color: var(--_highlight);
|
|
777
|
+
/**
|
|
778
|
+
* A ring as well as a ground. Nothing on this surface holds focus — DOM
|
|
779
|
+
* focus is on the input for the whole interaction — so there is no focus
|
|
780
|
+
* ring anywhere to say where the reader is, and the APG's own select-only
|
|
781
|
+
* example marks its current option with an outline for that reason. An
|
|
782
|
+
* inset shadow rather than an outline, so it follows the option's own
|
|
783
|
+
* radius and never overflows the surface's rounded edge.
|
|
784
|
+
*/
|
|
785
|
+
box-shadow: inset 0 0 0 var(--slotted-border-width-thin, 1px)
|
|
786
|
+
var(--slotted-combobox-highlight-ring, var(--slotted-tone-accent-border));
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
[data-ui='combobox'] [data-part='item']:not([data-disabled]):active {
|
|
790
|
+
background-color: var(--_highlight-active);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
[data-ui='combobox'] [data-part='item'][data-selected] {
|
|
794
|
+
color: var(--_selected-color);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Two chosen neighbours are one block (LB2). Every item keeps its own
|
|
799
|
+
* radius, so two selected siblings painted with the same ground met at a
|
|
800
|
+
* waist — four rounded corners inside the block — and a multiple selection
|
|
801
|
+
* read as a column of separate chips. The second gives up its top corners
|
|
802
|
+
* and the first its bottom ones, so the block is rounded only where the
|
|
803
|
+
* selection begins and ends. `select` and `combobox` draw the same ground
|
|
804
|
+
* and answer the same way; `selection-block.test.mjs` holds the three to it.
|
|
805
|
+
*/
|
|
806
|
+
[data-ui='combobox'] [data-part='item'][data-selected] + [data-part='item'][data-selected] {
|
|
807
|
+
border-start-end-radius: 0;
|
|
808
|
+
border-start-start-radius: 0;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
[data-ui='combobox'] [data-part='item'][data-selected]:has(+ [data-part='item'][data-selected]) {
|
|
812
|
+
border-end-end-radius: 0;
|
|
813
|
+
border-end-start-radius: 0;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
[data-ui='combobox'] [data-part='item'][data-selected] > [data-part='label'] {
|
|
817
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
[data-ui='combobox'] [data-part='item'][data-disabled] {
|
|
821
|
+
color: var(--slotted-disabled-foreground, #64748b);
|
|
822
|
+
cursor: not-allowed;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* The highlight can land on an option nobody can choose, because a disabled
|
|
827
|
+
* option keeps its place in the collection and the pattern requires it to be
|
|
828
|
+
* announced. It must not wear the accent cursor while it is there: an accent
|
|
829
|
+
* ring on a row that answers nothing says "act here" to the one reader who
|
|
830
|
+
* cannot. The ground and the ring both step down to the theme's disabled
|
|
831
|
+
* pair, and the row stays legible rather than being faded toward it.
|
|
832
|
+
*/
|
|
833
|
+
/**
|
|
834
|
+
* The highlight can land on an option nobody can choose, because a disabled
|
|
835
|
+
* option keeps its place in the collection and the pattern requires it to be
|
|
836
|
+
* announced.
|
|
837
|
+
*
|
|
838
|
+
* **The ground stays the highlight's.** Painting the theme's disabled surface
|
|
839
|
+
* here was the first answer and it was wrong in the dark scheme, for the same
|
|
840
|
+
* reason the highlight itself was: `--slotted-disabled-background` is
|
|
841
|
+
* `#18181b` where the raised popup is `#1c1c20`, so the cursor *sank* on a
|
|
842
|
+
* disabled row and rose on every other one — a reader arrowing down the list
|
|
843
|
+
* would watch it disappear. A cursor lifts, always. What the row cannot do is
|
|
844
|
+
* said by the ink and by the ring, which both step down to the disabled pair.
|
|
845
|
+
*/
|
|
846
|
+
[data-ui='combobox'] [data-part='item'][data-disabled][data-current] {
|
|
847
|
+
box-shadow: inset 0 0 0 var(--slotted-border-width-thin, 1px)
|
|
848
|
+
var(--slotted-disabled-border, #cbd5e1);
|
|
849
|
+
color: var(--slotted-disabled-foreground, #64748b);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/* ── The cells ────────────────────────────────────────────────────────── */
|
|
853
|
+
|
|
854
|
+
[data-ui='combobox'] :is([data-part='indicator'], [data-part='icon']) {
|
|
855
|
+
block-size: 1lh;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* Column one holds content and paints none: a `Glyph` in an `Icon` box, or
|
|
859
|
+
artwork of the consumer's own, centred and sized from the column. */
|
|
860
|
+
[data-ui='combobox'] [data-part='icon'] {
|
|
861
|
+
--slotted-icon-size: var(--_content-icon-size);
|
|
862
|
+
|
|
863
|
+
align-items: center;
|
|
864
|
+
display: flex;
|
|
865
|
+
grid-column: 1;
|
|
866
|
+
grid-row: 1;
|
|
867
|
+
inline-size: var(--_content-icon-size);
|
|
868
|
+
justify-content: center;
|
|
869
|
+
justify-self: center;
|
|
870
|
+
margin-inline-end: var(--_column-gap);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
[data-ui='combobox'] [data-part='label'] {
|
|
874
|
+
grid-column: 2;
|
|
875
|
+
grid-row: 1;
|
|
876
|
+
min-inline-size: 0;
|
|
877
|
+
display: -webkit-box;
|
|
878
|
+
-webkit-box-orient: vertical;
|
|
879
|
+
-webkit-line-clamp: 2;
|
|
880
|
+
overflow: hidden;
|
|
881
|
+
overflow-wrap: anywhere;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* The span the query matched is not painted here. It is the shared mark of
|
|
886
|
+
* R6 — `highlight/highlight.css`, `data-ui='highlight'` worn beside this
|
|
887
|
+
* family's `match` part — because every list a reader types into says the
|
|
888
|
+
* same thing about the same span, and `select` with a filter, `listbox` with
|
|
889
|
+
* a filter and `menu` with a search would otherwise each have answered it
|
|
890
|
+
* again. The contract names the sheet under `mark`.
|
|
891
|
+
*
|
|
892
|
+
* What lived here also changed the metric of the word: 600 weight and 0.1em
|
|
893
|
+
* of inline padding made `Blueberry` 6.86px wider marked than plain, and the
|
|
894
|
+
* run moved on every keystroke as the filter re-marked the label (CB6).
|
|
895
|
+
*/
|
|
896
|
+
|
|
897
|
+
[data-ui='combobox'] [data-part='description'] {
|
|
898
|
+
color: var(--_muted);
|
|
899
|
+
font-size: var(--_secondary-font-size);
|
|
900
|
+
grid-column: 2;
|
|
901
|
+
grid-row: 2;
|
|
902
|
+
line-height: var(--slotted-line-height-sm, 1.45);
|
|
903
|
+
min-inline-size: 0;
|
|
904
|
+
overflow-wrap: anywhere;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
[data-ui='combobox'] [data-part='item'][data-disabled] > [data-part='description'] {
|
|
908
|
+
color: inherit;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/* The tick is a `Glyph` the binding draws, at the content's icon step. */
|
|
912
|
+
[data-ui='combobox'] [data-part='indicator'] {
|
|
913
|
+
--slotted-icon-size: var(--_content-icon-size);
|
|
914
|
+
|
|
915
|
+
align-items: center;
|
|
916
|
+
display: flex;
|
|
917
|
+
grid-column: 3;
|
|
918
|
+
grid-row: 1;
|
|
919
|
+
inline-size: var(--_content-icon-size);
|
|
920
|
+
justify-content: center;
|
|
921
|
+
justify-self: end;
|
|
922
|
+
margin-inline-start: var(--_column-gap);
|
|
923
|
+
opacity: 0;
|
|
924
|
+
transition: opacity var(--slotted-duration-short) var(--slotted-easing-standard);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
[data-ui='combobox'] [data-part='item'][data-selected] > [data-part='indicator'] {
|
|
928
|
+
opacity: 1;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/* ── Separator, empty, status ─────────────────────────────────────────── */
|
|
932
|
+
|
|
933
|
+
[data-ui='combobox'] [data-part='separator'] {
|
|
934
|
+
background-color: var(--slotted-combobox-separator-color, var(--_border-color));
|
|
935
|
+
block-size: var(--_border-width);
|
|
936
|
+
border: 0;
|
|
937
|
+
grid-column: 1 / -1;
|
|
938
|
+
margin-block: var(--slotted-space-2, 0.25rem);
|
|
939
|
+
margin-inline: 0;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* A query with no answers, and a query whose answer is still travelling.
|
|
944
|
+
* Both keep the surface's measure rather than collapsing, so nothing jumps
|
|
945
|
+
* when the results land — which is the gap none of the surveyed
|
|
946
|
+
* implementations closes.
|
|
947
|
+
*/
|
|
948
|
+
[data-ui='combobox'] :is([data-part='empty'], [data-part='status']) {
|
|
949
|
+
color: var(--_muted);
|
|
950
|
+
/**
|
|
951
|
+
* Its own bidi run, ordered by its own content. "3 results" is a European
|
|
952
|
+
* number, a neutral space and a Latin word, so in a right-to-left document
|
|
953
|
+
* the space resolves to the paragraph and the two runs swap: the first
|
|
954
|
+
* right-to-left capture of this family printed "results 3". `plaintext`
|
|
955
|
+
* takes the direction from the sentence's own first strong character, so an
|
|
956
|
+
* English count reads as itself and a translated one reads as itself — the
|
|
957
|
+
* same repair `text-field` makes for an adornment, and for the same reason.
|
|
958
|
+
* These two parts are centred, so taking their own direction costs no
|
|
959
|
+
* alignment; an option's label is the consumer's content and keeps the
|
|
960
|
+
* document's direction unless the consumer says otherwise.
|
|
961
|
+
*/
|
|
962
|
+
unicode-bidi: plaintext;
|
|
963
|
+
grid-column: 1 / -1;
|
|
964
|
+
/**
|
|
965
|
+
* Wide enough that a one-word message does not draw a popup narrower than a
|
|
966
|
+
* word, and never wider than the popup it is in: at `width="anchor"` the
|
|
967
|
+
* surface is exactly the control's width, and a bare `12rem` on a child
|
|
968
|
+
* overflows the grid the moment the control is narrower than that.
|
|
969
|
+
*/
|
|
970
|
+
min-inline-size: min(12rem, 100%);
|
|
971
|
+
padding-block: var(--slotted-space-5, 0.75rem);
|
|
972
|
+
padding-inline: var(--_item-inset);
|
|
973
|
+
text-align: center;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* The status row is also the live region that announces the count, so it is
|
|
978
|
+
* often present with nothing to draw. A row with no text takes no space, and
|
|
979
|
+
* a row with text takes the same space as the empty message beside it.
|
|
980
|
+
*/
|
|
981
|
+
[data-ui='combobox'] [data-part='status']:empty {
|
|
982
|
+
display: none;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* The wait, as the shape of the list that is coming. `select`'s decision and
|
|
987
|
+
* `select`'s reasons (SL6/CB5): three rows the height of an option rather
|
|
988
|
+
* than one sentence, so the surface a reader is looking at while the answer
|
|
989
|
+
* travels is the surface they will go on looking at. The bars are
|
|
990
|
+
* `skeleton/skeleton.css`'s — the family places them and states nothing
|
|
991
|
+
* about how a placeholder is painted — and they are hidden from assistive
|
|
992
|
+
* technology, because the `status` row beside them is the live region.
|
|
993
|
+
*/
|
|
994
|
+
[data-ui='combobox'] [data-part='placeholder'] {
|
|
995
|
+
display: grid;
|
|
996
|
+
/* The surface is a grid of option columns; the rows span all of them, as
|
|
997
|
+
the status and empty rows do. */
|
|
998
|
+
grid-column: 1 / -1;
|
|
999
|
+
padding-block: var(--slotted-space-2, 0.25rem);
|
|
1000
|
+
padding-inline: var(--_item-inset);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
[data-ui='combobox'] [data-part='placeholder'] > * {
|
|
1004
|
+
align-items: center;
|
|
1005
|
+
display: flex;
|
|
1006
|
+
min-block-size: var(--_item-height);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
[data-ui='combobox'] [data-part='placeholder'] > [data-ui='skeleton'] {
|
|
1010
|
+
align-self: center;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/* Three ragged widths: three identical bars read as a table, and a list of
|
|
1014
|
+
labels is ragged. */
|
|
1015
|
+
[data-ui='combobox'] [data-part='placeholder'] > :nth-child(2) [data-ui='skeleton'] {
|
|
1016
|
+
inline-size: 78%;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
[data-ui='combobox'] [data-part='placeholder'] > :nth-child(3) [data-ui='skeleton'] {
|
|
1020
|
+
inline-size: 56%;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* The status row while an answer is travelling. It no longer draws a pulsing
|
|
1025
|
+
* dot of its own: the control carries the ring and the popup carries the
|
|
1026
|
+
* three bars, and a third repeating motion beside them was one answer too
|
|
1027
|
+
* many for one wait (SL6/CB5).
|
|
1028
|
+
*/
|
|
1029
|
+
|
|
1030
|
+
[data-ui='combobox'] > [data-part='content'][data-loading] {
|
|
1031
|
+
cursor: progress;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/* ── Forced colours ───────────────────────────────────────────────────── */
|
|
1035
|
+
|
|
1036
|
+
@media (forced-colors: active) {
|
|
1037
|
+
[data-ui='combobox'] [data-part='item'][data-current] {
|
|
1038
|
+
background-color: Highlight;
|
|
1039
|
+
color: HighlightText;
|
|
1040
|
+
forced-color-adjust: none;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
[data-ui='combobox'] [data-part='item'][data-disabled][data-current] {
|
|
1044
|
+
background-color: Highlight;
|
|
1045
|
+
color: GrayText;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|