@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,937 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* ── The row ────────────────────────────────────────────────────────────
|
|
4
|
+
*
|
|
5
|
+
* One entry of a `list`. The set decides four things — variant, size, marker
|
|
6
|
+
* and inset — and hands each one down through the binding as a `data-`
|
|
7
|
+
* attribute this sheet reads. **No selector here reaches `[data-ui='list']`,
|
|
8
|
+
* and none there reaches this family**, which is the rule `accordion` and
|
|
9
|
+
* `collapsible` set for the same relationship.
|
|
10
|
+
*
|
|
11
|
+
* **The root is never the interactive element.** `content` is: a `div` for a
|
|
12
|
+
* row that is read, a `button` for a row that is one command, an `a` for a
|
|
13
|
+
* row that is one destination. `actions` is `content`'s sibling and never its
|
|
14
|
+
* child, because interactive content may not nest inside `a` or `button` —
|
|
15
|
+
* the decision `tag` took for `remove`, taken once here for every row.
|
|
16
|
+
*
|
|
17
|
+
* The row draws its own marker. CSS has no `display` that is both
|
|
18
|
+
* `list-item` and a grid, so a row carrying a trailing control has already
|
|
19
|
+
* lost the native `::marker`; `list` writes `role="list"` for that reason and
|
|
20
|
+
* the mark becomes geometry from the glyph scale.
|
|
21
|
+
*
|
|
22
|
+
* **Every part is reached with child combinators**, along the anatomy's own
|
|
23
|
+
* chain: `root > content > start | body | end`, `body > label | description`,
|
|
24
|
+
* and `root > actions`. A row holds other families, and they reuse these
|
|
25
|
+
* names — a `tag` in `end` has a `body` and a `label` of its own. Reached by a
|
|
26
|
+
* descendant selector, the tag's body became a column with its text on the
|
|
27
|
+
* top edge and its label took the row's line height and weight. Angular puts
|
|
28
|
+
* each part on the element the page wrote and React renders it as that
|
|
29
|
+
* element, so the chain in the selectors is the chain in the document.
|
|
30
|
+
*/
|
|
31
|
+
[data-ui='list-item'][data-part='root'] {
|
|
32
|
+
/* Geometry. Every value is the control scale's, because a row is a
|
|
33
|
+
control-sized thing: one theme decision retunes the rows, the buttons and
|
|
34
|
+
the fields together, and `@media (pointer: coarse)` grows all three at
|
|
35
|
+
once without this family writing a rule. */
|
|
36
|
+
--_min-block: var(--slotted-list-item-min-block-size, var(--slotted-control-height-md, 34px));
|
|
37
|
+
--_font-size: var(--slotted-list-item-font-size, var(--slotted-control-font-size-md, 13px));
|
|
38
|
+
--_icon-size: var(--slotted-list-item-icon-size, var(--slotted-control-icon-size-md, 16px));
|
|
39
|
+
/* The chooser's square, when the leading column holds one: the selection
|
|
40
|
+
scale `checkbox` draws in, which density does not move. */
|
|
41
|
+
--_control-size: var(--slotted-list-item-control-size, var(--slotted-selection-size-md, 16px));
|
|
42
|
+
--_gap: var(--slotted-list-item-gap, var(--slotted-control-gap-md, 8px));
|
|
43
|
+
--_pad-inline: var(
|
|
44
|
+
--slotted-list-item-padding-inline,
|
|
45
|
+
var(--slotted-control-padding-inline-md, 13px)
|
|
46
|
+
);
|
|
47
|
+
/**
|
|
48
|
+
* The block inset is what is left of the control height around one line
|
|
49
|
+
* of the title, so a one-line row is exactly the control height at every
|
|
50
|
+
* density — 34, 28 and 26 pixels at `md` — and a row of two lines grows by
|
|
51
|
+
* its second line and nothing else (LI3). Stated as a step of the space
|
|
52
|
+
* scale it was eight pixels at every density, and the row stood at 34px in
|
|
53
|
+
* `dense` as in `comfortable`: the one control on the page that density
|
|
54
|
+
* did not move. A floor of one space step keeps a row whose text is taller
|
|
55
|
+
* than its control from losing its inset.
|
|
56
|
+
*/
|
|
57
|
+
--_pad-block: var(
|
|
58
|
+
--slotted-list-item-padding-block,
|
|
59
|
+
max(
|
|
60
|
+
var(--slotted-space-2, 0.25rem),
|
|
61
|
+
calc((var(--_min-block) - var(--_font-size) * var(--slotted-line-height-md, 1.5)) / 2)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
--_radius: var(--slotted-list-item-radius, var(--slotted-radius-md, 6px));
|
|
65
|
+
|
|
66
|
+
/* Ink. `secondary` is the library's neutral, and a neutral row takes the
|
|
67
|
+
page's own text colour rather than the tone's: `--slotted-tone-secondary-text`
|
|
68
|
+
is calibrated on a chip, and a list of forty rows set in it reads as forty
|
|
69
|
+
pieces of metadata. The other four tones do take their own. */
|
|
70
|
+
--_text: var(--slotted-list-item-color, var(--slotted-text, CanvasText));
|
|
71
|
+
--_muted: var(--slotted-list-item-color-muted, var(--slotted-text-muted, GrayText));
|
|
72
|
+
/* The tone's four steps, named once so a state rule moves between them
|
|
73
|
+
instead of restating five tones. */
|
|
74
|
+
--_subtle-hover: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
|
|
75
|
+
--_subtle-active: var(--slotted-tone-secondary-subtle-active, ButtonFace);
|
|
76
|
+
--_solid-hover: var(--slotted-tone-secondary-solid-hover, ButtonFace);
|
|
77
|
+
--_solid-active: var(--slotted-tone-secondary-solid-active, ButtonFace);
|
|
78
|
+
--_surface: var(--slotted-tone-secondary-surface, Canvas);
|
|
79
|
+
--_hover: var(--slotted-list-item-background-hover, var(--_subtle-hover));
|
|
80
|
+
--_active: var(--slotted-list-item-background-active, var(--_subtle-active));
|
|
81
|
+
/* A selected row is the accent ground with the accent ink, and the edge it
|
|
82
|
+
carries is a one-pixel ring in the accent border. Every tone surface is
|
|
83
|
+
white in the `high-contrast` scheme, so a selection said with a fill
|
|
84
|
+
alone is a selection that scheme cannot show — the defect the first
|
|
85
|
+
high-contrast capture found. `tag` reached for the same answer for the
|
|
86
|
+
same reason. The pointer states of a selected row are the accent pair's
|
|
87
|
+
own steps, so hovering a selected row never lands on the surface an
|
|
88
|
+
unselected hovered row has (R1). */
|
|
89
|
+
--_selected-edge: var(--slotted-tone-accent-border, ButtonBorder);
|
|
90
|
+
--_selected-surface: var(
|
|
91
|
+
--slotted-list-item-background-selected,
|
|
92
|
+
var(--slotted-tone-accent-surface, Canvas)
|
|
93
|
+
);
|
|
94
|
+
--_selected-text: var(--slotted-tone-accent-text, CanvasText);
|
|
95
|
+
--_selected-hover: var(--slotted-tone-accent-subtle-hover, ButtonFace);
|
|
96
|
+
--_selected-active: var(--slotted-tone-accent-subtle-active, ButtonFace);
|
|
97
|
+
/* A current row is the neutral ground with a one-pixel ring in the neutral
|
|
98
|
+
border, whatever the row's tone: it is where the reader is, not what
|
|
99
|
+
they chose, and it stays out of the tone's way so a row can be both at
|
|
100
|
+
once with the selection winning (R1). */
|
|
101
|
+
--_current-surface: var(
|
|
102
|
+
--slotted-list-item-background-current,
|
|
103
|
+
var(--slotted-tone-secondary-surface, Canvas)
|
|
104
|
+
);
|
|
105
|
+
--_current-edge: var(--slotted-tone-secondary-border, ButtonBorder);
|
|
106
|
+
--_rule: var(--slotted-list-item-border-color, var(--slotted-border-subtle, ButtonBorder));
|
|
107
|
+
--_rule-width: var(--slotted-list-item-border-width, var(--slotted-border-width-thin, 1px));
|
|
108
|
+
--_marker-size: calc(var(--_icon-size) * 0.75);
|
|
109
|
+
|
|
110
|
+
/* The row counts itself, whatever the marker is. Incrementing only under
|
|
111
|
+
`number` would restart the count the moment an application retuned the
|
|
112
|
+
axis, and the counter costs nothing when nothing reads it. */
|
|
113
|
+
box-sizing: border-box;
|
|
114
|
+
/**
|
|
115
|
+
* What the row is painted with, and it is the row that is painted rather
|
|
116
|
+
* than the box inside it. Read on `content`, a selected row with a trailing
|
|
117
|
+
* control showed a filled box that stopped in the middle of the row and a
|
|
118
|
+
* seam where `actions` began — half a row highlighted. The row is what is
|
|
119
|
+
* selected, hovered and pressed; `content` is only where the pointer lands.
|
|
120
|
+
*/
|
|
121
|
+
--_fill: transparent;
|
|
122
|
+
/* Two shadows on one element: the rule above the row, and the edge a
|
|
123
|
+
selected row carries. Named separately so a selected ruled row keeps
|
|
124
|
+
both, which one `box-shadow` declaration overwriting another would not. */
|
|
125
|
+
--_rule-shadow: 0 0 0 0 transparent;
|
|
126
|
+
--_edge-shadow: 0 0 0 0 transparent;
|
|
127
|
+
|
|
128
|
+
background-color: var(--_fill);
|
|
129
|
+
border-radius: var(--_radius);
|
|
130
|
+
box-shadow: var(--_rule-shadow), var(--_edge-shadow);
|
|
131
|
+
counter-increment: slotted-list-item;
|
|
132
|
+
/* The fill and both shadows are one state change and move together. */
|
|
133
|
+
transition:
|
|
134
|
+
background-color var(--slotted-control-transition-duration, var(--slotted-duration-short))
|
|
135
|
+
var(--slotted-control-transition-easing, var(--slotted-easing-standard)),
|
|
136
|
+
box-shadow var(--slotted-control-transition-duration, var(--slotted-duration-short))
|
|
137
|
+
var(--slotted-control-transition-easing, var(--slotted-easing-standard));
|
|
138
|
+
/* The row answers its own inline size. The set does not: it has no layout
|
|
139
|
+
that depends on its width, and a container on both would make the row
|
|
140
|
+
query the set instead of the page. */
|
|
141
|
+
container-name: slotted-list-item;
|
|
142
|
+
container-type: inline-size;
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: stretch;
|
|
145
|
+
/* The row wraps, and only the container query ever makes it: `actions` is
|
|
146
|
+
given its own line below the breakpoint. Left on one line, a target
|
|
147
|
+
carrying a word rather than a glyph starved the box beside it — the
|
|
148
|
+
content shrank to eighty pixels and a one-word timestamp spilled out of
|
|
149
|
+
the column it was in. */
|
|
150
|
+
flex-wrap: wrap;
|
|
151
|
+
list-style: none;
|
|
152
|
+
min-inline-size: 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Size is the set's step, handed down. Density is the application's, and it
|
|
157
|
+
* arrives inside every control token above; the two never multiply, because
|
|
158
|
+
* this family reads the density-varying token and states no second scale.
|
|
159
|
+
*/
|
|
160
|
+
[data-ui='list-item'][data-size='sm'] {
|
|
161
|
+
--_min-block: var(
|
|
162
|
+
--slotted-list-item-min-block-size-sm,
|
|
163
|
+
var(--slotted-control-height-sm, 30px)
|
|
164
|
+
);
|
|
165
|
+
--_font-size: var(--slotted-list-item-font-size-sm, var(--slotted-control-font-size-sm, 12px));
|
|
166
|
+
--_icon-size: var(--slotted-list-item-icon-size-sm, var(--slotted-control-icon-size-sm, 14px));
|
|
167
|
+
--_control-size: var(
|
|
168
|
+
--slotted-list-item-control-size-sm,
|
|
169
|
+
var(--slotted-selection-size-sm, 14px)
|
|
170
|
+
);
|
|
171
|
+
--_gap: var(--slotted-list-item-gap-sm, var(--slotted-control-gap-sm, 6px));
|
|
172
|
+
--_pad-inline: var(
|
|
173
|
+
--slotted-list-item-padding-inline-sm,
|
|
174
|
+
var(--slotted-control-padding-inline-sm, 10px)
|
|
175
|
+
);
|
|
176
|
+
--_pad-block: var(
|
|
177
|
+
--slotted-list-item-padding-block-sm,
|
|
178
|
+
max(
|
|
179
|
+
var(--slotted-space-2, 0.25rem),
|
|
180
|
+
calc((var(--_min-block) - var(--_font-size) * var(--slotted-line-height-md, 1.5)) / 2)
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
[data-ui='list-item'][data-size='lg'] {
|
|
186
|
+
--_min-block: var(
|
|
187
|
+
--slotted-list-item-min-block-size-lg,
|
|
188
|
+
var(--slotted-control-height-lg, 38px)
|
|
189
|
+
);
|
|
190
|
+
--_font-size: var(--slotted-list-item-font-size-lg, var(--slotted-control-font-size-lg, 14px));
|
|
191
|
+
--_icon-size: var(--slotted-list-item-icon-size-lg, var(--slotted-control-icon-size-lg, 18px));
|
|
192
|
+
--_control-size: var(
|
|
193
|
+
--slotted-list-item-control-size-lg,
|
|
194
|
+
var(--slotted-selection-size-lg, 18px)
|
|
195
|
+
);
|
|
196
|
+
--_gap: var(--slotted-list-item-gap-lg, var(--slotted-control-gap-lg, 8px));
|
|
197
|
+
--_pad-inline: var(
|
|
198
|
+
--slotted-list-item-padding-inline-lg,
|
|
199
|
+
var(--slotted-control-padding-inline-lg, 16px)
|
|
200
|
+
);
|
|
201
|
+
--_pad-block: var(
|
|
202
|
+
--slotted-list-item-padding-block-lg,
|
|
203
|
+
max(
|
|
204
|
+
var(--slotted-space-2, 0.25rem),
|
|
205
|
+
calc((var(--_min-block) - var(--_font-size) * var(--slotted-line-height-md, 1.5)) / 2)
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* ── Tone ───────────────────────────────────────────────────────────────
|
|
212
|
+
*
|
|
213
|
+
* Primer ships one of these — `danger`, for a destructive row — and hides the
|
|
214
|
+
* rest behind a boolean. The theme here carries all five with the same nine
|
|
215
|
+
* roles, so shipping one of a scale and calling the other four out of scope
|
|
216
|
+
* would be the invention rather than the restraint.
|
|
217
|
+
*
|
|
218
|
+
* A tone moves three things and no more: the ink of the title and the mark,
|
|
219
|
+
* the wash under the pointer, and the ground and ink of a selected row. It
|
|
220
|
+
* never fills a resting row, because a list of rows each filled with a tone
|
|
221
|
+
* is a list nobody can read. The current row is not the tone's to move.
|
|
222
|
+
*/
|
|
223
|
+
[data-ui='list-item'][data-tone='accent'] {
|
|
224
|
+
--_text: var(--slotted-tone-accent-text, CanvasText);
|
|
225
|
+
--_subtle-hover: var(--slotted-tone-accent-subtle-hover, ButtonFace);
|
|
226
|
+
--_subtle-active: var(--slotted-tone-accent-subtle-active, ButtonFace);
|
|
227
|
+
--_solid-hover: var(--slotted-tone-accent-solid-hover, ButtonFace);
|
|
228
|
+
--_solid-active: var(--slotted-tone-accent-solid-active, ButtonFace);
|
|
229
|
+
--_surface: var(--slotted-tone-accent-surface, Canvas);
|
|
230
|
+
--_selected-edge: var(--slotted-tone-accent-border, ButtonBorder);
|
|
231
|
+
--_selected-surface: var(--slotted-list-item-background-selected, var(--_surface));
|
|
232
|
+
--_selected-text: var(--slotted-tone-accent-text, CanvasText);
|
|
233
|
+
--_selected-hover: var(--_subtle-hover);
|
|
234
|
+
--_selected-active: var(--_subtle-active);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
[data-ui='list-item'][data-tone='success'] {
|
|
238
|
+
--_text: var(--slotted-tone-success-text, CanvasText);
|
|
239
|
+
--_subtle-hover: var(--slotted-tone-success-subtle-hover, ButtonFace);
|
|
240
|
+
--_subtle-active: var(--slotted-tone-success-subtle-active, ButtonFace);
|
|
241
|
+
--_solid-hover: var(--slotted-tone-success-solid-hover, ButtonFace);
|
|
242
|
+
--_solid-active: var(--slotted-tone-success-solid-active, ButtonFace);
|
|
243
|
+
--_surface: var(--slotted-tone-success-surface, Canvas);
|
|
244
|
+
--_selected-edge: var(--slotted-tone-success-border, ButtonBorder);
|
|
245
|
+
--_selected-surface: var(--slotted-list-item-background-selected, var(--_surface));
|
|
246
|
+
--_selected-text: var(--slotted-tone-success-text, CanvasText);
|
|
247
|
+
--_selected-hover: var(--_subtle-hover);
|
|
248
|
+
--_selected-active: var(--_subtle-active);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
[data-ui='list-item'][data-tone='warning'] {
|
|
252
|
+
--_text: var(--slotted-tone-warning-text, CanvasText);
|
|
253
|
+
--_subtle-hover: var(--slotted-tone-warning-subtle-hover, ButtonFace);
|
|
254
|
+
--_subtle-active: var(--slotted-tone-warning-subtle-active, ButtonFace);
|
|
255
|
+
--_solid-hover: var(--slotted-tone-warning-solid-hover, ButtonFace);
|
|
256
|
+
--_solid-active: var(--slotted-tone-warning-solid-active, ButtonFace);
|
|
257
|
+
--_surface: var(--slotted-tone-warning-surface, Canvas);
|
|
258
|
+
--_selected-edge: var(--slotted-tone-warning-border, ButtonBorder);
|
|
259
|
+
--_selected-surface: var(--slotted-list-item-background-selected, var(--_surface));
|
|
260
|
+
--_selected-text: var(--slotted-tone-warning-text, CanvasText);
|
|
261
|
+
--_selected-hover: var(--_subtle-hover);
|
|
262
|
+
--_selected-active: var(--_subtle-active);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
[data-ui='list-item'][data-tone='danger'] {
|
|
266
|
+
--_text: var(--slotted-tone-danger-text, CanvasText);
|
|
267
|
+
--_subtle-hover: var(--slotted-tone-danger-subtle-hover, ButtonFace);
|
|
268
|
+
--_subtle-active: var(--slotted-tone-danger-subtle-active, ButtonFace);
|
|
269
|
+
--_solid-hover: var(--slotted-tone-danger-solid-hover, ButtonFace);
|
|
270
|
+
--_solid-active: var(--slotted-tone-danger-solid-active, ButtonFace);
|
|
271
|
+
--_surface: var(--slotted-tone-danger-surface, Canvas);
|
|
272
|
+
--_selected-edge: var(--slotted-tone-danger-border, ButtonBorder);
|
|
273
|
+
--_selected-surface: var(--slotted-list-item-background-selected, var(--_surface));
|
|
274
|
+
--_selected-text: var(--slotted-tone-danger-text, CanvasText);
|
|
275
|
+
--_selected-hover: var(--_subtle-hover);
|
|
276
|
+
--_selected-active: var(--_subtle-active);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* ── The marker ─────────────────────────────────────────────────────────
|
|
281
|
+
*
|
|
282
|
+
* A character is never an icon — `docs/token-foundation.md` rule 3 — so the
|
|
283
|
+
* bullet is the library's own dot `Glyph`, an `<svg>` the binding draws in a
|
|
284
|
+
* `marker` part before the row's content and in the row's ink, not a `•` in a
|
|
285
|
+
* `content` string that changes shape with the reader's font.
|
|
286
|
+
*
|
|
287
|
+
* The number is a counter and stays text, because it is text: a reader hears
|
|
288
|
+
* "one" before the row, which is what the native marker said. It is the
|
|
289
|
+
* root's own `::before`, which stands in the same column the bullet's part
|
|
290
|
+
* does.
|
|
291
|
+
*
|
|
292
|
+
* The column is one line tall rather than the row's own height, so the mark
|
|
293
|
+
* sits on the title's line in a row of three lines instead of floating in the
|
|
294
|
+
* middle of the block.
|
|
295
|
+
*/
|
|
296
|
+
[data-ui='list-item'][data-marker='bullet'] > [data-part='marker'],
|
|
297
|
+
[data-ui='list-item'][data-marker='number']::before {
|
|
298
|
+
/* The mark sits on the title's first line and never in the middle of the
|
|
299
|
+
block, whatever `align` says. `align` is about the leading visual — an
|
|
300
|
+
avatar beside three lines of text belongs with the title or with the
|
|
301
|
+
block, and both readings are defensible — while a list marker has only
|
|
302
|
+
one reading, and it is the platform's own. The first capture centred a
|
|
303
|
+
bullet between two lines and read as a bullet nobody had placed. */
|
|
304
|
+
align-items: start;
|
|
305
|
+
/* One line tall, stated rather than stretched. The mark's own box holds no
|
|
306
|
+
text, so a row that wraps gave it the height of its padding alone and the
|
|
307
|
+
dot disappeared — the numbered marker survived only because its digits
|
|
308
|
+
gave it a height of their own. */
|
|
309
|
+
block-size: calc(
|
|
310
|
+
var(--_pad-block) * 2 + var(--_font-size) * var(--slotted-line-height-md, 1.5)
|
|
311
|
+
);
|
|
312
|
+
box-sizing: border-box;
|
|
313
|
+
/* The row's ink, not its muted step: a marker is part of what the row says,
|
|
314
|
+
which is why the browser's own `::marker` inherits `color`. */
|
|
315
|
+
color: var(--_text);
|
|
316
|
+
display: flex;
|
|
317
|
+
flex: none;
|
|
318
|
+
font-size: var(--_font-size);
|
|
319
|
+
/* A ten beside a nine is only a column if the digits are the same width. */
|
|
320
|
+
font-variant-numeric: tabular-nums;
|
|
321
|
+
/* The column is the glyph's own width and the gap beside it is the control
|
|
322
|
+
scale's, so the mark and the leading visual of the row below stand in one
|
|
323
|
+
column and the text starts on one line. Read as one box with the gap
|
|
324
|
+
inside it, the number and the title had nothing between them. */
|
|
325
|
+
inline-size: var(--_icon-size);
|
|
326
|
+
line-height: var(--slotted-line-height-md, 1.5);
|
|
327
|
+
margin-inline-end: var(--_gap);
|
|
328
|
+
margin-inline-start: var(--_pad-inline);
|
|
329
|
+
padding-block-start: var(--_pad-block);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
[data-ui='list-item'][data-marker='bullet'] > [data-part='marker'] {
|
|
333
|
+
--slotted-icon-size: var(--_marker-size);
|
|
334
|
+
justify-content: center;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* The dot is placed on the middle of the first line rather than on the
|
|
338
|
+
middle of the part, because the part is one line and its padding tall and
|
|
339
|
+
the dot has no baseline to sit on. Half the line less half the dot, so the
|
|
340
|
+
dot stands between the baseline and the cap line rather than on either. */
|
|
341
|
+
[data-ui='list-item'][data-marker='bullet'] > [data-part='marker'] > [data-ui='icon'] {
|
|
342
|
+
margin-block-start: calc(
|
|
343
|
+
var(--_font-size) * var(--slotted-line-height-md, 1.5) * 0.5 - var(--_marker-size) * 0.5
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
[data-ui='list-item'][data-marker='number']::before {
|
|
348
|
+
content: counter(slotted-list-item) '.';
|
|
349
|
+
justify-content: end;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* The mark already stands in its own gutter, so the box beside it gives up
|
|
353
|
+
the padding it would otherwise repeat. */
|
|
354
|
+
[data-ui='list-item']:is([data-marker='bullet'], [data-marker='number']) > [data-part='content'] {
|
|
355
|
+
padding-inline-start: 0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/* `inset` is the set's answer for a list inside a box that already pads its
|
|
359
|
+
own content. The mark gives up its gutter with everything else. */
|
|
360
|
+
[data-ui='list-item'][data-inset][data-marker='bullet'] > [data-part='marker'],
|
|
361
|
+
[data-ui='list-item'][data-inset][data-marker='number']::before {
|
|
362
|
+
margin-inline-start: 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* ── The box that is read, and sometimes activated ──────────────────────
|
|
367
|
+
*
|
|
368
|
+
* Three columns: the leading visual, the text, and the metadata that belongs
|
|
369
|
+
* to what the row says. Each gap is a margin on the optional part rather than
|
|
370
|
+
* a `column-gap` on the grid, because a gap between two empty tracks is still
|
|
371
|
+
* a gap — a row with no leading visual would start one gap in from every row
|
|
372
|
+
* that has one.
|
|
373
|
+
*
|
|
374
|
+
* The reset is what makes a `button` and an `a` the same box as a `div`: a
|
|
375
|
+
* consumer choosing between the three chooses an accessibility tree, never a
|
|
376
|
+
* different picture.
|
|
377
|
+
*/
|
|
378
|
+
[data-ui='list-item'] > [data-part='content'] {
|
|
379
|
+
appearance: none;
|
|
380
|
+
background-color: transparent;
|
|
381
|
+
border: none;
|
|
382
|
+
/* The row's corners, so the focus ring follows the shape the reader sees
|
|
383
|
+
rather than a rectangle inside it. */
|
|
384
|
+
border-radius: inherit;
|
|
385
|
+
/* The floor is a border-box height, not a content-box one. Read as content
|
|
386
|
+
the row stood fifty pixels tall for one line of thirteen-pixel text: the
|
|
387
|
+
padding was counted twice, once by the box and once by the floor. */
|
|
388
|
+
box-sizing: border-box;
|
|
389
|
+
color: var(--_text);
|
|
390
|
+
display: grid;
|
|
391
|
+
/* A basis of nought rather than of its content. Flex wraps before it
|
|
392
|
+
shrinks, so a box whose basis is its own text pushed itself onto a second
|
|
393
|
+
line the moment the row was narrow — the marker stood alone above its
|
|
394
|
+
own title at 240 pixels. With nothing to wrap, only the item that asks
|
|
395
|
+
for a whole line gets one, which is what `actions` does below the
|
|
396
|
+
breakpoint. */
|
|
397
|
+
flex: 1 1 0%;
|
|
398
|
+
font: inherit;
|
|
399
|
+
font-size: var(--_font-size);
|
|
400
|
+
grid-template-areas: 'start body end';
|
|
401
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
402
|
+
align-items: center;
|
|
403
|
+
min-block-size: var(--_min-block);
|
|
404
|
+
min-inline-size: 0;
|
|
405
|
+
padding-block: var(--_pad-block);
|
|
406
|
+
padding-inline: var(--_pad-inline);
|
|
407
|
+
text-align: start;
|
|
408
|
+
text-decoration: none;
|
|
409
|
+
transition: color var(--slotted-control-transition-duration, var(--slotted-duration-short))
|
|
410
|
+
var(--slotted-control-transition-easing, var(--slotted-easing-standard));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* A variant that draws a line between rows wants a square fill, because a
|
|
415
|
+
* rounded wash inside a full-bleed rule fights the line it sits on. The two
|
|
416
|
+
* variants that draw no line — a plain run of rows, and a row that is its own
|
|
417
|
+
* surface — round it, which is what a selected row in a sidebar looks like
|
|
418
|
+
* everywhere it is done well.
|
|
419
|
+
*
|
|
420
|
+
* `framed` clips its own corners at the set, so the first and last rows are
|
|
421
|
+
* rounded by the box rather than by themselves.
|
|
422
|
+
*/
|
|
423
|
+
[data-ui='list-item']:is([data-variant='ruled'], [data-variant='framed']) {
|
|
424
|
+
border-radius: 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* A row whose whole box resolves somewhere, or runs a command, is a target
|
|
428
|
+
and the pointer says so. A row that is only read keeps the arrow. */
|
|
429
|
+
[data-ui='list-item']:not([data-disabled]) > :is(a, button)[data-part='content']:not(:disabled) {
|
|
430
|
+
cursor: pointer;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* `inset` takes the row's inline padding away so a list inside a padded box
|
|
434
|
+
lines its titles up with the box. The fill and the rule still run edge to
|
|
435
|
+
edge, which is the half MUI's `disableGutters` leaves out. */
|
|
436
|
+
[data-ui='list-item'][data-inset] > [data-part='content'] {
|
|
437
|
+
padding-inline: 0;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* `start` for a row of one line, and for a row of three the leading visual
|
|
442
|
+
* belongs beside the title rather than in the middle of the block. MUI calls
|
|
443
|
+
* the same decision `alignItems`; Angular Material derives it from counting
|
|
444
|
+
* the lines, which is a count a translated string can change.
|
|
445
|
+
*/
|
|
446
|
+
[data-ui='list-item'][data-align='start'] > [data-part='content'] {
|
|
447
|
+
align-items: start;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='start'] {
|
|
451
|
+
align-items: center;
|
|
452
|
+
color: var(--_text);
|
|
453
|
+
display: flex;
|
|
454
|
+
flex: none;
|
|
455
|
+
grid-area: start;
|
|
456
|
+
margin-inline-end: var(--_gap);
|
|
457
|
+
/* The column is the control glyph's, so an icon, an avatar and a checkbox
|
|
458
|
+
each land on the same line however tall they are. */
|
|
459
|
+
min-inline-size: var(--_icon-size);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* A chooser in the leading column (LI2). `checkbox` lifts its own box onto
|
|
464
|
+
* the first line of the text beside it — the same line box this row sets
|
|
465
|
+
* its title in, at the same step — so the column only has to stand at the
|
|
466
|
+
* top of that line and be as tall as it: the box then sits on the title's
|
|
467
|
+
* centre by the chooser's own arithmetic rather than by a second one here.
|
|
468
|
+
* Centred on the block, as an icon is, a one-line row put the box a pixel
|
|
469
|
+
* low and a two-line row put it between the lines.
|
|
470
|
+
*
|
|
471
|
+
* The column is the chooser's own square, fixed across densities as the
|
|
472
|
+
* chooser is (CK1); the gap beside it is the row's control gap, the same
|
|
473
|
+
* distance the chooser puts between its box and its own label.
|
|
474
|
+
*/
|
|
475
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='start']:has(> [data-ui='checkbox']) {
|
|
476
|
+
align-items: start;
|
|
477
|
+
inline-size: var(--_control-size);
|
|
478
|
+
min-block-size: calc(var(--_font-size) * var(--slotted-line-height-md, 1.5));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* A leading visual beside a three-line row sits on the title's line, and the
|
|
482
|
+
line is the box's own, not the block's. */
|
|
483
|
+
[data-ui='list-item'][data-align='start'] > [data-part='content'] > [data-part='start'] {
|
|
484
|
+
min-block-size: calc(var(--_font-size) * var(--slotted-line-height-md, 1.5));
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The text column, and the one box in the row that may shrink. Without
|
|
489
|
+
* `min-inline-size: 0` a flex or grid item refuses to go below its longest
|
|
490
|
+
* word, so a title that is one unbroken token — a URL, a commit hash — pushes
|
|
491
|
+
* the metadata out of the row instead of breaking inside it.
|
|
492
|
+
*/
|
|
493
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='body'] {
|
|
494
|
+
display: flex;
|
|
495
|
+
flex-direction: column;
|
|
496
|
+
grid-area: body;
|
|
497
|
+
min-inline-size: 0;
|
|
498
|
+
row-gap: var(--slotted-list-item-body-gap, var(--slotted-space-1, 0.125rem));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='body'] > [data-part='label'] {
|
|
502
|
+
color: inherit;
|
|
503
|
+
font-size: var(--_font-size);
|
|
504
|
+
font-weight: var(--slotted-list-item-font-weight, var(--slotted-font-weight-regular, 400));
|
|
505
|
+
line-height: var(--slotted-line-height-md, 1.5);
|
|
506
|
+
margin-block: 0;
|
|
507
|
+
min-inline-size: 0;
|
|
508
|
+
/* A single unbroken token breaks inside the row rather than widening it.
|
|
509
|
+
No surveyed implementation does this; MUI's `ListItemText` overflows. */
|
|
510
|
+
overflow-wrap: anywhere;
|
|
511
|
+
/* `plaintext` rather than `isolate`: a row is a run of content, so a title
|
|
512
|
+
in another script takes its own paragraph direction and leaves the row
|
|
513
|
+
around it alone. */
|
|
514
|
+
unicode-bidi: plaintext;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='body'] > [data-part='description'] {
|
|
518
|
+
color: var(--_muted);
|
|
519
|
+
font-size: var(--slotted-list-item-description-font-size, var(--slotted-font-size-xs, 0.75rem));
|
|
520
|
+
line-height: var(--slotted-line-height-sm, 1.45);
|
|
521
|
+
margin-block: 0;
|
|
522
|
+
min-inline-size: 0;
|
|
523
|
+
overflow-wrap: anywhere;
|
|
524
|
+
unicode-bidi: plaintext;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* `truncate` clips the title and the lines under it to one line each. Both,
|
|
529
|
+
* rather than the title alone: a clipped title over a description wrapping to
|
|
530
|
+
* four lines is a row that gave up on one measure and not the other.
|
|
531
|
+
*
|
|
532
|
+
* The content stays in the DOM, which is the briefing's standing decision — a
|
|
533
|
+
* truncated string is still readable to assistive technology and still
|
|
534
|
+
* reachable in full when the row is opened.
|
|
535
|
+
*/
|
|
536
|
+
[data-ui='list-item'][data-truncate]
|
|
537
|
+
> [data-part='content']
|
|
538
|
+
> [data-part='body']
|
|
539
|
+
> :is([data-part='label'], [data-part='description']) {
|
|
540
|
+
overflow: hidden;
|
|
541
|
+
overflow-wrap: normal;
|
|
542
|
+
text-overflow: ellipsis;
|
|
543
|
+
white-space: nowrap;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* The metadata that belongs to what the row says — a timestamp, a count, a
|
|
548
|
+
* badge. It is inside `content`, so it is part of the row's own name for a
|
|
549
|
+
* reader and part of its target for a pointer. Anything that acts is
|
|
550
|
+
* `actions` instead.
|
|
551
|
+
*/
|
|
552
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='end'] {
|
|
553
|
+
align-items: center;
|
|
554
|
+
color: var(--_muted);
|
|
555
|
+
display: flex;
|
|
556
|
+
flex: none;
|
|
557
|
+
gap: var(--_gap);
|
|
558
|
+
grid-area: end;
|
|
559
|
+
margin-inline-start: var(--_gap);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* ── Independent targets ────────────────────────────────────────────────
|
|
564
|
+
*
|
|
565
|
+
* A sibling of `content` and never its child: a `button` cannot contain a
|
|
566
|
+
* `button` and an `a` can contain neither, so a row that navigates and also
|
|
567
|
+
* deletes has to put its two controls side by side. Every surveyed
|
|
568
|
+
* implementation lets a consumer nest them instead, and produces HTML no
|
|
569
|
+
* browser can make focusable.
|
|
570
|
+
*
|
|
571
|
+
* The box is above the row's own fill, so a control here is operable on a row
|
|
572
|
+
* whose whole surface resolves somewhere else.
|
|
573
|
+
*/
|
|
574
|
+
[data-ui='list-item'] > [data-part='actions'] {
|
|
575
|
+
align-items: center;
|
|
576
|
+
/* The box counts its own inset (LI4). Below the breakpoint it takes the
|
|
577
|
+
whole line and the row's inline inset on both sides, and read as
|
|
578
|
+
content it stood the row's width plus twenty-six pixels: a 266px line in
|
|
579
|
+
a 240px list, in every scheme. */
|
|
580
|
+
box-sizing: border-box;
|
|
581
|
+
display: flex;
|
|
582
|
+
flex: none;
|
|
583
|
+
gap: var(--_gap);
|
|
584
|
+
padding-inline-end: var(--_pad-inline);
|
|
585
|
+
position: relative;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
[data-ui='list-item'][data-inset] > [data-part='actions'] {
|
|
589
|
+
padding-inline-end: 0;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* The independent targets follow `align` for the same reason the leading
|
|
594
|
+
* visual and the metadata do. Left centred on the block while `end` sat on
|
|
595
|
+
* the title's line, a row of two lines put its badge and its delete control
|
|
596
|
+
* on two different lines — the one thing a trailing pair must not do.
|
|
597
|
+
*/
|
|
598
|
+
[data-ui='list-item'][data-align='start'] > [data-part='actions'] {
|
|
599
|
+
align-items: start;
|
|
600
|
+
padding-block-start: var(--_pad-block);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* ── Ruled, framed, separated ───────────────────────────────────────────
|
|
605
|
+
*
|
|
606
|
+
* Before the states, and the order is the point: a separated row states its
|
|
607
|
+
* own resting fill and a selected row replaces it, and the two selectors
|
|
608
|
+
* carry the same weight. Read the other way round the resting surface won
|
|
609
|
+
* and a selected card kept its edge and lost its tint.
|
|
610
|
+
*
|
|
611
|
+
* The line between two rows is drawn by the row below, because the row is the
|
|
612
|
+
* only element that knows whether it is the first of its list. A rule drawn
|
|
613
|
+
* by the set would need a selector reaching into this family, which is what
|
|
614
|
+
* the two sheets do not do.
|
|
615
|
+
*
|
|
616
|
+
* `framed` rules its rows exactly as `ruled` does; what it adds is the box
|
|
617
|
+
* around them, and that box belongs to the set.
|
|
618
|
+
*/
|
|
619
|
+
[data-ui='list-item']:is([data-variant='ruled'], [data-variant='framed']):not(:first-child) {
|
|
620
|
+
/* A shadow rather than a border, and the reason is the pointer. A border is
|
|
621
|
+
part of the row's box and outside the box that paints hover, so the top
|
|
622
|
+
pixel of every ruled row answered nothing: the reader saw a one-pixel
|
|
623
|
+
strip where the fill stopped short of the rule. Drawn outward the rule
|
|
624
|
+
takes no layout at all — it lands on the last pixel of the row above,
|
|
625
|
+
which is painted before it — so `content` fills the row and every pixel
|
|
626
|
+
of it is hoverable.
|
|
627
|
+
|
|
628
|
+
The offset is physical because `box-shadow` has no logical form. It costs
|
|
629
|
+
nothing here: the rule runs along the block axis, which is vertical in
|
|
630
|
+
both directions this library supports. */
|
|
631
|
+
--_rule-shadow: 0 calc(var(--_rule-width) * -1) 0 0 var(--_rule);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* A separated row is its own surface. It keeps the frame the set would have
|
|
636
|
+
* drawn once, at row scale, so a list of cards and a list of rows are the
|
|
637
|
+
* same family in two arrangements rather than two families.
|
|
638
|
+
*/
|
|
639
|
+
[data-ui='list-item'][data-variant='separated'] {
|
|
640
|
+
--_fill: var(--slotted-list-item-background, var(--slotted-surface-raised, Canvas));
|
|
641
|
+
|
|
642
|
+
border: var(--_rule-width) solid var(--_rule);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/* The row's own corners clip the fill its content paints, so a hover wash
|
|
646
|
+
inside a rounded row does not square off its edges. `clip` rather than
|
|
647
|
+
`hidden`: a row is not a scroll container, and `hidden` would make it one. */
|
|
648
|
+
[data-ui='list-item'][data-variant='separated'] {
|
|
649
|
+
overflow: clip;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* ── The states ─────────────────────────────────────────────────────────
|
|
654
|
+
*
|
|
655
|
+
* Hover lays a wash under the box and press goes one step further. Both hold
|
|
656
|
+
* themselves back for `disabled` and for `loading`, which are the two states
|
|
657
|
+
* above them in `STATE_PRECEDENCE`; the library learned that from a defect,
|
|
658
|
+
* and `states.test.mjs` is what keeps it from being relearned the same way.
|
|
659
|
+
*
|
|
660
|
+
* Only a row that acts answers the pointer. A row that is only read has
|
|
661
|
+
* nothing to say about being pointed at, and washing it would promise an
|
|
662
|
+
* interaction that never arrives.
|
|
663
|
+
*/
|
|
664
|
+
[data-ui='list-item']:not([data-disabled]):not([data-loading]):has(
|
|
665
|
+
> :is(a, button)[data-part='content']:not(:disabled):hover
|
|
666
|
+
) {
|
|
667
|
+
--_fill: var(--_hover);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
[data-ui='list-item']:not([data-disabled]):not([data-loading]):has(
|
|
671
|
+
> :is(a, button)[data-part='content']:not(:disabled):active
|
|
672
|
+
) {
|
|
673
|
+
--_fill: var(--_active);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* The ring sits inside the row rather than around it. A row is full width, so
|
|
678
|
+
* an outward ring on the first row of a framed list is drawn under the frame
|
|
679
|
+
* and on the last row it is drawn outside the page; a negative offset keeps
|
|
680
|
+
* the whole ring on the row it is about.
|
|
681
|
+
*/
|
|
682
|
+
[data-ui='list-item'] > [data-part='content']:focus-visible {
|
|
683
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
684
|
+
outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Current is a ground, and the two states are told apart by which ground: a
|
|
689
|
+
* row can be the one the reader is on **and** one of the rows they have
|
|
690
|
+
* chosen, and when it is both the selection is the one that shows, because
|
|
691
|
+
* it is declared after this and the reader already knows where they are.
|
|
692
|
+
*
|
|
693
|
+
* `aria-current` is the one selection-shaped state ARIA 1.2 lets a `listitem`
|
|
694
|
+
* announce for itself, so this is also the only one of the two the row says
|
|
695
|
+
* out loud.
|
|
696
|
+
*/
|
|
697
|
+
[data-ui='list-item'][data-current] {
|
|
698
|
+
--_fill: var(--_current-surface);
|
|
699
|
+
/* The edge is an inset shadow rather than a border, so the state changes
|
|
700
|
+
no measurement and moves no text. It is what carries the state in
|
|
701
|
+
`high-contrast`, where every tone surface is the page's own white. */
|
|
702
|
+
--_edge-shadow: inset 0 0 0 var(--_rule-width) var(--_current-edge);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Selected is a fill, and it is a paint rather than a model: `aria-selected`
|
|
707
|
+
* is not valid on `listitem`, so the row mirrors a selection the page owns
|
|
708
|
+
* and the control the page puts in `start` — a `checkbox` — is what announces
|
|
709
|
+
* it. `card` reached the same conclusion for the same reason.
|
|
710
|
+
*/
|
|
711
|
+
[data-ui='list-item'][data-selected] {
|
|
712
|
+
/* A selected row that is hovered has to darken, not lighten. The resting
|
|
713
|
+
fill is already the tone's subtle step, so the two pointer states move
|
|
714
|
+
one step along the same subtle pair rather than staying where an
|
|
715
|
+
unselected row leaves them — otherwise hovering a selected row washed it
|
|
716
|
+
out. */
|
|
717
|
+
--_hover: var(--_selected-hover);
|
|
718
|
+
--_active: var(--_selected-active);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
[data-ui='list-item'][data-selected] {
|
|
722
|
+
--_fill: var(--_selected-surface);
|
|
723
|
+
--_edge-shadow: inset 0 0 0 var(--_rule-width) var(--_selected-edge);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* The rule of a divided list is drawn by the row below, outward, on the
|
|
728
|
+
* last pixel of the row above — the pixel a selected or current row's inset
|
|
729
|
+
* edge ends on. Painted later, it covered that pixel, and a selected row in
|
|
730
|
+
* a ruled list was a box open at the bottom. So neither the row after one of
|
|
731
|
+
* those nor the row itself draws a rule: the edge is the line on both sides,
|
|
732
|
+
* and a rule drawn above the edge made its top two pixels in `high-contrast`,
|
|
733
|
+
* where both are black.
|
|
734
|
+
*/
|
|
735
|
+
[data-ui='list-item']:is([data-selected], [data-current]):not(:first-child),
|
|
736
|
+
[data-ui='list-item']:is([data-selected], [data-current]) + [data-ui='list-item'] {
|
|
737
|
+
--_rule-shadow: 0 0 0 0 transparent;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/* A run of selected rows is one box. The second of two draws its sides and
|
|
741
|
+
its bottom, and the bottom edge of the row above is the one line between
|
|
742
|
+
them; both edges drawn made that line two pixels. The offsets are
|
|
743
|
+
physical because `box-shadow` has no logical form, and the two sides are
|
|
744
|
+
the same width, so the mirrored row is the same picture. */
|
|
745
|
+
[data-ui='list-item'][data-selected] + [data-ui='list-item'][data-selected] {
|
|
746
|
+
--_edge-shadow:
|
|
747
|
+
inset 0 calc(var(--_rule-width) * -1) 0 0 var(--_selected-edge),
|
|
748
|
+
inset var(--_rule-width) 0 0 0 var(--_selected-edge),
|
|
749
|
+
inset calc(var(--_rule-width) * -1) 0 0 0 var(--_selected-edge);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
[data-ui='list-item'][data-selected] > [data-part='content'] {
|
|
753
|
+
color: var(--_selected-text);
|
|
754
|
+
font-weight: var(
|
|
755
|
+
--slotted-list-item-font-weight-selected,
|
|
756
|
+
var(--slotted-font-weight-medium, 500)
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
[data-ui='list-item'][data-current] > [data-part='content'] {
|
|
761
|
+
font-weight: var(
|
|
762
|
+
--slotted-list-item-font-weight-current,
|
|
763
|
+
var(--slotted-font-weight-medium, 500)
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* ── Loading ────────────────────────────────────────────────────────────
|
|
769
|
+
*
|
|
770
|
+
* The binding writes `aria-busy` and takes the activation away — the native
|
|
771
|
+
* `disabled` from a button, the `href` from an anchor — so the row cannot run
|
|
772
|
+
* the same command twice. What is left for the sheet is to say so without
|
|
773
|
+
* changing the row's size, which `docs/component-features.md` section 2.5
|
|
774
|
+
* requires: the ink recedes and the pointer changes, and nothing moves.
|
|
775
|
+
*
|
|
776
|
+
* No placeholder is drawn. `skeleton` owns placeholder geometry, and a second
|
|
777
|
+
* answer to that question is what `collapsible` already refused.
|
|
778
|
+
*/
|
|
779
|
+
[data-ui='list-item'][data-loading] {
|
|
780
|
+
/* One retarget rather than a rule per part: the title, the description, the
|
|
781
|
+
metadata and the mark all read the same two custom properties, so the
|
|
782
|
+
whole row recedes together and nothing changes size. */
|
|
783
|
+
--_text: var(--_muted);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
[data-ui='list-item'][data-loading] > [data-part='content'] {
|
|
787
|
+
cursor: progress;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* ── Disabled ───────────────────────────────────────────────────────────
|
|
792
|
+
*
|
|
793
|
+
* The row dims and stops answering the pointer. The attribute that means it
|
|
794
|
+
* is on `content` — `disabled` on a button, `aria-disabled` on an anchor that
|
|
795
|
+
* has also lost its `href` — and never on the `li`: ARIA 1.2 deprecates
|
|
796
|
+
* `aria-disabled` on `listitem`, and no surveyed implementation says so.
|
|
797
|
+
*
|
|
798
|
+
* A control the page put in `actions` is the page's to disable. Only the
|
|
799
|
+
* control can refuse an interaction, which is the rule `card` states for the
|
|
800
|
+
* same shape.
|
|
801
|
+
*/
|
|
802
|
+
[data-ui='list-item'][data-disabled] {
|
|
803
|
+
/* Both, stated from one alias rather than one pointing at the other: a row
|
|
804
|
+
that is loading retargets `--_text` at `--_muted`, and a disabled loading
|
|
805
|
+
row would otherwise be a cycle CSS resolves by dropping both. Disabled is
|
|
806
|
+
the stronger state and its rule comes last, so it wins the pair. */
|
|
807
|
+
--_disabled-ink: var(
|
|
808
|
+
--slotted-list-item-color-disabled,
|
|
809
|
+
var(--slotted-disabled-foreground, GrayText)
|
|
810
|
+
);
|
|
811
|
+
--_text: var(--_disabled-ink);
|
|
812
|
+
--_muted: var(--_disabled-ink);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
[data-ui='list-item'][data-disabled] > [data-part='content'] {
|
|
816
|
+
cursor: default;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* A separated row recedes onto the sunken surface rather than onto the
|
|
821
|
+
* control's disabled ground, which is `card`'s rule for the same shape. The
|
|
822
|
+
* ground is worth naming: in the light scheme it is the same hex as the tone
|
|
823
|
+
* surface a selected row is filled with, so a disabled card and a selected
|
|
824
|
+
* one were one rectangle told apart only by their edge.
|
|
825
|
+
*/
|
|
826
|
+
[data-ui='list-item'][data-disabled][data-variant='separated'] {
|
|
827
|
+
--_fill: var(--slotted-surface-sunken, Canvas);
|
|
828
|
+
|
|
829
|
+
border-color: var(--slotted-disabled-border, GrayText);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* ── The narrow row ─────────────────────────────────────────────────────
|
|
834
|
+
*
|
|
835
|
+
* Below 22rem the trailing metadata leaves the row's inline axis and sits
|
|
836
|
+
* under the title, in the title's own column, rather than squeezing it. The
|
|
837
|
+
* leading visual and the independent targets stay where they are: one is the
|
|
838
|
+
* row's identity and the other is its controls, and neither becomes easier to
|
|
839
|
+
* use by moving.
|
|
840
|
+
*
|
|
841
|
+
* The breakpoint is a literal because `@container (max-inline-size: var(--x))`
|
|
842
|
+
* is invalid CSS — `docs/token-foundation.md` rule 4.
|
|
843
|
+
*/
|
|
844
|
+
@container slotted-list-item (max-inline-size: 22rem) {
|
|
845
|
+
[data-ui='list-item'] > [data-part='content'] {
|
|
846
|
+
grid-template-areas:
|
|
847
|
+
'start body'
|
|
848
|
+
'start end';
|
|
849
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='end'] {
|
|
853
|
+
justify-content: start;
|
|
854
|
+
margin-block-start: var(--slotted-list-item-body-gap, var(--slotted-space-1, 0.125rem));
|
|
855
|
+
margin-inline-start: 0;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/* The leading visual now spans two rows, so it stops being centred on the
|
|
859
|
+
block and returns to the title's line. */
|
|
860
|
+
[data-ui='list-item'] > [data-part='content'] > [data-part='start'] {
|
|
861
|
+
align-self: start;
|
|
862
|
+
min-block-size: calc(var(--_font-size) * var(--slotted-line-height-md, 1.5));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* The independent targets take their own line. On one line with the box
|
|
867
|
+
* they never shrink — a target is a target — so the box shrank instead,
|
|
868
|
+
* and a row whose target carried a word rather than a glyph left its
|
|
869
|
+
* metadata spilling out of a column eighty pixels wide.
|
|
870
|
+
*
|
|
871
|
+
* They stay at the end of the row, where they were, and take the row's own
|
|
872
|
+
* inline inset so they line up with the content above them.
|
|
873
|
+
*/
|
|
874
|
+
[data-ui='list-item'] > [data-part='actions'] {
|
|
875
|
+
flex-basis: 100%;
|
|
876
|
+
justify-content: flex-end;
|
|
877
|
+
padding-block-end: var(--_pad-block);
|
|
878
|
+
padding-inline: var(--_pad-inline);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
[data-ui='list-item'][data-inset] > [data-part='actions'] {
|
|
882
|
+
padding-inline: 0;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Unless every target is a glyph. Two icon-only controls are a column
|
|
887
|
+
* narrower than the visual at the start of the row, and a line of their
|
|
888
|
+
* own under the words put a row's two smallest things at the end of a
|
|
889
|
+
* line that belonged to nothing — a notification list on a phone read as
|
|
890
|
+
* a list of rows with a stray pair of marks under each. A glyph pair
|
|
891
|
+
* keeps the line it had; a target that carries a word still takes its
|
|
892
|
+
* own, because a word is what does not fit.
|
|
893
|
+
*/
|
|
894
|
+
[data-ui='list-item'] > [data-part='actions']:not(:has(> :not([data-shape]))) {
|
|
895
|
+
flex-basis: auto;
|
|
896
|
+
padding-block-end: 0;
|
|
897
|
+
padding-inline: 0 var(--_pad-inline);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
[data-ui='list-item'][data-inset] > [data-part='actions']:not(:has(> :not([data-shape]))) {
|
|
901
|
+
padding-inline-end: 0;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* ── Forced colours ─────────────────────────────────────────────────────
|
|
907
|
+
*
|
|
908
|
+
* The theme remaps every semantic token once, so the row needs a rule only
|
|
909
|
+
* for what it paints itself. The two grounds and the two rings are all
|
|
910
|
+
* dropped here, so both states have to be said again in the system's own
|
|
911
|
+
* colours.
|
|
912
|
+
*/
|
|
913
|
+
@media (forced-colors: active) {
|
|
914
|
+
/**
|
|
915
|
+
* Every tone surface is remapped to `Canvas`, so a selected row and a
|
|
916
|
+
* resting one would be the same rectangle. Selection is the accent state,
|
|
917
|
+
* and the system's own selected pair is what says so.
|
|
918
|
+
*/
|
|
919
|
+
[data-ui='list-item'][data-selected] {
|
|
920
|
+
background-color: Highlight;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
[data-ui='list-item'][data-selected] > [data-part='content'] {
|
|
924
|
+
color: HighlightText;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* The current row keeps its ring as a one-pixel outline in the selection
|
|
929
|
+
* colour, drawn inward so it changes no measurement: the inset shadow that
|
|
930
|
+
* says it elsewhere is decoration the theme cannot reach (R1).
|
|
931
|
+
*/
|
|
932
|
+
[data-ui='list-item'][data-current]:not([data-selected]) {
|
|
933
|
+
outline: var(--slotted-border-width-thin, 1px) solid Highlight;
|
|
934
|
+
outline-offset: calc(-1 * var(--slotted-border-width-thin, 1px));
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|