@slotted/styles 0.0.0-stage → 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/package.json +276 -3
- package/src/accordion/accordion.css +96 -0
- package/src/accordion/accordion.tokens.json +14 -0
- package/src/action-bar/action-bar.css +455 -0
- package/src/action-bar/action-bar.tokens.json +50 -0
- package/src/action-sheet/action-sheet.css +462 -0
- package/src/action-sheet/action-sheet.tokens.json +59 -0
- package/src/alert/alert.css +764 -0
- package/src/alert/alert.tokens.json +77 -0
- package/src/app-shell/app-shell.css +1899 -0
- package/src/app-shell/app-shell.tokens.json +88 -0
- package/src/aspect-ratio/aspect-ratio.css +131 -0
- package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
- package/src/attachment/attachment.css +906 -0
- package/src/attachment/attachment.tokens.json +85 -0
- package/src/avatar/avatar.css +598 -0
- package/src/avatar/avatar.tokens.json +64 -0
- package/src/avatar-group/avatar-group.css +268 -0
- package/src/avatar-group/avatar-group.tokens.json +16 -0
- package/src/badge/badge.css +462 -0
- package/src/badge/badge.tokens.json +58 -0
- package/src/breadcrumb/breadcrumb.css +441 -0
- package/src/breadcrumb/breadcrumb.tokens.json +50 -0
- package/src/button/button.css +754 -0
- package/src/button/button.tokens.json +72 -0
- package/src/button-group/button-group.css +455 -0
- package/src/button-group/button-group.tokens.json +11 -0
- package/src/calendar/calendar.css +846 -0
- package/src/calendar/calendar.tokens.json +67 -0
- package/src/card/card.css +602 -0
- package/src/card/card.tokens.json +68 -0
- package/src/carousel/carousel.css +860 -0
- package/src/carousel/carousel.tokens.json +62 -0
- package/src/cascader/cascader.css +1320 -0
- package/src/cascader/cascader.tokens.json +103 -0
- package/src/chart/chart.css +1473 -0
- package/src/chart/chart.tokens.json +107 -0
- package/src/checkbox/checkbox.css +1011 -0
- package/src/checkbox/checkbox.tokens.json +102 -0
- package/src/checkbox-group/checkbox-group.css +70 -0
- package/src/checkbox-group/checkbox-group.tokens.json +6 -0
- package/src/code-block/code-block.css +555 -0
- package/src/code-block/code-block.tokens.json +69 -0
- package/src/collapsible/collapsible.css +546 -0
- package/src/collapsible/collapsible.tokens.json +55 -0
- package/src/color-picker/color-picker.css +607 -0
- package/src/color-picker/color-picker.tokens.json +58 -0
- package/src/column-manager/column-manager.css +452 -0
- package/src/column-manager/column-manager.tokens.json +43 -0
- package/src/combobox/combobox.css +1048 -0
- package/src/combobox/combobox.tokens.json +112 -0
- package/src/command-palette/command-palette.css +1000 -0
- package/src/command-palette/command-palette.tokens.json +75 -0
- package/src/container/container.css +198 -0
- package/src/container/container.tokens.json +18 -0
- package/src/context-menu/context-menu.css +104 -0
- package/src/context-menu/context-menu.tokens.json +11 -0
- package/src/currency-field/currency-field.css +787 -0
- package/src/currency-field/currency-field.tokens.json +80 -0
- package/src/dashboard-grid/dashboard-grid.css +748 -0
- package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
- package/src/data-grid/data-grid.css +2484 -0
- package/src/data-grid/data-grid.tokens.json +100 -0
- package/src/data-list/data-list.css +455 -0
- package/src/data-list/data-list.tokens.json +35 -0
- package/src/date-field/date-field.css +560 -0
- package/src/date-field/date-field.tokens.json +80 -0
- package/src/date-picker/date-picker.css +420 -0
- package/src/date-picker/date-picker.tokens.json +49 -0
- package/src/date-range-picker/date-range-picker.css +983 -0
- package/src/date-range-picker/date-range-picker.tokens.json +109 -0
- package/src/datetime-field/datetime-field.css +850 -0
- package/src/datetime-field/datetime-field.tokens.json +91 -0
- package/src/datetime-picker/datetime-picker.css +843 -0
- package/src/datetime-picker/datetime-picker.tokens.json +78 -0
- package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
- package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
- package/src/description-list/description-list.css +675 -0
- package/src/description-list/description-list.tokens.json +66 -0
- package/src/detail-panel/detail-panel.css +329 -0
- package/src/detail-panel/detail-panel.tokens.json +33 -0
- package/src/dialog/dialog.css +968 -0
- package/src/dialog/dialog.tokens.json +66 -0
- package/src/divider/divider.css +131 -0
- package/src/divider/divider.tokens.json +18 -0
- package/src/drawer/drawer.css +1303 -0
- package/src/drawer/drawer.tokens.json +75 -0
- package/src/entity-picker/entity-picker.css +1367 -0
- package/src/entity-picker/entity-picker.tokens.json +118 -0
- package/src/event-calendar/event-calendar.css +2148 -0
- package/src/event-calendar/event-calendar.tokens.json +87 -0
- package/src/field/field.css +707 -0
- package/src/field/field.tokens.json +58 -0
- package/src/field-group/field-group.css +226 -0
- package/src/field-group/field-group.tokens.json +33 -0
- package/src/filter-bar/filter-bar.css +1306 -0
- package/src/filter-bar/filter-bar.tokens.json +78 -0
- package/src/form/form.css +218 -0
- package/src/form/form.tokens.json +32 -0
- package/src/fullscreen/fullscreen.css +376 -0
- package/src/fullscreen/fullscreen.tokens.json +50 -0
- package/src/grid/grid.css +173 -0
- package/src/grid/grid.tokens.json +20 -0
- package/src/highlight/highlight.css +135 -0
- package/src/highlight/highlight.tokens.json +16 -0
- package/src/hover-card/hover-card.css +93 -0
- package/src/hover-card/hover-card.tokens.json +17 -0
- package/src/icon/icon.css +136 -0
- package/src/icon/icon.tokens.json +14 -0
- package/src/image/image.css +449 -0
- package/src/image/image.tokens.json +27 -0
- package/src/import-export-center/import-export-center.css +1175 -0
- package/src/import-export-center/import-export-center.tokens.json +84 -0
- package/src/inline/inline.css +149 -0
- package/src/inline/inline.tokens.json +14 -0
- package/src/inline-message/inline-message.css +396 -0
- package/src/inline-message/inline-message.tokens.json +19 -0
- package/src/kbd/kbd.css +490 -0
- package/src/kbd/kbd.tokens.json +40 -0
- package/src/link/link.css +237 -0
- package/src/link/link.tokens.json +25 -0
- package/src/list/list.css +240 -0
- package/src/list/list.tokens.json +42 -0
- package/src/list-item/list-item.css +937 -0
- package/src/list-item/list-item.tokens.json +114 -0
- package/src/listbox/listbox.css +674 -0
- package/src/listbox/listbox.tokens.json +72 -0
- package/src/loading-overlay/loading-overlay.css +730 -0
- package/src/loading-overlay/loading-overlay.tokens.json +48 -0
- package/src/markdown/markdown.css +168 -0
- package/src/markdown/markdown.tokens.json +18 -0
- package/src/menu/menu.css +817 -0
- package/src/menu/menu.tokens.json +78 -0
- package/src/menubar/menubar.css +170 -0
- package/src/menubar/menubar.tokens.json +32 -0
- package/src/message/message.css +1453 -0
- package/src/message/message.tokens.json +85 -0
- package/src/message-scroller/message-scroller.css +371 -0
- package/src/message-scroller/message-scroller.tokens.json +47 -0
- package/src/multi-select/multi-select.css +1427 -0
- package/src/multi-select/multi-select.tokens.json +114 -0
- package/src/navigation-menu/navigation-menu.css +1029 -0
- package/src/navigation-menu/navigation-menu.tokens.json +70 -0
- package/src/notification-center/notification-center.css +856 -0
- package/src/notification-center/notification-center.tokens.json +84 -0
- package/src/number-field/number-field.css +794 -0
- package/src/number-field/number-field.tokens.json +80 -0
- package/src/otp-input/otp-input.css +525 -0
- package/src/otp-input/otp-input.tokens.json +69 -0
- package/src/page/page.css +179 -0
- package/src/page/page.tokens.json +20 -0
- package/src/page-header/page-header.css +1181 -0
- package/src/page-header/page-header.tokens.json +71 -0
- package/src/pagination/pagination.css +500 -0
- package/src/pagination/pagination.tokens.json +56 -0
- package/src/popover/popover.css +526 -0
- package/src/popover/popover.tokens.json +60 -0
- package/src/progress-indicator/progress-indicator.css +1584 -0
- package/src/progress-indicator/progress-indicator.tokens.json +50 -0
- package/src/prompt-composer/prompt-composer.css +680 -0
- package/src/prompt-composer/prompt-composer.tokens.json +99 -0
- package/src/prose/prose.css +733 -0
- package/src/prose/prose.tokens.json +79 -0
- package/src/radio-group/radio-group.css +778 -0
- package/src/radio-group/radio-group.tokens.json +103 -0
- package/src/rating/rating.css +1071 -0
- package/src/rating/rating.tokens.json +88 -0
- package/src/result-state/result-state.css +980 -0
- package/src/result-state/result-state.tokens.json +63 -0
- package/src/runtime-properties.mjs +321 -0
- package/src/saved-views/saved-views.css +394 -0
- package/src/saved-views/saved-views.tokens.json +41 -0
- package/src/scroll-area/scroll-area.css +481 -0
- package/src/scroll-area/scroll-area.tokens.json +15 -0
- package/src/section/section.css +177 -0
- package/src/section/section.tokens.json +39 -0
- package/src/segmented-control/segmented-control.css +564 -0
- package/src/segmented-control/segmented-control.tokens.json +67 -0
- package/src/select/select.css +1593 -0
- package/src/select/select.tokens.json +110 -0
- package/src/side-navigation/side-navigation.css +1096 -0
- package/src/side-navigation/side-navigation.tokens.json +87 -0
- package/src/skeleton/skeleton.css +431 -0
- package/src/skeleton/skeleton.tokens.json +29 -0
- package/src/slider/slider.css +792 -0
- package/src/slider/slider.tokens.json +75 -0
- package/src/sparkline/sparkline.css +282 -0
- package/src/sparkline/sparkline.tokens.json +45 -0
- package/src/spinner/spinner.css +224 -0
- package/src/spinner/spinner.tokens.json +8 -0
- package/src/split-button/split-button.css +253 -0
- package/src/split-button/split-button.tokens.json +12 -0
- package/src/splitter/splitter.css +336 -0
- package/src/splitter/splitter.tokens.json +24 -0
- package/src/stack/stack.css +128 -0
- package/src/stack/stack.tokens.json +14 -0
- package/src/stat-card/stat-card.css +641 -0
- package/src/stat-card/stat-card.tokens.json +95 -0
- package/src/status-indicator/status-indicator.css +481 -0
- package/src/status-indicator/status-indicator.tokens.json +38 -0
- package/src/stepper/stepper.css +629 -0
- package/src/stepper/stepper.tokens.json +72 -0
- package/src/switch/switch.css +703 -0
- package/src/switch/switch.tokens.json +75 -0
- package/src/table/table.css +1482 -0
- package/src/table/table.tokens.json +69 -0
- package/src/table-of-contents/table-of-contents.css +533 -0
- package/src/table-of-contents/table-of-contents.tokens.json +53 -0
- package/src/tabs/tabs.css +998 -0
- package/src/tabs/tabs.tokens.json +82 -0
- package/src/tag/tag.css +768 -0
- package/src/tag/tag.tokens.json +85 -0
- package/src/tags-input/tags-input.css +757 -0
- package/src/tags-input/tags-input.tokens.json +84 -0
- package/src/text-field/text-field.css +900 -0
- package/src/text-field/text-field.tokens.json +87 -0
- package/src/textarea/textarea.css +365 -0
- package/src/textarea/textarea.tokens.json +59 -0
- package/src/time-field/time-field.css +719 -0
- package/src/time-field/time-field.tokens.json +86 -0
- package/src/time-picker/time-picker.css +665 -0
- package/src/time-picker/time-picker.tokens.json +66 -0
- package/src/time-range-picker/time-range-picker.css +1287 -0
- package/src/time-range-picker/time-range-picker.tokens.json +134 -0
- package/src/timeline/timeline.css +1596 -0
- package/src/timeline/timeline.tokens.json +96 -0
- package/src/toast/toast.css +943 -0
- package/src/toast/toast.tokens.json +90 -0
- package/src/toggle/toggle.css +290 -0
- package/src/toggle/toggle.tokens.json +54 -0
- package/src/toggle-group/toggle-group.css +463 -0
- package/src/toggle-group/toggle-group.tokens.json +54 -0
- package/src/toolbar/toolbar.css +434 -0
- package/src/toolbar/toolbar.tokens.json +49 -0
- package/src/tooltip/tooltip.css +368 -0
- package/src/tooltip/tooltip.tokens.json +39 -0
- package/src/top-navigation/top-navigation.css +1287 -0
- package/src/top-navigation/top-navigation.tokens.json +91 -0
- package/src/tour/tour.css +680 -0
- package/src/tour/tour.tokens.json +67 -0
- package/src/transfer/transfer.css +571 -0
- package/src/transfer/transfer.tokens.json +49 -0
- package/src/tree/tree.css +1000 -0
- package/src/tree/tree.tokens.json +80 -0
- package/src/typography/typography.css +211 -0
- package/src/typography/typography.tokens.json +31 -0
- package/src/upload/upload.css +1706 -0
- package/src/upload/upload.tokens.json +123 -0
- package/src/visually-hidden/visually-hidden.css +52 -0
- package/src/visually-hidden/visually-hidden.tokens.json +1 -0
- package/src/wizard/wizard.css +740 -0
- package/src/wizard/wizard.tokens.json +63 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* A link is text that goes somewhere. It is not a control surface: it has no
|
|
4
|
+
* height, no padding and no fill, it takes the type of the text around it,
|
|
5
|
+
* and `button` owns the anchor that wants the action surface — `ButtonLink`,
|
|
6
|
+
* the same family, the same geometry.
|
|
7
|
+
*
|
|
8
|
+
* Three values carry every variant: the colour at rest, the colour under the
|
|
9
|
+
* pointer, and the colour while it is being pressed. A fourth, `--_strong`,
|
|
10
|
+
* is the maximum-contrast text colour of whatever context the link sits in,
|
|
11
|
+
* and it is what hover mixes toward. That indirection is the whole reason
|
|
12
|
+
* this family was rebuilt: the shipped stylesheet painted hover with
|
|
13
|
+
* `--slotted-tone-accent-solid-hover`, which is a fill colour. In the light
|
|
14
|
+
* scheme a fill that darkens is also a text colour that darkens, so the
|
|
15
|
+
* defect never showed. In the dark scheme that token is `#1d4ed8` over a
|
|
16
|
+
* `#131316` ground, and hovering a link made it harder to read than leaving
|
|
17
|
+
* it alone. A ramp built for fills cannot be a ramp for text, and the tone
|
|
18
|
+
* scale has no `text-hover` role to reach for; mixing toward the colour the
|
|
19
|
+
* theme already holds to the highest ratio in each scheme cannot fail the
|
|
20
|
+
* same way.
|
|
21
|
+
*/
|
|
22
|
+
[data-ui='link'] {
|
|
23
|
+
--_strong: var(--slotted-text, CanvasText);
|
|
24
|
+
--_rest: var(--slotted-link-color, var(--slotted-tone-accent-text, LinkText));
|
|
25
|
+
--_hover: var(
|
|
26
|
+
--slotted-link-color-hover,
|
|
27
|
+
color-mix(in oklab, var(--_rest) 65%, var(--_strong))
|
|
28
|
+
);
|
|
29
|
+
--_active: var(
|
|
30
|
+
--slotted-link-color-active,
|
|
31
|
+
color-mix(in oklab, var(--_rest) 35%, var(--_strong))
|
|
32
|
+
);
|
|
33
|
+
--_visited: var(
|
|
34
|
+
--slotted-link-color-visited,
|
|
35
|
+
color-mix(in oklab, var(--_rest) 40%, var(--slotted-text-muted, GrayText))
|
|
36
|
+
);
|
|
37
|
+
/**
|
|
38
|
+
* The underline at rest is lighter than the text it belongs to, and
|
|
39
|
+
* reaches full strength from hover onward. That is what gives `inverse` a
|
|
40
|
+
* hover at all: on a solid surface the text colour is already the
|
|
41
|
+
* strongest one available, so the underline is the only property left that
|
|
42
|
+
* can answer the pointer.
|
|
43
|
+
*/
|
|
44
|
+
--_underline: var(
|
|
45
|
+
--slotted-link-underline-color,
|
|
46
|
+
color-mix(in oklab, currentColor 55%, transparent)
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
border-radius: var(--slotted-link-radius, var(--slotted-control-radius, 4px));
|
|
50
|
+
color: var(--_rest);
|
|
51
|
+
/**
|
|
52
|
+
* A link inside a `Stack`, a grid cell or any other flex container is
|
|
53
|
+
* blockified by the layout — `display: inline` is not a choice a flex item
|
|
54
|
+
* gets to keep — and a blockified link stretches to the full inline size of
|
|
55
|
+
* the column. Nothing about the text changes, and then the focus ring is
|
|
56
|
+
* drawn around the whole column instead of around the words, which is what
|
|
57
|
+
* the first focus capture of this family showed. Shrinking to the content
|
|
58
|
+
* is inert for an inline link, where inline-size does not apply at all.
|
|
59
|
+
*/
|
|
60
|
+
inline-size: fit-content;
|
|
61
|
+
/**
|
|
62
|
+
* A destination pasted as the link text is one unbroken token. Without
|
|
63
|
+
* this it widens the column it sits in rather than wrapping inside it,
|
|
64
|
+
* which is what a 240-pixel capture shows and a paragraph of ordinary
|
|
65
|
+
* prose never does.
|
|
66
|
+
*/
|
|
67
|
+
overflow-wrap: anywhere;
|
|
68
|
+
text-decoration-color: var(--_underline);
|
|
69
|
+
text-decoration-line: underline;
|
|
70
|
+
text-decoration-thickness: var(--slotted-link-underline-thickness, from-font);
|
|
71
|
+
text-underline-offset: var(--slotted-link-underline-offset, 0.15em);
|
|
72
|
+
transition:
|
|
73
|
+
color var(--slotted-duration-short) var(--slotted-easing-standard),
|
|
74
|
+
text-decoration-color var(--slotted-duration-short) var(--slotted-easing-standard);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The link that takes the colour of the text it sits in — a title inside a
|
|
79
|
+
* card, a name inside a table row — and reaches the accent under the
|
|
80
|
+
* pointer. Fluent calls it `subtle`, Primer `muted`, Polaris `monochrome`,
|
|
81
|
+
* and all three describe the same two colours.
|
|
82
|
+
*/
|
|
83
|
+
[data-ui='link'][data-variant='neutral'] {
|
|
84
|
+
--_rest: var(--slotted-link-color, currentColor);
|
|
85
|
+
--_hover: var(--slotted-link-color-hover, var(--slotted-tone-accent-text, LinkText));
|
|
86
|
+
--_active: var(
|
|
87
|
+
--slotted-link-color-active,
|
|
88
|
+
color-mix(in oklab, var(--slotted-tone-accent-text, LinkText) 65%, var(--_strong))
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The link on a solid or inverse surface. The strong colour changes with the
|
|
94
|
+
* ground, so hover has nowhere further to go and the underline carries the
|
|
95
|
+
* state on its own.
|
|
96
|
+
*/
|
|
97
|
+
[data-ui='link'][data-variant='inverse'] {
|
|
98
|
+
--_strong: var(--slotted-text-inverse, Canvas);
|
|
99
|
+
--_rest: var(--slotted-link-color, var(--slotted-text-inverse, Canvas));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* ── Underline axis ─────────────────────────────────────────────────────
|
|
103
|
+
*
|
|
104
|
+
* `always` is the default because colour alone does not distinguish a link:
|
|
105
|
+
* the accent text colour clears 4.5:1 against the surface and not 3:1
|
|
106
|
+
* against the body text beside it, which is the ratio a link with no second
|
|
107
|
+
* cue has to meet. The other two values are for a link that stands alone,
|
|
108
|
+
* where there is no sentence for it to disappear into.
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
[data-ui='link'][data-underline='hover'],
|
|
112
|
+
[data-ui='link'][data-underline='none'] {
|
|
113
|
+
text-decoration-line: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
[data-ui='link'][data-underline='hover']:not([data-disabled]):hover {
|
|
117
|
+
text-decoration-line: underline;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A keyboard has no hover, so focus is where a deferred underline is owed.
|
|
122
|
+
* `none` is left alone: it says the underline does not exist, not that it is
|
|
123
|
+
* waiting for something.
|
|
124
|
+
*/
|
|
125
|
+
[data-ui='link'][data-underline='hover']:focus-visible {
|
|
126
|
+
text-decoration-line: underline;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* ── Visited ────────────────────────────────────────────────────────────
|
|
130
|
+
*
|
|
131
|
+
* Opt-in, and declared before the interaction rules so hover still answers a
|
|
132
|
+
* link the reader has already followed. `:visited` accepts colour and
|
|
133
|
+
* nothing else — the restriction is deliberate, and it is also why no test
|
|
134
|
+
* in this repository can read this rule back.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
[data-ui='link'][data-visited]:visited {
|
|
138
|
+
color: var(--_visited);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* ── Hover and press, held back for disabled ────────────────────────────── */
|
|
142
|
+
|
|
143
|
+
[data-ui='link']:not([data-disabled]):hover {
|
|
144
|
+
--_underline: currentColor;
|
|
145
|
+
|
|
146
|
+
color: var(--_hover);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
[data-ui='link']:not([data-disabled]):active {
|
|
150
|
+
--_underline: currentColor;
|
|
151
|
+
|
|
152
|
+
color: var(--_active);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* ── Focus ──────────────────────────────────────────────────────────────
|
|
156
|
+
*
|
|
157
|
+
* The ring hugs the text at one pixel rather than the two a control uses: a
|
|
158
|
+
* link has no border for the ring to clear, and on a line of prose a wider
|
|
159
|
+
* offset reaches into the line above.
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
[data-ui='link']:focus-visible {
|
|
163
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
164
|
+
outline-offset: var(--slotted-link-focus-ring-offset, 1px);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ── Disabled ───────────────────────────────────────────────────────────
|
|
168
|
+
*
|
|
169
|
+
* `[data-disabled]` rather than a pseudo-class, because an anchor has none:
|
|
170
|
+
* what makes the link unavailable is the destination the binding did not
|
|
171
|
+
* render, plus `aria-disabled`. The underline stays, so the element still
|
|
172
|
+
* reads as a link that is not available rather than as plain text.
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
[data-ui='link'][data-disabled] {
|
|
176
|
+
color: var(--slotted-link-color-disabled, var(--slotted-disabled-foreground, GrayText));
|
|
177
|
+
cursor: not-allowed;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ── The external marker ────────────────────────────────────────────────
|
|
181
|
+
*
|
|
182
|
+
* The arrow is the `Glyph` element inside an `icon` box, so it is the colour
|
|
183
|
+
* of the link at every step of the ramp, in every scheme and under forced
|
|
184
|
+
* colours, and mirrors in a right-to-left document through the box's own
|
|
185
|
+
* `directional`. A character would be a font's opinion of an arrow.
|
|
186
|
+
*
|
|
187
|
+
* The binding writes a word joiner before this element — U+2060, the
|
|
188
|
+
* zero-width character whose whole purpose is to forbid a line break without
|
|
189
|
+
* occupying anything — so the glyph cannot wrap onto the next line without
|
|
190
|
+
* the word it belongs to. A no-break space would do the same job and carry a
|
|
191
|
+
* full word space with it, and "published schedule ↗" then reads as three
|
|
192
|
+
* words rather than a link and its marker. The distance is a token instead.
|
|
193
|
+
*
|
|
194
|
+
* The part stays an inline wrapper around the box: the gap is an inline
|
|
195
|
+
* margin, and the box inside sets its own size and optical alignment from
|
|
196
|
+
* `--slotted-icon-size`, which the part states at the size of the text.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
[data-ui='link'] [data-part='external-icon'] {
|
|
200
|
+
--slotted-icon-size: var(--slotted-link-external-icon-size, 1em);
|
|
201
|
+
|
|
202
|
+
margin-inline-start: var(--slotted-link-external-icon-gap, 0.15em);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* ── The current link ───────────────────────────────────────────────────
|
|
206
|
+
*
|
|
207
|
+
* Painted from the platform's own attribute, which is the one a React
|
|
208
|
+
* consumer writes by hand and the one Angular's `routerLinkActive` writes
|
|
209
|
+
* through `ariaCurrentWhenActive`. A mirrored `data-current` would need the
|
|
210
|
+
* family to observe an attribute a router sets at runtime, and would paint
|
|
211
|
+
* nothing at all for the consumer who never adopted the mirror.
|
|
212
|
+
*
|
|
213
|
+
* The destination of a current link is the page the reader is already on, so
|
|
214
|
+
* it stops being an invitation and takes the body colour. The underline
|
|
215
|
+
* stays, because it is still a link and colour alone would not say so. The
|
|
216
|
+
* weight does not change: a nav item that thickens shifts every item beside
|
|
217
|
+
* it.
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
[data-ui='link'][aria-current]:not([aria-current='false']) {
|
|
221
|
+
--_rest: var(--slotted-link-color-current, var(--slotted-text, CanvasText));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ── Forced colours ─────────────────────────────────────────────────────
|
|
225
|
+
*
|
|
226
|
+
* The theme remaps every token it owns, so this block covers only what the
|
|
227
|
+
* family paints itself: an underline the axis may have taken away, where a
|
|
228
|
+
* flattened palette leaves a link with nothing to be recognized by. The
|
|
229
|
+
* external marker is stroked with `currentColor` and follows the link.
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
@media (forced-colors: active) {
|
|
233
|
+
[data-ui='link'] {
|
|
234
|
+
text-decoration-line: underline;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[
|
|
2
|
+
"--slotted-control-radius",
|
|
3
|
+
"--slotted-disabled-foreground",
|
|
4
|
+
"--slotted-duration-short",
|
|
5
|
+
"--slotted-easing-standard",
|
|
6
|
+
"--slotted-focus-ring-color",
|
|
7
|
+
"--slotted-focus-ring-width",
|
|
8
|
+
"--slotted-link-color",
|
|
9
|
+
"--slotted-link-color-active",
|
|
10
|
+
"--slotted-link-color-current",
|
|
11
|
+
"--slotted-link-color-disabled",
|
|
12
|
+
"--slotted-link-color-hover",
|
|
13
|
+
"--slotted-link-color-visited",
|
|
14
|
+
"--slotted-link-external-icon-gap",
|
|
15
|
+
"--slotted-link-external-icon-size",
|
|
16
|
+
"--slotted-link-focus-ring-offset",
|
|
17
|
+
"--slotted-link-radius",
|
|
18
|
+
"--slotted-link-underline-color",
|
|
19
|
+
"--slotted-link-underline-offset",
|
|
20
|
+
"--slotted-link-underline-thickness",
|
|
21
|
+
"--slotted-text",
|
|
22
|
+
"--slotted-text-inverse",
|
|
23
|
+
"--slotted-text-muted",
|
|
24
|
+
"--slotted-tone-accent-text"
|
|
25
|
+
]
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* ── The set ────────────────────────────────────────────────────────────
|
|
4
|
+
*
|
|
5
|
+
* A vertical run of related rows. The rows are `list-item`, a family of its
|
|
6
|
+
* own, and **no selector here reaches `[data-ui='list-item']`** — the rule
|
|
7
|
+
* `accordion` and `collapsible` set for the same relationship. What the set
|
|
8
|
+
* decides it hands to each row through the binding, as a `data-` attribute
|
|
9
|
+
* the row's own stylesheet reads.
|
|
10
|
+
*
|
|
11
|
+
* The one thing the two sheets share is a counter name. `slotted-list-item`
|
|
12
|
+
* is reset here, on the root and on every nested group, and incremented by
|
|
13
|
+
* the row; a counter is not a selector, so neither family's DOM becomes part
|
|
14
|
+
* of the other's contract.
|
|
15
|
+
*
|
|
16
|
+
* The native marker is gone in every configuration, because a row is a
|
|
17
|
+
* content box beside its independent targets and CSS has no `display` that is
|
|
18
|
+
* both `list-item` and a grid. The bindings therefore write `role="list"`
|
|
19
|
+
* here and on `section-list`, which is what Safari and VoiceOver need once
|
|
20
|
+
* the marker is removed.
|
|
21
|
+
*/
|
|
22
|
+
[data-ui='list'][data-part='root'],
|
|
23
|
+
[data-ui='list'] [data-part='section-list'] {
|
|
24
|
+
/* The row's own number. The set opens the count; each group opens its own,
|
|
25
|
+
so a numbered list of groups restarts rather than running through. */
|
|
26
|
+
counter-reset: slotted-list-item;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
list-style: none;
|
|
30
|
+
margin-block: 0;
|
|
31
|
+
margin-inline: 0;
|
|
32
|
+
/* A row's text column can only shrink below its content if every box above
|
|
33
|
+
it can, and a flex item's default `min-inline-size: auto` stops at the
|
|
34
|
+
longest word. Without this a title that is one unbroken token widens the
|
|
35
|
+
whole list instead of breaking inside the row. */
|
|
36
|
+
min-inline-size: 0;
|
|
37
|
+
padding-inline: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[data-ui='list'][data-part='root'] {
|
|
41
|
+
/* The distance between rows, and it is spent only by `separated`. The other
|
|
42
|
+
three variants separate rows with a line or with nothing, so a gap there
|
|
43
|
+
would be space the reader cannot account for. */
|
|
44
|
+
--_gap: var(--slotted-list-gap, var(--slotted-space-3, 0.375rem));
|
|
45
|
+
/* The frame `framed` draws, and the ground the sticky group heading needs.
|
|
46
|
+
Both are declared at the root so a theme retunes them once. */
|
|
47
|
+
--_frame-color: var(--slotted-list-border-color, var(--slotted-border-subtle, ButtonBorder));
|
|
48
|
+
--_frame-width: var(--slotted-list-border-width, var(--slotted-border-width-thin, 1px));
|
|
49
|
+
--_frame-radius: var(--slotted-list-radius, var(--slotted-radius-md, 6px));
|
|
50
|
+
--_surface: var(--slotted-list-background, var(--slotted-surface, Canvas));
|
|
51
|
+
/* The group heading's type and colour. It is a heading in the document,
|
|
52
|
+
so it takes the muted ink rather than a tone: a coloured heading over a
|
|
53
|
+
neutral list reads as a status the group does not have. */
|
|
54
|
+
--_section-color: var(--slotted-list-section-color, var(--slotted-text-muted, GrayText));
|
|
55
|
+
--_section-font-size: var(
|
|
56
|
+
--slotted-list-section-font-size,
|
|
57
|
+
var(--slotted-font-size-xs, 0.75rem)
|
|
58
|
+
);
|
|
59
|
+
--_section-weight: var(
|
|
60
|
+
--slotted-list-section-font-weight,
|
|
61
|
+
var(--slotted-font-weight-semibold, 600)
|
|
62
|
+
);
|
|
63
|
+
--_section-inset-block: var(
|
|
64
|
+
--slotted-list-section-padding-block,
|
|
65
|
+
var(--slotted-space-4, 0.5rem)
|
|
66
|
+
);
|
|
67
|
+
--_row-inset-inline: var(
|
|
68
|
+
--slotted-list-padding-inline,
|
|
69
|
+
var(--slotted-control-padding-inline-md, 13px)
|
|
70
|
+
);
|
|
71
|
+
--_empty-color: var(--slotted-list-empty-color, var(--slotted-text-muted, GrayText));
|
|
72
|
+
--_empty-inset: var(--slotted-list-empty-padding, var(--slotted-space-8, 1.5rem));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Size is this list's own step and density is the application's. The two
|
|
77
|
+
* scale different things — density retunes every control on the page, size
|
|
78
|
+
* says how much room this one list gives a row — so a dense inbox and a
|
|
79
|
+
* roomy settings list stand on the same page without either of them lying
|
|
80
|
+
* about the density.
|
|
81
|
+
*/
|
|
82
|
+
[data-ui='list'][data-part='root'][data-size='sm'] {
|
|
83
|
+
--_gap: var(--slotted-list-gap-sm, var(--slotted-space-2, 0.25rem));
|
|
84
|
+
--_section-inset-block: var(
|
|
85
|
+
--slotted-list-section-padding-block-sm,
|
|
86
|
+
var(--slotted-space-3, 0.375rem)
|
|
87
|
+
);
|
|
88
|
+
--_row-inset-inline: var(
|
|
89
|
+
--slotted-list-padding-inline-sm,
|
|
90
|
+
var(--slotted-control-padding-inline-sm, 10px)
|
|
91
|
+
);
|
|
92
|
+
--_empty-inset: var(--slotted-list-empty-padding-sm, var(--slotted-space-6, 1rem));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[data-ui='list'][data-part='root'][data-size='lg'] {
|
|
96
|
+
--_gap: var(--slotted-list-gap-lg, var(--slotted-space-4, 0.5rem));
|
|
97
|
+
--_section-inset-block: var(
|
|
98
|
+
--slotted-list-section-padding-block-lg,
|
|
99
|
+
var(--slotted-space-5, 0.75rem)
|
|
100
|
+
);
|
|
101
|
+
--_row-inset-inline: var(
|
|
102
|
+
--slotted-list-padding-inline-lg,
|
|
103
|
+
var(--slotted-control-padding-inline-lg, 16px)
|
|
104
|
+
);
|
|
105
|
+
--_empty-inset: var(--slotted-list-empty-padding-lg, var(--slotted-space-9, 2rem));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* ── How rows are told apart ────────────────────────────────────────────
|
|
110
|
+
*
|
|
111
|
+
* Four words, and they are `accordion`'s four so that two families cannot
|
|
112
|
+
* mean different things by one of them. Only two of them draw anything here:
|
|
113
|
+
* the line between rows and the surface of a separated row belong to the row,
|
|
114
|
+
* which is the only element that knows whether it is first, last or alone.
|
|
115
|
+
*
|
|
116
|
+
* `plain` and `ruled` draw nothing on the set.
|
|
117
|
+
*/
|
|
118
|
+
[data-ui='list'][data-part='root'][data-variant='framed'] {
|
|
119
|
+
background-color: var(--_surface);
|
|
120
|
+
border: var(--_frame-width) solid var(--_frame-color);
|
|
121
|
+
border-radius: var(--_frame-radius);
|
|
122
|
+
/* The frame clips its own corners, so the first and last rows do not paint
|
|
123
|
+
a square hover fill over a rounded edge. `clip` rather than `hidden`: the
|
|
124
|
+
set is not a scroll container, and `hidden` would silently make it one. */
|
|
125
|
+
overflow: clip;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[data-ui='list'][data-part='root'][data-variant='separated'] {
|
|
129
|
+
row-gap: var(--_gap);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A group inside the set. It is an `li` holding a heading and a nested list,
|
|
134
|
+
* which is the grouping HTML already has; MUI, Angular Material, Primer and
|
|
135
|
+
* React Aria each leave the heading loose among the rows instead, so a reader
|
|
136
|
+
* hears a heading inside a set rather than a set with a name.
|
|
137
|
+
*/
|
|
138
|
+
[data-ui='list'] [data-part='section'] {
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
min-inline-size: 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* A separated set gaps its groups too, and a group gaps its own rows. Both
|
|
145
|
+
read the one distance the root declared. */
|
|
146
|
+
[data-ui='list'][data-variant='separated'] [data-part='section'],
|
|
147
|
+
[data-ui='list'][data-variant='separated'] [data-part='section-list'] {
|
|
148
|
+
row-gap: var(--_gap);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The group's name. It shares the row's inline inset so the heading and the
|
|
153
|
+
* titles under it stand in one column, which is the alignment that makes a
|
|
154
|
+
* grouped list read as one list rather than as several.
|
|
155
|
+
*/
|
|
156
|
+
[data-ui='list'] [data-part='section-label'] {
|
|
157
|
+
color: var(--_section-color);
|
|
158
|
+
font-size: var(--_section-font-size);
|
|
159
|
+
font-weight: var(--_section-weight);
|
|
160
|
+
letter-spacing: var(--slotted-list-section-letter-spacing, 0);
|
|
161
|
+
line-height: var(--slotted-line-height-sm, 1.45);
|
|
162
|
+
margin-block: 0;
|
|
163
|
+
min-inline-size: 0;
|
|
164
|
+
padding-block: var(--_section-inset-block);
|
|
165
|
+
/* The heading takes the row's own inline inset — the control padding scale,
|
|
166
|
+
not a space step — so the group's name and the titles under it stand in
|
|
167
|
+
one column. Reading a different scale left the two a pixel apart. */
|
|
168
|
+
padding-inline: var(--_row-inset-inline);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* `inset` is for a list dropped into a box that already pads its own content
|
|
173
|
+
* — a `card` body, a `dialog`. It takes the row's inline padding away so the
|
|
174
|
+
* content lines up with the box around it, and the heading gives up the same
|
|
175
|
+
* padding so the column holds.
|
|
176
|
+
*
|
|
177
|
+
* The fill and the rule still run edge to edge, which is the half MUI's
|
|
178
|
+
* `disableGutters` leaves out: it removes the padding and leaves the line
|
|
179
|
+
* inset, so a flush list draws a rule stopping short of the box it is in.
|
|
180
|
+
*/
|
|
181
|
+
[data-ui='list'][data-inset] [data-part='section-label'],
|
|
182
|
+
[data-ui='list'][data-inset] [data-part='empty'] {
|
|
183
|
+
padding-inline: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* A heading that stays while its own rows scroll past. MUI ships it and is
|
|
188
|
+
* the only surveyed source that does; composing it needs the family's ground
|
|
189
|
+
* and its stack level, and a consumer writing `position: sticky` alone gets a
|
|
190
|
+
* heading with rows showing through it.
|
|
191
|
+
*
|
|
192
|
+
* The ground is the set's surface rather than `transparent`, and the stack
|
|
193
|
+
* level is the library's own sticky step, so a heading never rises above an
|
|
194
|
+
* overlay that is above the page.
|
|
195
|
+
*/
|
|
196
|
+
[data-ui='list'] [data-part='section-label'][data-sticky] {
|
|
197
|
+
background-color: var(--_surface);
|
|
198
|
+
inset-block-start: 0;
|
|
199
|
+
position: sticky;
|
|
200
|
+
z-index: var(--slotted-z-index-sticky, 100);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* What the set says when it holds nothing. It is an `li`, so the reader hears
|
|
205
|
+
* "list, one item" and then the message; a message outside the `ul` leaves
|
|
206
|
+
* them with "list, zero items" and silence, and leaves the words outside the
|
|
207
|
+
* box a framed set paints.
|
|
208
|
+
*
|
|
209
|
+
* The family supplies the box, the height and the muted ink. The words are
|
|
210
|
+
* the page's, and `result-state` is what goes in here.
|
|
211
|
+
*/
|
|
212
|
+
[data-ui='list'] [data-part='empty'] {
|
|
213
|
+
align-items: center;
|
|
214
|
+
color: var(--_empty-color);
|
|
215
|
+
display: flex;
|
|
216
|
+
flex-direction: column;
|
|
217
|
+
justify-content: center;
|
|
218
|
+
min-inline-size: 0;
|
|
219
|
+
padding-block: var(--_empty-inset);
|
|
220
|
+
padding-inline: var(--_row-inset-inline);
|
|
221
|
+
text-align: center;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* ── Loading ────────────────────────────────────────────────────────────
|
|
226
|
+
*
|
|
227
|
+
* The binding writes `aria-busy="true"`, which ARIA 1.2 section 5.2.6 asks of
|
|
228
|
+
* a container whose required owned elements have not arrived yet. That is the
|
|
229
|
+
* capability; the picture is the page's.
|
|
230
|
+
*
|
|
231
|
+
* The family draws no spinner and no placeholder row. `skeleton` owns
|
|
232
|
+
* placeholder geometry and `progress-indicator` owns a spinner, and a second
|
|
233
|
+
* answer to either question is what `collapsible` already refused for a
|
|
234
|
+
* loading panel. What is left for the set is the pointer, which is the one
|
|
235
|
+
* signal that belongs to the box rather than to its content.
|
|
236
|
+
*/
|
|
237
|
+
[data-ui='list'][data-part='root'][data-loading] {
|
|
238
|
+
cursor: progress;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[
|
|
2
|
+
"--slotted-border-subtle",
|
|
3
|
+
"--slotted-border-width-thin",
|
|
4
|
+
"--slotted-control-padding-inline-lg",
|
|
5
|
+
"--slotted-control-padding-inline-md",
|
|
6
|
+
"--slotted-control-padding-inline-sm",
|
|
7
|
+
"--slotted-font-size-xs",
|
|
8
|
+
"--slotted-font-weight-semibold",
|
|
9
|
+
"--slotted-line-height-sm",
|
|
10
|
+
"--slotted-list-background",
|
|
11
|
+
"--slotted-list-border-color",
|
|
12
|
+
"--slotted-list-border-width",
|
|
13
|
+
"--slotted-list-empty-color",
|
|
14
|
+
"--slotted-list-empty-padding",
|
|
15
|
+
"--slotted-list-empty-padding-lg",
|
|
16
|
+
"--slotted-list-empty-padding-sm",
|
|
17
|
+
"--slotted-list-gap",
|
|
18
|
+
"--slotted-list-gap-lg",
|
|
19
|
+
"--slotted-list-gap-sm",
|
|
20
|
+
"--slotted-list-padding-inline",
|
|
21
|
+
"--slotted-list-padding-inline-lg",
|
|
22
|
+
"--slotted-list-padding-inline-sm",
|
|
23
|
+
"--slotted-list-radius",
|
|
24
|
+
"--slotted-list-section-color",
|
|
25
|
+
"--slotted-list-section-font-size",
|
|
26
|
+
"--slotted-list-section-font-weight",
|
|
27
|
+
"--slotted-list-section-letter-spacing",
|
|
28
|
+
"--slotted-list-section-padding-block",
|
|
29
|
+
"--slotted-list-section-padding-block-lg",
|
|
30
|
+
"--slotted-list-section-padding-block-sm",
|
|
31
|
+
"--slotted-radius-md",
|
|
32
|
+
"--slotted-space-2",
|
|
33
|
+
"--slotted-space-3",
|
|
34
|
+
"--slotted-space-4",
|
|
35
|
+
"--slotted-space-5",
|
|
36
|
+
"--slotted-space-6",
|
|
37
|
+
"--slotted-space-8",
|
|
38
|
+
"--slotted-space-9",
|
|
39
|
+
"--slotted-surface",
|
|
40
|
+
"--slotted-text-muted",
|
|
41
|
+
"--slotted-z-index-sticky"
|
|
42
|
+
]
|