@lumiose/ui 0.0.0-stage → 0.1.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 +53 -2
- package/dist/accordion/accordion.css +20 -0
- package/dist/accordion/accordion.script.ts +66 -0
- package/dist/accordion/accordion.tsx +288 -0
- package/dist/animation/animation.ts +34 -0
- package/dist/autocomplete/autocomplete.tsx +239 -0
- package/dist/avatar/avatar.css +54 -0
- package/dist/avatar/avatar.script.ts +96 -0
- package/dist/avatar/avatar.tsx +110 -0
- package/dist/button/button.script.ts +35 -0
- package/dist/button/button.tsx +40 -0
- package/dist/checkbox/checkbox.script.ts +225 -0
- package/dist/checkbox/checkbox.tsx +156 -0
- package/dist/checkbox/context.ts +17 -0
- package/dist/checkbox-group/checkbox-group.tsx +111 -0
- package/dist/collapsible/collapsible.css +12 -0
- package/dist/collapsible/collapsible.script.ts +7 -0
- package/dist/collapsible/collapsible.tsx +153 -0
- package/dist/collapsible/panel.ts +115 -0
- package/dist/combobox/combobox.css +37 -0
- package/dist/combobox/combobox.script.ts +974 -0
- package/dist/combobox/combobox.tsx +556 -0
- package/dist/combobox/context.ts +46 -0
- package/dist/context-menu/context-menu.css +16 -0
- package/dist/context-menu/context-menu.script.ts +172 -0
- package/dist/context-menu/context-menu.tsx +178 -0
- package/dist/dialog/dialog.css +35 -0
- package/dist/dialog/dialog.script.ts +269 -0
- package/dist/dialog/dialog.tsx +214 -0
- package/dist/drawer/drawer.css +38 -0
- package/dist/drawer/drawer.script.ts +207 -0
- package/dist/drawer/drawer.tsx +113 -0
- package/dist/field/context.ts +156 -0
- package/dist/field/field.css +16 -0
- package/dist/field/field.script.ts +422 -0
- package/dist/field/field.tsx +465 -0
- package/dist/fieldset/fieldset.tsx +41 -0
- package/dist/form/form.tsx +50 -0
- package/dist/form/native.ts +21 -0
- package/dist/form/reset.ts +53 -0
- package/dist/index.ts +261 -0
- package/dist/input/input.tsx +67 -0
- package/dist/layer/layer.ts +191 -0
- package/dist/locale/digits.ts +21 -0
- package/dist/menu/menu.css +22 -0
- package/dist/menu/menu.script.ts +591 -0
- package/dist/menu/menu.tsx +520 -0
- package/dist/menubar/menubar.css +16 -0
- package/dist/menubar/menubar.script.ts +195 -0
- package/dist/menubar/menubar.tsx +67 -0
- package/dist/meter/meter.tsx +134 -0
- package/dist/navigation-menu/navigation-menu.css +14 -0
- package/dist/navigation-menu/navigation-menu.script.ts +466 -0
- package/dist/navigation-menu/navigation-menu.tsx +266 -0
- package/dist/number-field/format.ts +70 -0
- package/dist/number-field/number-field.css +38 -0
- package/dist/number-field/number-field.script.ts +490 -0
- package/dist/number-field/number-field.tsx +403 -0
- package/dist/otp-field/otp-field.css +45 -0
- package/dist/otp-field/otp-field.script.ts +330 -0
- package/dist/otp-field/otp-field.tsx +320 -0
- package/dist/placement/place.ts +148 -0
- package/dist/placement/placement.css +155 -0
- package/dist/placement/placement.ts +60 -0
- package/dist/popover/hover.ts +178 -0
- package/dist/popover/popover.css +20 -0
- package/dist/popover/popover.script.ts +256 -0
- package/dist/popover/popover.tsx +317 -0
- package/dist/preview-card/preview-card.css +7 -0
- package/dist/preview-card/preview-card.script.ts +136 -0
- package/dist/preview-card/preview-card.tsx +128 -0
- package/dist/progress/progress.tsx +155 -0
- package/dist/progress/value.ts +23 -0
- package/dist/radio-group/radio-group.tsx +156 -0
- package/dist/scroll-area/scroll-area.css +72 -0
- package/dist/scroll-area/scroll-area.script.ts +281 -0
- package/dist/scroll-area/scroll-area.tsx +118 -0
- package/dist/select/select.css +25 -0
- package/dist/select/select.tsx +171 -0
- package/dist/separator/separator.css +12 -0
- package/dist/separator/separator.tsx +38 -0
- package/dist/slider/format.ts +33 -0
- package/dist/slider/slider.css +93 -0
- package/dist/slider/slider.script.ts +355 -0
- package/dist/slider/slider.tsx +374 -0
- package/dist/styles.css +30 -0
- package/dist/switch/switch.tsx +92 -0
- package/dist/tabs/tabs.css +54 -0
- package/dist/tabs/tabs.script.ts +225 -0
- package/dist/tabs/tabs.tsx +272 -0
- package/dist/themes/default.css +2111 -0
- package/dist/toast/command.ts +3 -0
- package/dist/toast/toast.css +68 -0
- package/dist/toast/toast.script.ts +516 -0
- package/dist/toast/toast.tsx +432 -0
- package/dist/toggle/context.ts +16 -0
- package/dist/toggle/toggle.tsx +99 -0
- package/dist/toggle-group/toggle-group.script.ts +166 -0
- package/dist/toggle-group/toggle-group.tsx +117 -0
- package/dist/toolbar/context.ts +18 -0
- package/dist/toolbar/toolbar.css +12 -0
- package/dist/toolbar/toolbar.script.ts +123 -0
- package/dist/toolbar/toolbar.tsx +180 -0
- package/dist/tooltip/tooltip.css +8 -0
- package/dist/tooltip/tooltip.script.ts +222 -0
- package/dist/tooltip/tooltip.tsx +149 -0
- package/docs/README.md +174 -0
- package/docs/accordion.md +208 -0
- package/docs/autocomplete.md +161 -0
- package/docs/avatar.md +198 -0
- package/docs/button.md +98 -0
- package/docs/checkbox-group.md +112 -0
- package/docs/checkbox.md +133 -0
- package/docs/collapsible.md +165 -0
- package/docs/combobox.md +369 -0
- package/docs/context-menu.md +197 -0
- package/docs/dialog.md +256 -0
- package/docs/drawer.md +204 -0
- package/docs/field.md +295 -0
- package/docs/fieldset.md +92 -0
- package/docs/form.md +131 -0
- package/docs/input.md +87 -0
- package/docs/installation.md +65 -0
- package/docs/llms-full.txt +6923 -0
- package/docs/llms.txt +53 -0
- package/docs/menu.md +365 -0
- package/docs/menubar.md +186 -0
- package/docs/meter.md +103 -0
- package/docs/navigation-menu.md +257 -0
- package/docs/number-field.md +181 -0
- package/docs/otp-field.md +160 -0
- package/docs/popover.md +271 -0
- package/docs/preview-card.md +130 -0
- package/docs/progress.md +115 -0
- package/docs/radio-group.md +127 -0
- package/docs/scroll-area.md +147 -0
- package/docs/select.md +236 -0
- package/docs/separator.md +116 -0
- package/docs/slider.md +184 -0
- package/docs/switch.md +98 -0
- package/docs/tabs.md +254 -0
- package/docs/theming.md +132 -0
- package/docs/toast.md +311 -0
- package/docs/toggle-group.md +119 -0
- package/docs/toggle.md +94 -0
- package/docs/toolbar.md +138 -0
- package/docs/tooltip.md +128 -0
- package/package.json +102 -3
|
@@ -0,0 +1,2111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @lumiose/ui's default theme (decision-62): opt-in, for demos, getting started and the docs. It
|
|
3
|
+
* styles the classes below, which you put on the parts through their `class` prop, and nothing
|
|
4
|
+
* else. Every colour, radius and ring comes from a `--lu-` custom property named as in shadcn/ui,
|
|
5
|
+
* with light and dark values that follow the page's `color-scheme`. All of it sits in the
|
|
6
|
+
* `lu.theme` layer, above `lu.core`: any app CSS outside layers wins, so set a property on `:root`
|
|
7
|
+
* (or any subtree) to restyle everything.
|
|
8
|
+
*
|
|
9
|
+
* WCAG 2.2 AA (decision-62, doc-9 section 17), light / dark: every `-foreground` reaches 4.5:1 on
|
|
10
|
+
* its surface, muted text included (5.1 / 5.8 on --lu-muted, 5.6 / 6.9 on --lu-popover); field
|
|
11
|
+
* and control borders (--lu-input) and the focus ring 3:1 on the surfaces they sit on (3.3 / 3.1
|
|
12
|
+
* on --lu-muted; ring 5.2 / 7.0). --lu-border is for decoration only: it is not enough to outline
|
|
13
|
+
* a control. The ratios per pair are in TASK-392.
|
|
14
|
+
*
|
|
15
|
+
* .lu-button a button; data-variant="primary" | "destructive"
|
|
16
|
+
* .lu-dialog a Dialog.Popup: surface, backdrop, title (h2),
|
|
17
|
+
* description (p), footer
|
|
18
|
+
* .lu-popover a Popover.Popup: surface, title (h2), description (p),
|
|
19
|
+
* footer, a 4px gap to the trigger
|
|
20
|
+
* .lu-tooltip a Tooltip.Popup: inverted colours, a 6px gap
|
|
21
|
+
* .lu-tabs a Tabs.Root: the list, its tabs (the selected one
|
|
22
|
+
* underlined, by a sliding Tabs.Indicator when there is one)
|
|
23
|
+
* and the panels
|
|
24
|
+
* .lu-menu a Menu.Popup (submenus too): surface, items, checkbox
|
|
25
|
+
* and radio marks, separators, group labels
|
|
26
|
+
* .lu-combobox a Combobox.Root: the field (label, chips, input, trigger
|
|
27
|
+
* and clear buttons), the popup, options, groups, states
|
|
28
|
+
* .lu-field a Field.Root: label, description and errors in a column
|
|
29
|
+
* .lu-input an Input (Field.Control): a text field
|
|
30
|
+
* .lu-fieldset a Fieldset.Root, CheckboxGroup or RadioGroup: legend
|
|
31
|
+
* and items in a column
|
|
32
|
+
* .lu-checkbox, .lu-radio a Checkbox.Root, a Radio.Root: box, mark, 24px target
|
|
33
|
+
* .lu-switch a Switch.Root: track and thumb
|
|
34
|
+
* .lu-select a Select.Root: a customizable select (control, picker,
|
|
35
|
+
* options, groups, separators)
|
|
36
|
+
* .lu-collapsible a Collapsible.Root: the trigger (a chevron) and the
|
|
37
|
+
* panel, its height animated
|
|
38
|
+
* .lu-accordion an Accordion.Root: items between borders, their triggers
|
|
39
|
+
* and panels, as for Collapsible
|
|
40
|
+
* .lu-toast-viewport a Toast.Viewport: a column at the bottom end
|
|
41
|
+
* .lu-toast a Toast.Root: surface, title (h2), description (p), the
|
|
42
|
+
* close button (Toast.Close); data-type="error"
|
|
43
|
+
* .lu-toggle a Toggle: a button with a pressed surface and bar
|
|
44
|
+
* .lu-toggle-group a ToggleGroup: its toggles in a row (or a column)
|
|
45
|
+
* .lu-progress, .lu-meter a Progress.Root, a Meter.Root: label, value and bar
|
|
46
|
+
* .lu-slider a Slider.Root: label, value, track, indicator, thumbs
|
|
47
|
+
* .lu-drawer a Drawer.Popup: a surface against its edge (a handle on
|
|
48
|
+
* a bottom sheet), title, description, footer; slides
|
|
49
|
+
* .lu-separator a Separator: a 1px line, horizontal or vertical
|
|
50
|
+
* .lu-avatar an Avatar.Root: a 40px circle, the image covering it,
|
|
51
|
+
* the fallback's initials centred on a muted surface
|
|
52
|
+
* .lu-menubar a Menubar: a bordered bar of its menus' triggers (the
|
|
53
|
+
* open one filled); `lu-menu` on each Menu.Popup
|
|
54
|
+
* .lu-navigation-menu a NavigationMenu.Root: its list in a row (a column when
|
|
55
|
+
* vertical), triggers and links, the current page
|
|
56
|
+
* underlined, contents as surfaces of links that slide in
|
|
57
|
+
* .lu-number-field a NumberField.Root: label, one bordered group with the
|
|
58
|
+
* input between its buttons
|
|
59
|
+
* .lu-otp-field an OTPField.Root: a box per character, the caret's box
|
|
60
|
+
* ringed while focused, a dash for a separator
|
|
61
|
+
* .lu-preview-card a PreviewCard.Popup: a surface like a popover's, with a fade
|
|
62
|
+
* .lu-toolbar a Toolbar.Root: a bordered row (or column) of its items,
|
|
63
|
+
* separators across it
|
|
64
|
+
* .lu-scroll-area a ScrollArea.Root: a bordered box, 10px scrollbars that
|
|
65
|
+
* show while hovered, scrolled or focused
|
|
66
|
+
*/
|
|
67
|
+
@layer lu.core, lu.theme;
|
|
68
|
+
|
|
69
|
+
@layer lu.theme {
|
|
70
|
+
:root {
|
|
71
|
+
color-scheme: light dark;
|
|
72
|
+
--lu-background: light-dark(#fff, #09090b);
|
|
73
|
+
--lu-foreground: light-dark(#09090b, #fafafa);
|
|
74
|
+
--lu-card: light-dark(#fff, #18181b);
|
|
75
|
+
--lu-card-foreground: light-dark(#09090b, #fafafa);
|
|
76
|
+
--lu-popover: light-dark(#fff, #18181b);
|
|
77
|
+
--lu-popover-foreground: light-dark(#09090b, #fafafa);
|
|
78
|
+
--lu-primary: #2563eb;
|
|
79
|
+
--lu-primary-foreground: #fff;
|
|
80
|
+
--lu-secondary: light-dark(#f4f4f5, #27272a);
|
|
81
|
+
--lu-secondary-foreground: light-dark(#18181b, #fafafa);
|
|
82
|
+
--lu-muted: light-dark(#f4f4f5, #27272a);
|
|
83
|
+
--lu-muted-foreground: light-dark(#67676f, #a1a1aa);
|
|
84
|
+
--lu-accent: light-dark(#f4f4f5, #27272a);
|
|
85
|
+
--lu-accent-foreground: light-dark(#18181b, #fafafa);
|
|
86
|
+
--lu-destructive: #dc2626;
|
|
87
|
+
--lu-destructive-foreground: #fff;
|
|
88
|
+
--lu-border: light-dark(#e4e4e7, #3f3f46);
|
|
89
|
+
--lu-input: light-dark(#85858e, #71717a);
|
|
90
|
+
--lu-ring: light-dark(#2563eb, #60a5fa);
|
|
91
|
+
--lu-radius: 0.625rem;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Button ------------------------------------------------------------------------------------ */
|
|
95
|
+
|
|
96
|
+
.lu-button {
|
|
97
|
+
display: inline-flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
gap: 0.5rem;
|
|
101
|
+
min-block-size: 2.25rem;
|
|
102
|
+
padding: 0.5rem 1rem;
|
|
103
|
+
border: 1px solid var(--lu-input);
|
|
104
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
105
|
+
background: var(--lu-background);
|
|
106
|
+
color: var(--lu-foreground);
|
|
107
|
+
font: inherit;
|
|
108
|
+
font-size: 0.875rem;
|
|
109
|
+
font-weight: 500;
|
|
110
|
+
line-height: 1.25;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
}
|
|
113
|
+
.lu-button:hover {
|
|
114
|
+
background: var(--lu-accent);
|
|
115
|
+
color: var(--lu-accent-foreground);
|
|
116
|
+
}
|
|
117
|
+
.lu-button:focus-visible {
|
|
118
|
+
outline: 2px solid var(--lu-ring);
|
|
119
|
+
outline-offset: 2px;
|
|
120
|
+
}
|
|
121
|
+
.lu-button:disabled,
|
|
122
|
+
.lu-button[aria-disabled="true"] {
|
|
123
|
+
opacity: 0.5;
|
|
124
|
+
cursor: not-allowed;
|
|
125
|
+
}
|
|
126
|
+
/* An `aria-disabled` button still takes focus: its ring keeps full contrast (WCAG 1.4.11). */
|
|
127
|
+
.lu-button[aria-disabled="true"]:focus-visible {
|
|
128
|
+
opacity: 1;
|
|
129
|
+
}
|
|
130
|
+
.lu-button[data-variant="primary"] {
|
|
131
|
+
border-color: transparent;
|
|
132
|
+
background: var(--lu-primary);
|
|
133
|
+
color: var(--lu-primary-foreground);
|
|
134
|
+
}
|
|
135
|
+
.lu-button[data-variant="destructive"] {
|
|
136
|
+
border-color: transparent;
|
|
137
|
+
background: var(--lu-destructive);
|
|
138
|
+
color: var(--lu-destructive-foreground);
|
|
139
|
+
}
|
|
140
|
+
.lu-button[data-variant]:hover {
|
|
141
|
+
background-image: linear-gradient(rgb(0 0 0 / 0.1), rgb(0 0 0 / 0.1));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Dialog ------------------------------------------------------------------------------------ */
|
|
145
|
+
|
|
146
|
+
.lu-dialog {
|
|
147
|
+
box-sizing: border-box;
|
|
148
|
+
inline-size: min(32rem, 100vw - 2rem);
|
|
149
|
+
max-block-size: calc(100dvh - 2rem);
|
|
150
|
+
padding: 1.5rem;
|
|
151
|
+
border: 1px solid var(--lu-border);
|
|
152
|
+
border-radius: var(--lu-radius);
|
|
153
|
+
background: var(--lu-popover);
|
|
154
|
+
color: var(--lu-popover-foreground);
|
|
155
|
+
box-shadow:
|
|
156
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
157
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
158
|
+
}
|
|
159
|
+
.lu-dialog::backdrop {
|
|
160
|
+
background: rgb(0 0 0 / 0.5);
|
|
161
|
+
}
|
|
162
|
+
.lu-dialog :where(h2) {
|
|
163
|
+
margin: 0 0 0.5rem;
|
|
164
|
+
font-size: 1.125rem;
|
|
165
|
+
font-weight: 600;
|
|
166
|
+
line-height: 1.3;
|
|
167
|
+
}
|
|
168
|
+
.lu-dialog :where(p) {
|
|
169
|
+
margin: 0 0 1.5rem;
|
|
170
|
+
color: var(--lu-muted-foreground);
|
|
171
|
+
font-size: 0.875rem;
|
|
172
|
+
line-height: 1.5;
|
|
173
|
+
}
|
|
174
|
+
.lu-dialog :where(footer) {
|
|
175
|
+
display: flex;
|
|
176
|
+
flex-wrap: wrap;
|
|
177
|
+
justify-content: end;
|
|
178
|
+
gap: 0.5rem;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/*
|
|
182
|
+
* Fade and zoom in and out. `overlay` keeps the dialog in the top layer while it fades out, in
|
|
183
|
+
* Chromium only: elsewhere it leaves at once.
|
|
184
|
+
*/
|
|
185
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
186
|
+
.lu-dialog,
|
|
187
|
+
.lu-dialog::backdrop {
|
|
188
|
+
transition:
|
|
189
|
+
opacity 150ms ease-out,
|
|
190
|
+
scale 150ms ease-out,
|
|
191
|
+
overlay 150ms allow-discrete,
|
|
192
|
+
display 150ms allow-discrete;
|
|
193
|
+
}
|
|
194
|
+
.lu-dialog:not([open]),
|
|
195
|
+
.lu-dialog:not([open])::backdrop {
|
|
196
|
+
opacity: 0;
|
|
197
|
+
}
|
|
198
|
+
.lu-dialog:not([open]) {
|
|
199
|
+
scale: 0.96;
|
|
200
|
+
}
|
|
201
|
+
@starting-style {
|
|
202
|
+
.lu-dialog[open],
|
|
203
|
+
.lu-dialog[open]::backdrop {
|
|
204
|
+
opacity: 0;
|
|
205
|
+
}
|
|
206
|
+
.lu-dialog[open] {
|
|
207
|
+
scale: 0.96;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Popover ----------------------------------------------------------------------------------- */
|
|
213
|
+
|
|
214
|
+
.lu-popover {
|
|
215
|
+
--lu-side-offset: 4px;
|
|
216
|
+
box-sizing: border-box;
|
|
217
|
+
inline-size: max-content;
|
|
218
|
+
max-inline-size: min(20rem, 100vw - 1rem);
|
|
219
|
+
padding: 1rem;
|
|
220
|
+
border: 1px solid var(--lu-border);
|
|
221
|
+
border-radius: var(--lu-radius);
|
|
222
|
+
background: var(--lu-popover);
|
|
223
|
+
color: var(--lu-popover-foreground);
|
|
224
|
+
box-shadow:
|
|
225
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
226
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
227
|
+
}
|
|
228
|
+
.lu-popover :where(h2) {
|
|
229
|
+
margin: 0 0 0.25rem;
|
|
230
|
+
font-size: 1rem;
|
|
231
|
+
font-weight: 600;
|
|
232
|
+
line-height: 1.3;
|
|
233
|
+
}
|
|
234
|
+
.lu-popover :where(p) {
|
|
235
|
+
margin: 0;
|
|
236
|
+
color: var(--lu-muted-foreground);
|
|
237
|
+
font-size: 0.875rem;
|
|
238
|
+
line-height: 1.5;
|
|
239
|
+
}
|
|
240
|
+
.lu-popover :where(footer) {
|
|
241
|
+
display: flex;
|
|
242
|
+
flex-wrap: wrap;
|
|
243
|
+
justify-content: end;
|
|
244
|
+
gap: 0.5rem;
|
|
245
|
+
margin-block-start: 1rem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Tooltip ----------------------------------------------------------------------------------- */
|
|
249
|
+
|
|
250
|
+
.lu-tooltip {
|
|
251
|
+
--lu-side-offset: 6px;
|
|
252
|
+
box-sizing: border-box;
|
|
253
|
+
max-inline-size: min(18rem, 100vw - 1rem);
|
|
254
|
+
padding: 0.375rem 0.625rem;
|
|
255
|
+
border: 0;
|
|
256
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
257
|
+
background: var(--lu-foreground);
|
|
258
|
+
color: var(--lu-background);
|
|
259
|
+
font-size: 0.8125rem;
|
|
260
|
+
line-height: 1.4;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Fade in and out; `overlay` keeps them in the top layer while they fade out, in Chromium only. */
|
|
264
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
265
|
+
.lu-popover,
|
|
266
|
+
.lu-tooltip {
|
|
267
|
+
transition:
|
|
268
|
+
opacity 120ms ease-out,
|
|
269
|
+
scale 120ms ease-out,
|
|
270
|
+
overlay 120ms allow-discrete,
|
|
271
|
+
display 120ms allow-discrete;
|
|
272
|
+
}
|
|
273
|
+
/* A modal popover is an open <dialog>, not an open popover (TASK-394). */
|
|
274
|
+
.lu-popover:not(:popover-open, [open]),
|
|
275
|
+
.lu-tooltip:not(:popover-open) {
|
|
276
|
+
opacity: 0;
|
|
277
|
+
scale: 0.96;
|
|
278
|
+
}
|
|
279
|
+
@starting-style {
|
|
280
|
+
.lu-popover:is(:popover-open, [open]),
|
|
281
|
+
.lu-tooltip:popover-open {
|
|
282
|
+
opacity: 0;
|
|
283
|
+
scale: 0.96;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Tabs -------------------------------------------------------------------------------------- */
|
|
289
|
+
|
|
290
|
+
/*
|
|
291
|
+
* The selected tab is marked by a 2px bar in the foreground colour (19:1, against 3:1 for
|
|
292
|
+
* WCAG 1.4.11) and by its text colour, not by colour alone.
|
|
293
|
+
*/
|
|
294
|
+
.lu-tabs [role="tablist"] {
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-wrap: wrap;
|
|
297
|
+
gap: 0.25rem;
|
|
298
|
+
border-block-end: 1px solid var(--lu-border);
|
|
299
|
+
}
|
|
300
|
+
.lu-tabs [role="tablist"][aria-orientation="vertical"] {
|
|
301
|
+
flex-direction: column;
|
|
302
|
+
border-block-end: 0;
|
|
303
|
+
border-inline-end: 1px solid var(--lu-border);
|
|
304
|
+
}
|
|
305
|
+
.lu-tabs [role="tab"] {
|
|
306
|
+
min-block-size: 2.25rem;
|
|
307
|
+
padding: 0.5rem 0.875rem;
|
|
308
|
+
border: 0;
|
|
309
|
+
border-radius: calc(var(--lu-radius) - 4px) calc(var(--lu-radius) - 4px) 0 0;
|
|
310
|
+
background: transparent;
|
|
311
|
+
color: var(--lu-muted-foreground);
|
|
312
|
+
font: inherit;
|
|
313
|
+
font-size: 0.875rem;
|
|
314
|
+
font-weight: 500;
|
|
315
|
+
line-height: 1.25;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
}
|
|
318
|
+
.lu-tabs [role="tab"]:hover {
|
|
319
|
+
color: var(--lu-foreground);
|
|
320
|
+
}
|
|
321
|
+
.lu-tabs [role="tab"][aria-selected="true"] {
|
|
322
|
+
color: var(--lu-foreground);
|
|
323
|
+
box-shadow: inset 0 -2px var(--lu-foreground);
|
|
324
|
+
}
|
|
325
|
+
/*
|
|
326
|
+
* Logical sides, so a vertical list mirrors right to left without `:dir()` (which Lightning CSS
|
|
327
|
+
* lowers to `:lang()`s that miss a `dir` attribute, TASK-385).
|
|
328
|
+
*/
|
|
329
|
+
.lu-tabs [aria-orientation="vertical"] [role="tab"] {
|
|
330
|
+
border-radius: 0;
|
|
331
|
+
border-start-start-radius: calc(var(--lu-radius) - 4px);
|
|
332
|
+
border-end-start-radius: calc(var(--lu-radius) - 4px);
|
|
333
|
+
border-inline-end: 2px solid transparent;
|
|
334
|
+
text-align: start;
|
|
335
|
+
}
|
|
336
|
+
.lu-tabs [aria-orientation="vertical"] [role="tab"][aria-selected="true"] {
|
|
337
|
+
border-inline-end-color: var(--lu-foreground);
|
|
338
|
+
box-shadow: none;
|
|
339
|
+
}
|
|
340
|
+
/*
|
|
341
|
+
* A Tabs.Indicator (TASK-395) draws the same bar over the selected tab's from the server HTML
|
|
342
|
+
* on; once the script runs, the tab's own bar goes and the indicator slides to the next tab.
|
|
343
|
+
*/
|
|
344
|
+
.lu-tabs [data-indicator] {
|
|
345
|
+
border-block-end: 2px solid var(--lu-foreground);
|
|
346
|
+
}
|
|
347
|
+
.lu-tabs [aria-orientation="vertical"] > [data-indicator] {
|
|
348
|
+
border-block-end: 0;
|
|
349
|
+
border-inline-end: 2px solid var(--lu-foreground);
|
|
350
|
+
}
|
|
351
|
+
.lu-tabs:defined [role="tablist"]:has(> [data-indicator]) [role="tab"][aria-selected="true"] {
|
|
352
|
+
border-inline-end-color: transparent;
|
|
353
|
+
box-shadow: none;
|
|
354
|
+
}
|
|
355
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
356
|
+
.lu-tabs [data-indicator] {
|
|
357
|
+
transition:
|
|
358
|
+
left 0.2s ease,
|
|
359
|
+
top 0.2s ease,
|
|
360
|
+
width 0.2s ease,
|
|
361
|
+
height 0.2s ease;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/* Dimmed by its text, not `opacity`, which would dim its focus ring too (disabled tabs take focus). */
|
|
365
|
+
.lu-tabs [role="tab"][aria-disabled="true"] {
|
|
366
|
+
color: color-mix(in srgb, var(--lu-muted-foreground) 55%, transparent);
|
|
367
|
+
cursor: not-allowed;
|
|
368
|
+
}
|
|
369
|
+
.lu-tabs [role="tab"]:focus-visible,
|
|
370
|
+
.lu-tabs [role="tabpanel"]:focus-visible {
|
|
371
|
+
outline: 2px solid var(--lu-ring);
|
|
372
|
+
outline-offset: 2px;
|
|
373
|
+
}
|
|
374
|
+
.lu-tabs [role="tabpanel"] {
|
|
375
|
+
padding-block: 1rem;
|
|
376
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* Menu (TASK-357) --------------------------------------------------------------------------- */
|
|
380
|
+
|
|
381
|
+
.lu-menu {
|
|
382
|
+
box-sizing: border-box;
|
|
383
|
+
min-inline-size: 8rem;
|
|
384
|
+
max-block-size: min(24rem, var(--lu-available-height, 100dvh - 1rem));
|
|
385
|
+
overflow-y: auto;
|
|
386
|
+
padding: 0.25rem;
|
|
387
|
+
border: 1px solid var(--lu-border);
|
|
388
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
389
|
+
background: var(--lu-popover);
|
|
390
|
+
color: var(--lu-popover-foreground);
|
|
391
|
+
font-size: 0.875rem;
|
|
392
|
+
line-height: 1.25;
|
|
393
|
+
box-shadow:
|
|
394
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
395
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
396
|
+
--lu-side-offset: 0.25rem;
|
|
397
|
+
}
|
|
398
|
+
/* A submenu's first item lines up with its trigger. */
|
|
399
|
+
.lu-menu[data-side^="inline-"],
|
|
400
|
+
.lu-menu[data-side="left"],
|
|
401
|
+
.lu-menu[data-side="right"] {
|
|
402
|
+
--lu-side-offset: 0.125rem;
|
|
403
|
+
--lu-align-offset: calc(-0.25rem - 1px);
|
|
404
|
+
}
|
|
405
|
+
.lu-menu :where([role^="menuitem"]) {
|
|
406
|
+
box-sizing: border-box;
|
|
407
|
+
gap: 0.5rem;
|
|
408
|
+
min-block-size: 2rem;
|
|
409
|
+
padding: 0.375rem 0.5rem;
|
|
410
|
+
border: 0;
|
|
411
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
412
|
+
background: none;
|
|
413
|
+
color: inherit;
|
|
414
|
+
font: inherit;
|
|
415
|
+
text-align: start;
|
|
416
|
+
text-decoration: none;
|
|
417
|
+
cursor: default;
|
|
418
|
+
}
|
|
419
|
+
.lu-menu :where([role^="menuitem"][data-highlighted], [aria-expanded="true"]) {
|
|
420
|
+
background: var(--lu-accent);
|
|
421
|
+
color: var(--lu-accent-foreground);
|
|
422
|
+
}
|
|
423
|
+
.lu-menu :where([role^="menuitem"]:focus-visible) {
|
|
424
|
+
outline: 2px solid var(--lu-ring);
|
|
425
|
+
outline-offset: -2px;
|
|
426
|
+
}
|
|
427
|
+
/* Dimmed by its text, not `opacity`, which would fade its focus ring to 2:1 (TASK-455, L34). */
|
|
428
|
+
.lu-menu :where([role^="menuitem"][aria-disabled="true"]) {
|
|
429
|
+
color: color-mix(in srgb, var(--lu-muted-foreground) 55%, transparent);
|
|
430
|
+
}
|
|
431
|
+
/* Checkbox and radio marks: a symbol, not only a colour; empty alt text keeps them out of the name. */
|
|
432
|
+
.lu-menu :where([role="menuitemcheckbox"], [role="menuitemradio"])::before {
|
|
433
|
+
content: "";
|
|
434
|
+
flex: none;
|
|
435
|
+
inline-size: 1rem;
|
|
436
|
+
text-align: center;
|
|
437
|
+
}
|
|
438
|
+
.lu-menu :where([role="menuitemcheckbox"][aria-checked="true"])::before {
|
|
439
|
+
content: "✓" / "";
|
|
440
|
+
}
|
|
441
|
+
.lu-menu :where([role="menuitemradio"][aria-checked="true"])::before {
|
|
442
|
+
content: "●" / "";
|
|
443
|
+
font-size: 0.5rem;
|
|
444
|
+
}
|
|
445
|
+
.lu-menu :where([role="menuitem"][aria-haspopup="menu"])::after {
|
|
446
|
+
content: "›" / "";
|
|
447
|
+
margin-inline-start: auto;
|
|
448
|
+
padding-inline-start: 1rem;
|
|
449
|
+
}
|
|
450
|
+
/* Not `:dir(rtl)`: Lightning CSS lowers it to `:lang()`s, which miss a `dir` attribute. */
|
|
451
|
+
:where([dir="rtl"]) .lu-menu :where([role="menuitem"][aria-haspopup="menu"])::after {
|
|
452
|
+
content: "‹" / "";
|
|
453
|
+
}
|
|
454
|
+
:where([dir="rtl"])
|
|
455
|
+
:where([dir="ltr"])
|
|
456
|
+
.lu-menu
|
|
457
|
+
:where([role="menuitem"][aria-haspopup="menu"])::after {
|
|
458
|
+
content: "›" / "";
|
|
459
|
+
}
|
|
460
|
+
.lu-menu :where([role="separator"]) {
|
|
461
|
+
block-size: 1px;
|
|
462
|
+
margin: 0.25rem -0.25rem;
|
|
463
|
+
background: var(--lu-border);
|
|
464
|
+
}
|
|
465
|
+
.lu-menu :where([role="group"] > [role="presentation"]) {
|
|
466
|
+
padding: 0.375rem 0.5rem;
|
|
467
|
+
color: var(--lu-muted-foreground);
|
|
468
|
+
font-size: 0.75rem;
|
|
469
|
+
font-weight: 500;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/* Fade and zoom in and out; `overlay` keeps the menu in the top layer while it fades (Chromium). */
|
|
473
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
474
|
+
.lu-menu {
|
|
475
|
+
transition:
|
|
476
|
+
opacity 100ms ease-out,
|
|
477
|
+
scale 100ms ease-out,
|
|
478
|
+
overlay 100ms allow-discrete,
|
|
479
|
+
display 100ms allow-discrete;
|
|
480
|
+
}
|
|
481
|
+
.lu-menu:not(:popover-open) {
|
|
482
|
+
opacity: 0;
|
|
483
|
+
scale: 0.96;
|
|
484
|
+
}
|
|
485
|
+
@starting-style {
|
|
486
|
+
.lu-menu:popover-open {
|
|
487
|
+
opacity: 0;
|
|
488
|
+
scale: 0.96;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/* Combobox (TASK-358) ----------------------------------------------------------------------- */
|
|
494
|
+
|
|
495
|
+
/*
|
|
496
|
+
* The root becomes the field's grid: the label, the chips, then the input with the trigger and
|
|
497
|
+
* clear buttons laid over its inline end.
|
|
498
|
+
*/
|
|
499
|
+
.lu-combobox {
|
|
500
|
+
display: inline-grid;
|
|
501
|
+
grid-template-areas: "label label label" "chips chips chips" "field field field";
|
|
502
|
+
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
503
|
+
align-items: center;
|
|
504
|
+
inline-size: min(18rem, 100%);
|
|
505
|
+
font-size: 0.875rem;
|
|
506
|
+
line-height: 1.25;
|
|
507
|
+
}
|
|
508
|
+
.lu-combobox > :where(label) {
|
|
509
|
+
grid-area: label;
|
|
510
|
+
margin-block-end: 0.375rem;
|
|
511
|
+
font-weight: 500;
|
|
512
|
+
}
|
|
513
|
+
.lu-combobox > :where(input[role="combobox"]) {
|
|
514
|
+
grid-area: field;
|
|
515
|
+
box-sizing: border-box;
|
|
516
|
+
min-inline-size: 0;
|
|
517
|
+
min-block-size: 2.25rem;
|
|
518
|
+
padding: 0.5rem 0.75rem;
|
|
519
|
+
border: 1px solid var(--lu-input);
|
|
520
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
521
|
+
background: var(--lu-background);
|
|
522
|
+
color: var(--lu-foreground);
|
|
523
|
+
font: inherit;
|
|
524
|
+
}
|
|
525
|
+
.lu-combobox:has(> [command="--toggle"]) > :where(input[role="combobox"]) {
|
|
526
|
+
padding-inline-end: 2.25rem;
|
|
527
|
+
}
|
|
528
|
+
.lu-combobox:has(> [command="--toggle"]):has(> [command="--clear"]:not([hidden]))
|
|
529
|
+
> :where(input[role="combobox"]) {
|
|
530
|
+
padding-inline-end: 4rem;
|
|
531
|
+
}
|
|
532
|
+
.lu-combobox > :where(input[role="combobox"])::placeholder {
|
|
533
|
+
color: var(--lu-muted-foreground);
|
|
534
|
+
}
|
|
535
|
+
.lu-combobox > :where(input[role="combobox"]:focus-visible) {
|
|
536
|
+
outline: 2px solid var(--lu-ring);
|
|
537
|
+
outline-offset: 2px;
|
|
538
|
+
}
|
|
539
|
+
.lu-combobox > :where(input[role="combobox"]:disabled) {
|
|
540
|
+
opacity: 0.5;
|
|
541
|
+
cursor: not-allowed;
|
|
542
|
+
}
|
|
543
|
+
/* The trigger and clear buttons: 28px targets inside the field; a glyph when they are empty. */
|
|
544
|
+
.lu-combobox > :where(button[command]) {
|
|
545
|
+
grid-row: field;
|
|
546
|
+
z-index: 1;
|
|
547
|
+
display: inline-grid;
|
|
548
|
+
place-items: center;
|
|
549
|
+
inline-size: 1.75rem;
|
|
550
|
+
block-size: 1.75rem;
|
|
551
|
+
margin-inline-end: 0.25rem;
|
|
552
|
+
padding: 0;
|
|
553
|
+
border: 0;
|
|
554
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
555
|
+
background: none;
|
|
556
|
+
color: var(--lu-muted-foreground);
|
|
557
|
+
font: inherit;
|
|
558
|
+
cursor: default;
|
|
559
|
+
}
|
|
560
|
+
.lu-combobox > :where(button[command="--toggle"]) {
|
|
561
|
+
grid-column: 3;
|
|
562
|
+
}
|
|
563
|
+
.lu-combobox > :where(button[command="--clear"]) {
|
|
564
|
+
grid-column: 2;
|
|
565
|
+
}
|
|
566
|
+
.lu-combobox > :where(button[command]:hover) {
|
|
567
|
+
background: var(--lu-accent);
|
|
568
|
+
color: var(--lu-accent-foreground);
|
|
569
|
+
}
|
|
570
|
+
.lu-combobox > :where(button[command="--toggle"]:empty)::before {
|
|
571
|
+
content: "⌄" / "";
|
|
572
|
+
translate: 0 -0.2em;
|
|
573
|
+
}
|
|
574
|
+
.lu-combobox > :where(button[command="--clear"]:empty)::before {
|
|
575
|
+
content: "×" / "";
|
|
576
|
+
font-size: 1.125rem;
|
|
577
|
+
}
|
|
578
|
+
.lu-combobox > :where([role="list"]) {
|
|
579
|
+
grid-area: chips;
|
|
580
|
+
display: flex;
|
|
581
|
+
flex-wrap: wrap;
|
|
582
|
+
gap: 0.25rem;
|
|
583
|
+
margin-block-end: 0.375rem;
|
|
584
|
+
}
|
|
585
|
+
.lu-combobox > :where([role="list"]:empty) {
|
|
586
|
+
display: none;
|
|
587
|
+
}
|
|
588
|
+
.lu-combobox :where([role="listitem"]) {
|
|
589
|
+
display: inline-flex;
|
|
590
|
+
align-items: center;
|
|
591
|
+
gap: 0.125rem;
|
|
592
|
+
padding-inline-start: 0.5rem;
|
|
593
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
594
|
+
background: var(--lu-secondary);
|
|
595
|
+
color: var(--lu-secondary-foreground);
|
|
596
|
+
font-size: 0.8125rem;
|
|
597
|
+
}
|
|
598
|
+
.lu-combobox :where([role="listitem"] > button) {
|
|
599
|
+
inline-size: 1.5rem;
|
|
600
|
+
block-size: 1.5rem;
|
|
601
|
+
padding: 0;
|
|
602
|
+
border: 0;
|
|
603
|
+
border-radius: inherit;
|
|
604
|
+
background: none;
|
|
605
|
+
color: inherit;
|
|
606
|
+
font: inherit;
|
|
607
|
+
}
|
|
608
|
+
.lu-combobox :where([role="listitem"] > button:hover) {
|
|
609
|
+
background: var(--lu-accent);
|
|
610
|
+
}
|
|
611
|
+
/* A chip the arrow keys reach (TASK-461). */
|
|
612
|
+
.lu-combobox :where([role="listitem"]:focus-visible) {
|
|
613
|
+
outline: 2px solid var(--lu-ring);
|
|
614
|
+
outline-offset: 1px;
|
|
615
|
+
}
|
|
616
|
+
/* The popup: the List, or the Popup around it; the list scrolls. */
|
|
617
|
+
.lu-combobox :where([popover]) {
|
|
618
|
+
--lu-side-offset: 0.25rem;
|
|
619
|
+
box-sizing: border-box;
|
|
620
|
+
min-inline-size: 12rem;
|
|
621
|
+
padding: 0.25rem;
|
|
622
|
+
border: 1px solid var(--lu-border);
|
|
623
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
624
|
+
background: var(--lu-popover);
|
|
625
|
+
color: var(--lu-popover-foreground);
|
|
626
|
+
font-size: 0.875rem;
|
|
627
|
+
line-height: 1.25;
|
|
628
|
+
box-shadow:
|
|
629
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
630
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
631
|
+
}
|
|
632
|
+
@supports (anchor-name: --a) {
|
|
633
|
+
.lu-combobox :where([popover]) {
|
|
634
|
+
min-inline-size: anchor-size(inline);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
.lu-combobox :where([role="listbox"]) {
|
|
638
|
+
max-block-size: min(20rem, var(--lu-available-height, 100dvh - 1rem));
|
|
639
|
+
overflow-y: auto;
|
|
640
|
+
}
|
|
641
|
+
.lu-combobox :where([role="option"]) {
|
|
642
|
+
display: flex;
|
|
643
|
+
align-items: center;
|
|
644
|
+
gap: 0.5rem;
|
|
645
|
+
min-block-size: 2rem;
|
|
646
|
+
padding: 0.375rem 0.5rem;
|
|
647
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
648
|
+
cursor: default;
|
|
649
|
+
}
|
|
650
|
+
/* The highlighted option has no focus of its own: it gets the focus ring the input passes on. */
|
|
651
|
+
.lu-combobox :where([role="option"][data-highlighted]) {
|
|
652
|
+
background: var(--lu-accent);
|
|
653
|
+
color: var(--lu-accent-foreground);
|
|
654
|
+
outline: 2px solid var(--lu-ring);
|
|
655
|
+
outline-offset: -2px;
|
|
656
|
+
}
|
|
657
|
+
.lu-combobox :where([role="option"][aria-disabled="true"]) {
|
|
658
|
+
opacity: 0.5;
|
|
659
|
+
}
|
|
660
|
+
/* A mark, not only a colour, for the selected options; empty alt text keeps it out of the name. */
|
|
661
|
+
.lu-combobox :where([role="option"])::before {
|
|
662
|
+
content: "";
|
|
663
|
+
flex: none;
|
|
664
|
+
inline-size: 1rem;
|
|
665
|
+
text-align: center;
|
|
666
|
+
}
|
|
667
|
+
.lu-combobox :where([role="option"][aria-selected="true"])::before {
|
|
668
|
+
content: "✓" / "";
|
|
669
|
+
}
|
|
670
|
+
.lu-combobox :where([role="group"] > [role="presentation"]) {
|
|
671
|
+
padding: 0.375rem 0.5rem;
|
|
672
|
+
color: var(--lu-muted-foreground);
|
|
673
|
+
font-size: 0.75rem;
|
|
674
|
+
font-weight: 500;
|
|
675
|
+
}
|
|
676
|
+
.lu-combobox :where([popover] [role="status"]) {
|
|
677
|
+
padding: 0.5rem;
|
|
678
|
+
color: var(--lu-muted-foreground);
|
|
679
|
+
text-align: center;
|
|
680
|
+
}
|
|
681
|
+
.lu-combobox :where([popover] [role="status"]:empty) {
|
|
682
|
+
display: none;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
686
|
+
.lu-combobox :where([popover]) {
|
|
687
|
+
transition:
|
|
688
|
+
opacity 100ms ease-out,
|
|
689
|
+
overlay 100ms allow-discrete,
|
|
690
|
+
display 100ms allow-discrete;
|
|
691
|
+
}
|
|
692
|
+
.lu-combobox :where([popover]:not(:popover-open)) {
|
|
693
|
+
opacity: 0;
|
|
694
|
+
}
|
|
695
|
+
@starting-style {
|
|
696
|
+
.lu-combobox :where([popover]:popover-open) {
|
|
697
|
+
opacity: 0;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/* Select (TASK-358) ------------------------------------------------------------------------- */
|
|
703
|
+
|
|
704
|
+
/* A customizable select where the browser has it; elsewhere the closed control is styled. */
|
|
705
|
+
.lu-select,
|
|
706
|
+
.lu-select::picker(select) {
|
|
707
|
+
appearance: base-select;
|
|
708
|
+
}
|
|
709
|
+
.lu-select {
|
|
710
|
+
box-sizing: border-box;
|
|
711
|
+
display: inline-flex;
|
|
712
|
+
align-items: center;
|
|
713
|
+
gap: 0.5rem;
|
|
714
|
+
min-inline-size: 10rem;
|
|
715
|
+
min-block-size: 2.25rem;
|
|
716
|
+
padding: 0.5rem 0.75rem;
|
|
717
|
+
border: 1px solid var(--lu-input);
|
|
718
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
719
|
+
background: var(--lu-background);
|
|
720
|
+
color: var(--lu-foreground);
|
|
721
|
+
font: inherit;
|
|
722
|
+
font-size: 0.875rem;
|
|
723
|
+
line-height: 1.25;
|
|
724
|
+
}
|
|
725
|
+
.lu-select:focus-visible {
|
|
726
|
+
outline: 2px solid var(--lu-ring);
|
|
727
|
+
outline-offset: 2px;
|
|
728
|
+
}
|
|
729
|
+
.lu-select:disabled {
|
|
730
|
+
opacity: 0.5;
|
|
731
|
+
cursor: not-allowed;
|
|
732
|
+
}
|
|
733
|
+
/* With a Select.Trigger, the button is the whole control: it takes the padding and the target. */
|
|
734
|
+
.lu-select:has(> button) {
|
|
735
|
+
padding: 0;
|
|
736
|
+
}
|
|
737
|
+
.lu-select > :where(button) {
|
|
738
|
+
display: inline-flex;
|
|
739
|
+
flex: 1;
|
|
740
|
+
align-items: center;
|
|
741
|
+
gap: 0.5rem;
|
|
742
|
+
box-sizing: border-box;
|
|
743
|
+
min-block-size: calc(2.25rem - 2px);
|
|
744
|
+
padding: 0.5rem 0.75rem;
|
|
745
|
+
border: 0;
|
|
746
|
+
background: none;
|
|
747
|
+
color: inherit;
|
|
748
|
+
font: inherit;
|
|
749
|
+
}
|
|
750
|
+
.lu-select::picker-icon {
|
|
751
|
+
margin-inline-start: auto;
|
|
752
|
+
color: var(--lu-muted-foreground);
|
|
753
|
+
}
|
|
754
|
+
.lu-select:has(> button)::picker-icon {
|
|
755
|
+
margin-inline-end: 0.75rem;
|
|
756
|
+
}
|
|
757
|
+
.lu-select::picker(select) {
|
|
758
|
+
box-sizing: border-box;
|
|
759
|
+
min-inline-size: anchor-size(inline);
|
|
760
|
+
max-block-size: min(20rem, 100dvh - 1rem);
|
|
761
|
+
margin-block: 0.25rem;
|
|
762
|
+
padding: 0.25rem;
|
|
763
|
+
border: 1px solid var(--lu-border);
|
|
764
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
765
|
+
background: var(--lu-popover);
|
|
766
|
+
color: var(--lu-popover-foreground);
|
|
767
|
+
box-shadow:
|
|
768
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
769
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
770
|
+
}
|
|
771
|
+
.lu-select :where(option) {
|
|
772
|
+
gap: 0.5rem;
|
|
773
|
+
min-block-size: 2rem;
|
|
774
|
+
padding: 0.375rem 0.5rem;
|
|
775
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
776
|
+
}
|
|
777
|
+
.lu-select :where(option:hover, option:focus-visible) {
|
|
778
|
+
background: var(--lu-accent);
|
|
779
|
+
color: var(--lu-accent-foreground);
|
|
780
|
+
}
|
|
781
|
+
.lu-select :where(option:focus-visible) {
|
|
782
|
+
outline: 2px solid var(--lu-ring);
|
|
783
|
+
outline-offset: -2px;
|
|
784
|
+
}
|
|
785
|
+
.lu-select :where(option:disabled) {
|
|
786
|
+
opacity: 0.5;
|
|
787
|
+
}
|
|
788
|
+
.lu-select :where(optgroup) {
|
|
789
|
+
color: var(--lu-muted-foreground);
|
|
790
|
+
font-size: 0.75rem;
|
|
791
|
+
font-weight: 500;
|
|
792
|
+
}
|
|
793
|
+
.lu-select :where(optgroup option) {
|
|
794
|
+
color: var(--lu-popover-foreground);
|
|
795
|
+
font-size: 0.875rem;
|
|
796
|
+
font-weight: 400;
|
|
797
|
+
}
|
|
798
|
+
.lu-select :where(hr) {
|
|
799
|
+
margin: 0.25rem -0.25rem;
|
|
800
|
+
border: 0;
|
|
801
|
+
border-block-start: 1px solid var(--lu-border);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/* Field, Fieldset and Input (TASK-365) ------------------------------------------------------ */
|
|
805
|
+
|
|
806
|
+
.lu-field {
|
|
807
|
+
display: grid;
|
|
808
|
+
gap: 0.375rem;
|
|
809
|
+
font-size: 0.875rem;
|
|
810
|
+
line-height: 1.25;
|
|
811
|
+
}
|
|
812
|
+
.lu-field > :where(label) {
|
|
813
|
+
font-weight: 500;
|
|
814
|
+
}
|
|
815
|
+
.lu-field > :where(p) {
|
|
816
|
+
margin: 0;
|
|
817
|
+
color: var(--lu-muted-foreground);
|
|
818
|
+
font-size: 0.8125rem;
|
|
819
|
+
}
|
|
820
|
+
/* Errors: the destructive red where it reaches 4.5:1 on the page, a lighter red in dark. */
|
|
821
|
+
.lu-field > :where(output) {
|
|
822
|
+
color: light-dark(var(--lu-destructive), #f87171);
|
|
823
|
+
font-size: 0.8125rem;
|
|
824
|
+
}
|
|
825
|
+
.lu-input {
|
|
826
|
+
box-sizing: border-box;
|
|
827
|
+
min-block-size: 2.25rem;
|
|
828
|
+
padding: 0.5rem 0.75rem;
|
|
829
|
+
border: 1px solid var(--lu-input);
|
|
830
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
831
|
+
background: var(--lu-background);
|
|
832
|
+
color: var(--lu-foreground);
|
|
833
|
+
font: inherit;
|
|
834
|
+
font-size: 0.875rem;
|
|
835
|
+
}
|
|
836
|
+
.lu-input::placeholder {
|
|
837
|
+
color: var(--lu-muted-foreground);
|
|
838
|
+
}
|
|
839
|
+
.lu-input:focus-visible {
|
|
840
|
+
outline: 2px solid var(--lu-ring);
|
|
841
|
+
outline-offset: 2px;
|
|
842
|
+
}
|
|
843
|
+
.lu-input:disabled {
|
|
844
|
+
opacity: 0.5;
|
|
845
|
+
cursor: not-allowed;
|
|
846
|
+
}
|
|
847
|
+
.lu-input[aria-invalid="true"] {
|
|
848
|
+
border-color: light-dark(var(--lu-destructive), #f87171);
|
|
849
|
+
}
|
|
850
|
+
.lu-fieldset {
|
|
851
|
+
display: grid;
|
|
852
|
+
gap: 0.75rem;
|
|
853
|
+
min-inline-size: 0;
|
|
854
|
+
margin: 0;
|
|
855
|
+
padding: 0;
|
|
856
|
+
border: 0;
|
|
857
|
+
font-size: 0.875rem;
|
|
858
|
+
}
|
|
859
|
+
.lu-fieldset > :where(legend) {
|
|
860
|
+
margin-block-end: 0.25rem;
|
|
861
|
+
padding: 0;
|
|
862
|
+
font-weight: 600;
|
|
863
|
+
}
|
|
864
|
+
.lu-fieldset > :where(label) {
|
|
865
|
+
display: inline-flex;
|
|
866
|
+
align-items: center;
|
|
867
|
+
gap: 0.25rem;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/* Checkbox, Radio and Switch (TASK-366 to TASK-368) ----------------------------------------- */
|
|
871
|
+
|
|
872
|
+
/*
|
|
873
|
+
* A 24px target (WCAG 2.5.8) around an 18px box drawn by `::before`; the mark is a symbol and a
|
|
874
|
+
* shape, not only a colour (1.4.1). The box's border is --lu-input (3:1, 1.4.11).
|
|
875
|
+
*/
|
|
876
|
+
.lu-checkbox,
|
|
877
|
+
.lu-radio {
|
|
878
|
+
appearance: none;
|
|
879
|
+
display: inline-grid;
|
|
880
|
+
place-items: center;
|
|
881
|
+
flex: none;
|
|
882
|
+
inline-size: 1.5rem;
|
|
883
|
+
block-size: 1.5rem;
|
|
884
|
+
margin: 0;
|
|
885
|
+
vertical-align: middle;
|
|
886
|
+
cursor: pointer;
|
|
887
|
+
}
|
|
888
|
+
.lu-checkbox::before,
|
|
889
|
+
.lu-radio::before {
|
|
890
|
+
content: "";
|
|
891
|
+
box-sizing: border-box;
|
|
892
|
+
inline-size: 1.125rem;
|
|
893
|
+
block-size: 1.125rem;
|
|
894
|
+
border: 1px solid var(--lu-input);
|
|
895
|
+
border-radius: calc(var(--lu-radius) - 6px);
|
|
896
|
+
background: var(--lu-background);
|
|
897
|
+
color: var(--lu-primary-foreground);
|
|
898
|
+
font-size: 0.75rem;
|
|
899
|
+
font-weight: 700;
|
|
900
|
+
line-height: calc(1.125rem - 2px);
|
|
901
|
+
text-align: center;
|
|
902
|
+
}
|
|
903
|
+
.lu-radio::before {
|
|
904
|
+
border-radius: 50%;
|
|
905
|
+
}
|
|
906
|
+
.lu-checkbox:is(:checked, :indeterminate, [data-indeterminate])::before {
|
|
907
|
+
border-color: var(--lu-primary);
|
|
908
|
+
background: var(--lu-primary);
|
|
909
|
+
}
|
|
910
|
+
.lu-checkbox:checked::before {
|
|
911
|
+
content: "✓" / "";
|
|
912
|
+
}
|
|
913
|
+
.lu-checkbox:is(:indeterminate, [data-indeterminate])::before {
|
|
914
|
+
content: "–" / "";
|
|
915
|
+
}
|
|
916
|
+
.lu-radio:checked::before {
|
|
917
|
+
border: 0.3125rem solid var(--lu-primary);
|
|
918
|
+
}
|
|
919
|
+
.lu-switch {
|
|
920
|
+
appearance: none;
|
|
921
|
+
display: inline-block;
|
|
922
|
+
flex: none;
|
|
923
|
+
position: relative;
|
|
924
|
+
box-sizing: border-box;
|
|
925
|
+
inline-size: 2.5rem;
|
|
926
|
+
block-size: 1.5rem;
|
|
927
|
+
margin: 0;
|
|
928
|
+
border: 1px solid var(--lu-input);
|
|
929
|
+
border-radius: 999px;
|
|
930
|
+
background: var(--lu-input);
|
|
931
|
+
vertical-align: middle;
|
|
932
|
+
cursor: pointer;
|
|
933
|
+
}
|
|
934
|
+
/* The thumb's side tells on from off, not only the track's colour. */
|
|
935
|
+
.lu-switch::before {
|
|
936
|
+
content: "";
|
|
937
|
+
position: absolute;
|
|
938
|
+
inset-block: 1px;
|
|
939
|
+
inset-inline-start: 1px;
|
|
940
|
+
inline-size: calc(1.5rem - 4px);
|
|
941
|
+
border-radius: 50%;
|
|
942
|
+
background: #fff;
|
|
943
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / 0.3);
|
|
944
|
+
}
|
|
945
|
+
.lu-switch:checked {
|
|
946
|
+
border-color: var(--lu-primary);
|
|
947
|
+
background: var(--lu-primary);
|
|
948
|
+
}
|
|
949
|
+
.lu-switch:checked::before {
|
|
950
|
+
inset-inline-start: calc(100% - 1.5rem + 3px);
|
|
951
|
+
}
|
|
952
|
+
:is(.lu-checkbox, .lu-radio, .lu-switch):focus-visible {
|
|
953
|
+
outline: 2px solid var(--lu-ring);
|
|
954
|
+
outline-offset: 2px;
|
|
955
|
+
}
|
|
956
|
+
:is(.lu-checkbox, .lu-radio):focus-visible {
|
|
957
|
+
outline-offset: -1px;
|
|
958
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
959
|
+
}
|
|
960
|
+
:is(.lu-checkbox, .lu-radio, .lu-switch):disabled {
|
|
961
|
+
opacity: 0.5;
|
|
962
|
+
cursor: not-allowed;
|
|
963
|
+
}
|
|
964
|
+
:is(.lu-checkbox, .lu-radio)[aria-invalid="true"]::before,
|
|
965
|
+
.lu-switch[aria-invalid="true"] {
|
|
966
|
+
border-color: light-dark(var(--lu-destructive), #f87171);
|
|
967
|
+
}
|
|
968
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
969
|
+
.lu-switch,
|
|
970
|
+
.lu-switch::before {
|
|
971
|
+
transition:
|
|
972
|
+
background-color 120ms ease-out,
|
|
973
|
+
inset-inline-start 120ms ease-out;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/* Collapsible and Accordion (TASK-370) ------------------------------------------------------ */
|
|
978
|
+
|
|
979
|
+
/*
|
|
980
|
+
* The trigger: a row with a chevron that turns while the panel is open (a shape, not only a
|
|
981
|
+
* colour), a 36px target. The panel's height animates between 0 and the size the client script
|
|
982
|
+
* measures (--lu-collapsible-panel-height, --lu-accordion-panel-height), and `::details-content` stays
|
|
983
|
+
* visible while it closes. Spacers inside the panel keep its content's focus rings clear of the
|
|
984
|
+
* clipping the animation needs.
|
|
985
|
+
*/
|
|
986
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary {
|
|
987
|
+
display: flex;
|
|
988
|
+
align-items: center;
|
|
989
|
+
justify-content: space-between;
|
|
990
|
+
gap: 0.75rem;
|
|
991
|
+
min-block-size: 2.25rem;
|
|
992
|
+
padding: 0.5rem 0.25rem;
|
|
993
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
994
|
+
color: var(--lu-foreground);
|
|
995
|
+
font-size: 0.875rem;
|
|
996
|
+
font-weight: 500;
|
|
997
|
+
line-height: 1.25;
|
|
998
|
+
list-style: none;
|
|
999
|
+
cursor: pointer;
|
|
1000
|
+
}
|
|
1001
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary::-webkit-details-marker {
|
|
1002
|
+
display: none;
|
|
1003
|
+
}
|
|
1004
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary::after {
|
|
1005
|
+
content: "";
|
|
1006
|
+
flex: none;
|
|
1007
|
+
inline-size: 0.4375rem;
|
|
1008
|
+
block-size: 0.4375rem;
|
|
1009
|
+
/* Physical sides: rotated, they draw a down chevron in either direction (TASK-385). */
|
|
1010
|
+
border-bottom: 1.5px solid currentColor;
|
|
1011
|
+
border-right: 1.5px solid currentColor;
|
|
1012
|
+
rotate: 45deg;
|
|
1013
|
+
translate: 0 -25%;
|
|
1014
|
+
}
|
|
1015
|
+
:is(.lu-collapsible, .lu-accordion > details)[open] > summary::after {
|
|
1016
|
+
rotate: 225deg;
|
|
1017
|
+
translate: 0 25%;
|
|
1018
|
+
}
|
|
1019
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary:hover {
|
|
1020
|
+
text-decoration: underline;
|
|
1021
|
+
text-underline-offset: 0.2em;
|
|
1022
|
+
}
|
|
1023
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary:focus-visible {
|
|
1024
|
+
outline: 2px solid var(--lu-ring);
|
|
1025
|
+
outline-offset: 2px;
|
|
1026
|
+
}
|
|
1027
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary[aria-disabled="true"] {
|
|
1028
|
+
color: color-mix(in srgb, var(--lu-muted-foreground) 55%, transparent);
|
|
1029
|
+
}
|
|
1030
|
+
.lu-accordion > details > summary > :is(h1, h2, h3, h4, h5, h6) {
|
|
1031
|
+
margin: 0;
|
|
1032
|
+
font: inherit;
|
|
1033
|
+
}
|
|
1034
|
+
.lu-accordion > details {
|
|
1035
|
+
border-block-end: 1px solid var(--lu-border);
|
|
1036
|
+
}
|
|
1037
|
+
:is(.lu-collapsible, .lu-accordion > details) > :not(summary) {
|
|
1038
|
+
overflow: hidden;
|
|
1039
|
+
padding-inline: 0.25rem;
|
|
1040
|
+
color: var(--lu-muted-foreground);
|
|
1041
|
+
font-size: 0.875rem;
|
|
1042
|
+
line-height: 1.5;
|
|
1043
|
+
}
|
|
1044
|
+
:is(.lu-collapsible, .lu-accordion > details) > :not(summary)::before,
|
|
1045
|
+
:is(.lu-collapsible, .lu-accordion > details) > :not(summary)::after {
|
|
1046
|
+
content: "";
|
|
1047
|
+
display: block;
|
|
1048
|
+
block-size: 0.25rem;
|
|
1049
|
+
}
|
|
1050
|
+
:is(.lu-collapsible, .lu-accordion > details) > :not(summary)::after {
|
|
1051
|
+
block-size: 0.75rem;
|
|
1052
|
+
}
|
|
1053
|
+
.lu-collapsible > :not(summary) {
|
|
1054
|
+
block-size: var(--lu-collapsible-panel-height, auto);
|
|
1055
|
+
}
|
|
1056
|
+
.lu-accordion > details > :not(summary) {
|
|
1057
|
+
block-size: var(--lu-accordion-panel-height, auto);
|
|
1058
|
+
}
|
|
1059
|
+
:is(.lu-collapsible, .lu-accordion > details) > :is([data-starting-style], [data-ending-style]) {
|
|
1060
|
+
block-size: 0;
|
|
1061
|
+
}
|
|
1062
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1063
|
+
:is(.lu-collapsible, .lu-accordion > details)::details-content {
|
|
1064
|
+
transition: content-visibility 200ms allow-discrete;
|
|
1065
|
+
}
|
|
1066
|
+
:is(.lu-collapsible, .lu-accordion > details) > :not(summary) {
|
|
1067
|
+
transition: block-size 200ms ease-out;
|
|
1068
|
+
}
|
|
1069
|
+
:is(.lu-collapsible, .lu-accordion > details) > summary::after {
|
|
1070
|
+
transition:
|
|
1071
|
+
rotate 200ms ease-out,
|
|
1072
|
+
translate 200ms ease-out;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/* Toast (TASK-371) -------------------------------------------------------------------------- */
|
|
1077
|
+
|
|
1078
|
+
/*
|
|
1079
|
+
* The viewport: a column at the window's bottom end, the newest toast nearest the corner. A toast:
|
|
1080
|
+
* a popover surface with its title, description and buttons, the close button a 28px target. It
|
|
1081
|
+
* slides in, fades out, follows a swipe and leaves in its direction. An error toast has a red
|
|
1082
|
+
* edge besides its text.
|
|
1083
|
+
*/
|
|
1084
|
+
.lu-toast-viewport {
|
|
1085
|
+
box-sizing: border-box;
|
|
1086
|
+
display: flex;
|
|
1087
|
+
flex-direction: column-reverse;
|
|
1088
|
+
gap: 0.5rem;
|
|
1089
|
+
inline-size: min(24rem, 100vw);
|
|
1090
|
+
padding: 1rem;
|
|
1091
|
+
border-radius: var(--lu-radius);
|
|
1092
|
+
}
|
|
1093
|
+
.lu-toast-viewport:focus-visible {
|
|
1094
|
+
outline: 2px solid var(--lu-ring);
|
|
1095
|
+
outline-offset: -2px;
|
|
1096
|
+
}
|
|
1097
|
+
.lu-toast {
|
|
1098
|
+
display: grid;
|
|
1099
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
1100
|
+
align-items: start;
|
|
1101
|
+
gap: 0.25rem 0.75rem;
|
|
1102
|
+
padding: 0.875rem 0.75rem 0.875rem 1rem;
|
|
1103
|
+
border: 1px solid var(--lu-border);
|
|
1104
|
+
border-radius: var(--lu-radius);
|
|
1105
|
+
background: var(--lu-popover);
|
|
1106
|
+
color: var(--lu-popover-foreground);
|
|
1107
|
+
box-shadow:
|
|
1108
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
1109
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1110
|
+
font-size: 0.875rem;
|
|
1111
|
+
line-height: 1.4;
|
|
1112
|
+
translate: var(--lu-toast-swipe-movement-x, 0) var(--lu-toast-swipe-movement-y, 0);
|
|
1113
|
+
}
|
|
1114
|
+
.lu-toast > * {
|
|
1115
|
+
grid-column: 1;
|
|
1116
|
+
}
|
|
1117
|
+
.lu-toast :where(h2) {
|
|
1118
|
+
margin: 0;
|
|
1119
|
+
font-size: 0.875rem;
|
|
1120
|
+
font-weight: 600;
|
|
1121
|
+
}
|
|
1122
|
+
.lu-toast :where(p) {
|
|
1123
|
+
margin: 0;
|
|
1124
|
+
color: var(--lu-muted-foreground);
|
|
1125
|
+
}
|
|
1126
|
+
.lu-toast :where(.lu-button) {
|
|
1127
|
+
justify-self: start;
|
|
1128
|
+
margin-block-start: 0.5rem;
|
|
1129
|
+
}
|
|
1130
|
+
.lu-toast > [command="--close-toast"] {
|
|
1131
|
+
grid-column: 2;
|
|
1132
|
+
grid-row: 1;
|
|
1133
|
+
display: inline-grid;
|
|
1134
|
+
place-items: center;
|
|
1135
|
+
inline-size: 1.75rem;
|
|
1136
|
+
block-size: 1.75rem;
|
|
1137
|
+
margin-block: -0.25rem;
|
|
1138
|
+
padding: 0;
|
|
1139
|
+
border: 0;
|
|
1140
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
1141
|
+
background: transparent;
|
|
1142
|
+
color: var(--lu-muted-foreground);
|
|
1143
|
+
font: inherit;
|
|
1144
|
+
font-size: 1rem;
|
|
1145
|
+
line-height: 1;
|
|
1146
|
+
cursor: pointer;
|
|
1147
|
+
}
|
|
1148
|
+
.lu-toast > [command="--close-toast"]:hover {
|
|
1149
|
+
background: var(--lu-accent);
|
|
1150
|
+
color: var(--lu-accent-foreground);
|
|
1151
|
+
}
|
|
1152
|
+
.lu-toast > [command="--close-toast"]:focus-visible {
|
|
1153
|
+
outline: 2px solid var(--lu-ring);
|
|
1154
|
+
outline-offset: 0;
|
|
1155
|
+
}
|
|
1156
|
+
.lu-toast[data-type="error"] {
|
|
1157
|
+
border-inline-start: 4px solid var(--lu-destructive);
|
|
1158
|
+
}
|
|
1159
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1160
|
+
.lu-toast {
|
|
1161
|
+
transition:
|
|
1162
|
+
opacity 200ms ease-out,
|
|
1163
|
+
translate 200ms ease-out;
|
|
1164
|
+
}
|
|
1165
|
+
.lu-toast[data-starting-style] {
|
|
1166
|
+
opacity: 0;
|
|
1167
|
+
translate: 0 0.75rem;
|
|
1168
|
+
}
|
|
1169
|
+
.lu-toast[data-ending-style] {
|
|
1170
|
+
opacity: 0;
|
|
1171
|
+
}
|
|
1172
|
+
.lu-toast[data-ending-style][data-swipe-direction="right"] {
|
|
1173
|
+
translate: calc(100% + 1rem) 0;
|
|
1174
|
+
}
|
|
1175
|
+
.lu-toast[data-ending-style][data-swipe-direction="left"] {
|
|
1176
|
+
translate: calc(-100% - 1rem) 0;
|
|
1177
|
+
}
|
|
1178
|
+
.lu-toast[data-ending-style][data-swipe-direction="down"] {
|
|
1179
|
+
translate: 0 calc(100% + 1rem);
|
|
1180
|
+
}
|
|
1181
|
+
.lu-toast[data-ending-style][data-swipe-direction="up"] {
|
|
1182
|
+
translate: 0 calc(-100% - 1rem);
|
|
1183
|
+
}
|
|
1184
|
+
.lu-toast[data-swiping] {
|
|
1185
|
+
transition: none;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/* Toggle and Toggle Group (TASK-369) -------------------------------------------------------- */
|
|
1190
|
+
|
|
1191
|
+
.lu-toggle {
|
|
1192
|
+
display: inline-grid;
|
|
1193
|
+
place-items: center;
|
|
1194
|
+
min-inline-size: 2.25rem;
|
|
1195
|
+
min-block-size: 2.25rem;
|
|
1196
|
+
padding: 0.375rem 0.625rem;
|
|
1197
|
+
border: 1px solid var(--lu-input);
|
|
1198
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1199
|
+
background: var(--lu-background);
|
|
1200
|
+
color: var(--lu-foreground);
|
|
1201
|
+
font: inherit;
|
|
1202
|
+
font-size: 0.875rem;
|
|
1203
|
+
font-weight: 500;
|
|
1204
|
+
line-height: 1.25;
|
|
1205
|
+
cursor: pointer;
|
|
1206
|
+
}
|
|
1207
|
+
.lu-toggle:hover {
|
|
1208
|
+
background: var(--lu-accent);
|
|
1209
|
+
}
|
|
1210
|
+
/* Pressed: a filled surface and a bar along the bottom, a shape and not only a colour. */
|
|
1211
|
+
.lu-toggle[aria-pressed="true"] {
|
|
1212
|
+
background: var(--lu-accent);
|
|
1213
|
+
color: var(--lu-accent-foreground);
|
|
1214
|
+
box-shadow: inset 0 -3px 0 var(--lu-foreground);
|
|
1215
|
+
}
|
|
1216
|
+
.lu-toggle:focus-visible {
|
|
1217
|
+
outline: 2px solid var(--lu-ring);
|
|
1218
|
+
outline-offset: 2px;
|
|
1219
|
+
}
|
|
1220
|
+
.lu-toggle:disabled {
|
|
1221
|
+
opacity: 0.5;
|
|
1222
|
+
cursor: not-allowed;
|
|
1223
|
+
}
|
|
1224
|
+
.lu-toggle-group {
|
|
1225
|
+
display: inline-flex;
|
|
1226
|
+
flex-wrap: wrap;
|
|
1227
|
+
gap: 0.25rem;
|
|
1228
|
+
}
|
|
1229
|
+
.lu-toggle-group[data-orientation="vertical"] {
|
|
1230
|
+
flex-direction: column;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
/* Progress and Meter (TASK-373) ------------------------------------------------------------- */
|
|
1234
|
+
|
|
1235
|
+
.lu-progress,
|
|
1236
|
+
.lu-meter {
|
|
1237
|
+
display: grid;
|
|
1238
|
+
grid-template-columns: 1fr auto;
|
|
1239
|
+
align-items: baseline;
|
|
1240
|
+
gap: 0.375rem 1rem;
|
|
1241
|
+
inline-size: min(20rem, 100%);
|
|
1242
|
+
font-size: 0.875rem;
|
|
1243
|
+
}
|
|
1244
|
+
.lu-progress > :where(label),
|
|
1245
|
+
.lu-meter > :where(label) {
|
|
1246
|
+
font-weight: 500;
|
|
1247
|
+
}
|
|
1248
|
+
.lu-progress > :where(span),
|
|
1249
|
+
.lu-meter > :where(span) {
|
|
1250
|
+
color: var(--lu-muted-foreground);
|
|
1251
|
+
font-variant-numeric: tabular-nums;
|
|
1252
|
+
}
|
|
1253
|
+
/*
|
|
1254
|
+
* The bar: its edge in --lu-input (3:1, so the full range shows), the value in the primary
|
|
1255
|
+
* colour (a lighter blue in dark, 3:1 against the bar there too).
|
|
1256
|
+
*/
|
|
1257
|
+
.lu-progress > :where(progress),
|
|
1258
|
+
.lu-meter > :where(meter) {
|
|
1259
|
+
grid-column: 1 / -1;
|
|
1260
|
+
appearance: none;
|
|
1261
|
+
box-sizing: border-box;
|
|
1262
|
+
inline-size: 100%;
|
|
1263
|
+
block-size: 0.625rem;
|
|
1264
|
+
border: 1px solid var(--lu-input);
|
|
1265
|
+
border-radius: 999px;
|
|
1266
|
+
background: var(--lu-background);
|
|
1267
|
+
overflow: hidden;
|
|
1268
|
+
--lu-bar: light-dark(var(--lu-primary), #60a5fa);
|
|
1269
|
+
}
|
|
1270
|
+
.lu-progress > progress::-webkit-progress-bar {
|
|
1271
|
+
background: transparent;
|
|
1272
|
+
}
|
|
1273
|
+
.lu-progress > progress::-webkit-progress-value {
|
|
1274
|
+
border-radius: inherit;
|
|
1275
|
+
background: var(--lu-bar);
|
|
1276
|
+
}
|
|
1277
|
+
.lu-progress > progress::-moz-progress-bar {
|
|
1278
|
+
border-radius: inherit;
|
|
1279
|
+
background: var(--lu-bar);
|
|
1280
|
+
}
|
|
1281
|
+
/* Indeterminate: a segment that slides, still where motion is reduced. */
|
|
1282
|
+
.lu-progress > progress:indeterminate {
|
|
1283
|
+
background-image: linear-gradient(
|
|
1284
|
+
to right,
|
|
1285
|
+
transparent 0 35%,
|
|
1286
|
+
var(--lu-bar) 35% 65%,
|
|
1287
|
+
transparent 65%
|
|
1288
|
+
);
|
|
1289
|
+
background-size: 200% 100%;
|
|
1290
|
+
}
|
|
1291
|
+
.lu-progress > progress:indeterminate::-moz-progress-bar {
|
|
1292
|
+
background: transparent;
|
|
1293
|
+
}
|
|
1294
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1295
|
+
.lu-progress > progress:indeterminate {
|
|
1296
|
+
animation: lu-progress-slide 1.4s linear infinite;
|
|
1297
|
+
}
|
|
1298
|
+
/*
|
|
1299
|
+
* Right to left, the segment slides the other way (TASK-385). Not `:dir(rtl)`: Lightning CSS
|
|
1300
|
+
* lowers it to a list of `:lang()`s, which misses a `dir` attribute.
|
|
1301
|
+
*/
|
|
1302
|
+
:where([dir="rtl"]) .lu-progress > progress:indeterminate {
|
|
1303
|
+
animation-direction: reverse;
|
|
1304
|
+
}
|
|
1305
|
+
:where([dir="rtl"]) :where([dir="ltr"]) .lu-progress > progress:indeterminate {
|
|
1306
|
+
animation-direction: normal;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
@keyframes lu-progress-slide {
|
|
1310
|
+
from {
|
|
1311
|
+
background-position: 100% 0;
|
|
1312
|
+
}
|
|
1313
|
+
to {
|
|
1314
|
+
background-position: -100% 0;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
.lu-meter > meter::-webkit-meter-bar {
|
|
1318
|
+
border: 0;
|
|
1319
|
+
background: transparent;
|
|
1320
|
+
}
|
|
1321
|
+
.lu-meter > meter::-webkit-meter-optimum-value,
|
|
1322
|
+
.lu-meter > meter::-webkit-meter-suboptimum-value,
|
|
1323
|
+
.lu-meter > meter::-webkit-meter-even-less-good-value {
|
|
1324
|
+
border-radius: inherit;
|
|
1325
|
+
background: var(--lu-bar);
|
|
1326
|
+
}
|
|
1327
|
+
.lu-meter > meter::-moz-meter-bar {
|
|
1328
|
+
border-radius: inherit;
|
|
1329
|
+
background: var(--lu-bar);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/* Slider (TASK-372) ------------------------------------------------------------------------- */
|
|
1333
|
+
|
|
1334
|
+
.lu-slider {
|
|
1335
|
+
display: grid;
|
|
1336
|
+
grid-template-columns: 1fr auto;
|
|
1337
|
+
align-items: baseline;
|
|
1338
|
+
gap: 0.25rem 1rem;
|
|
1339
|
+
inline-size: min(20rem, 100%);
|
|
1340
|
+
font-size: 0.875rem;
|
|
1341
|
+
--lu-bar: light-dark(var(--lu-primary), #60a5fa);
|
|
1342
|
+
/* The thumbs' size: slider.css lines the track up with their centres. */
|
|
1343
|
+
--lu-slider-thumb-size: 1.5rem;
|
|
1344
|
+
}
|
|
1345
|
+
.lu-slider > :where(label) {
|
|
1346
|
+
font-weight: 500;
|
|
1347
|
+
}
|
|
1348
|
+
.lu-slider > :where(output) {
|
|
1349
|
+
color: var(--lu-muted-foreground);
|
|
1350
|
+
font-variant-numeric: tabular-nums;
|
|
1351
|
+
}
|
|
1352
|
+
/* The control: a 24px tall strip (the thumbs' target), the full width. */
|
|
1353
|
+
.lu-slider > :where(div) {
|
|
1354
|
+
grid-column: 1 / -1;
|
|
1355
|
+
block-size: 1.5rem;
|
|
1356
|
+
}
|
|
1357
|
+
/* Center alignment: the thumbs overhang the control, inside the slider's box. */
|
|
1358
|
+
.lu-slider[data-thumb-alignment="center"] > :where(div) {
|
|
1359
|
+
margin-inline: calc(var(--lu-slider-thumb-size) / 2);
|
|
1360
|
+
}
|
|
1361
|
+
.lu-slider[data-orientation="vertical"] > :where(div) {
|
|
1362
|
+
grid-column: auto;
|
|
1363
|
+
inline-size: 1.5rem;
|
|
1364
|
+
block-size: 10rem;
|
|
1365
|
+
}
|
|
1366
|
+
/* The track: --lu-input at its edge (3:1), the selected part in the primary colour. */
|
|
1367
|
+
.lu-slider > div > :where(div) {
|
|
1368
|
+
box-sizing: border-box;
|
|
1369
|
+
block-size: 0.5rem;
|
|
1370
|
+
border: 1px solid var(--lu-input);
|
|
1371
|
+
border-radius: 999px;
|
|
1372
|
+
background: var(--lu-background);
|
|
1373
|
+
}
|
|
1374
|
+
.lu-slider[data-orientation="vertical"] > div > :where(div) {
|
|
1375
|
+
inline-size: 0.5rem;
|
|
1376
|
+
block-size: auto;
|
|
1377
|
+
}
|
|
1378
|
+
.lu-slider > div > div > :where(div) {
|
|
1379
|
+
border-radius: inherit;
|
|
1380
|
+
background: var(--lu-bar);
|
|
1381
|
+
}
|
|
1382
|
+
/* In the thumb's own writing mode: a vertical thumb's block size is its width. */
|
|
1383
|
+
.lu-slider :where(input[type="range"]) {
|
|
1384
|
+
block-size: var(--lu-slider-thumb-size);
|
|
1385
|
+
cursor: pointer;
|
|
1386
|
+
}
|
|
1387
|
+
/* The thumb: a 24px circle with a primary edge; focus adds a ring around it. */
|
|
1388
|
+
.lu-slider input[type="range"]::-webkit-slider-thumb {
|
|
1389
|
+
appearance: none;
|
|
1390
|
+
box-sizing: border-box;
|
|
1391
|
+
inline-size: var(--lu-slider-thumb-size);
|
|
1392
|
+
block-size: var(--lu-slider-thumb-size);
|
|
1393
|
+
border: 2px solid var(--lu-bar);
|
|
1394
|
+
border-radius: 50%;
|
|
1395
|
+
background: var(--lu-background);
|
|
1396
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 0.3);
|
|
1397
|
+
}
|
|
1398
|
+
.lu-slider input[type="range"]::-moz-range-thumb {
|
|
1399
|
+
box-sizing: border-box;
|
|
1400
|
+
inline-size: var(--lu-slider-thumb-size);
|
|
1401
|
+
block-size: var(--lu-slider-thumb-size);
|
|
1402
|
+
border: 2px solid var(--lu-bar);
|
|
1403
|
+
border-radius: 50%;
|
|
1404
|
+
background: var(--lu-background);
|
|
1405
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 0.3);
|
|
1406
|
+
}
|
|
1407
|
+
.lu-slider input[type="range"]:focus-visible {
|
|
1408
|
+
outline: none;
|
|
1409
|
+
}
|
|
1410
|
+
.lu-slider input[type="range"]:focus-visible::-webkit-slider-thumb {
|
|
1411
|
+
outline: 2px solid var(--lu-ring);
|
|
1412
|
+
outline-offset: 2px;
|
|
1413
|
+
}
|
|
1414
|
+
.lu-slider input[type="range"]:focus-visible::-moz-range-thumb {
|
|
1415
|
+
outline: 2px solid var(--lu-ring);
|
|
1416
|
+
outline-offset: 2px;
|
|
1417
|
+
}
|
|
1418
|
+
.lu-slider input[type="range"]:disabled {
|
|
1419
|
+
opacity: 0.5;
|
|
1420
|
+
cursor: not-allowed;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/* Drawer (TASK-382) ------------------------------------------------------------------------- */
|
|
1424
|
+
|
|
1425
|
+
/*
|
|
1426
|
+
* A popover surface against its edge, rounded on the inside; a bottom sheet has a handle (a
|
|
1427
|
+
* decoration: the close buttons and Escape do what a swipe does). It slides in and out from its
|
|
1428
|
+
* edge, follows a swipe, and leaves from where the swipe let go; the backdrop fades with it.
|
|
1429
|
+
*/
|
|
1430
|
+
.lu-drawer {
|
|
1431
|
+
box-sizing: border-box;
|
|
1432
|
+
padding: 1.5rem;
|
|
1433
|
+
border: 1px solid var(--lu-border);
|
|
1434
|
+
background: var(--lu-popover);
|
|
1435
|
+
color: var(--lu-popover-foreground);
|
|
1436
|
+
box-shadow:
|
|
1437
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
1438
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1439
|
+
translate: var(--lu-drawer-swipe-movement-x, 0) var(--lu-drawer-swipe-movement-y, 0);
|
|
1440
|
+
}
|
|
1441
|
+
.lu-drawer::backdrop {
|
|
1442
|
+
background: rgb(0 0 0 / 0.5);
|
|
1443
|
+
opacity: calc(1 - var(--lu-drawer-swipe-progress, 0));
|
|
1444
|
+
}
|
|
1445
|
+
.lu-drawer[data-swipe-direction="down"] {
|
|
1446
|
+
max-block-size: 85dvh;
|
|
1447
|
+
padding-block-start: 2rem;
|
|
1448
|
+
border-block-end: 0;
|
|
1449
|
+
border-radius: var(--lu-radius) var(--lu-radius) 0 0;
|
|
1450
|
+
}
|
|
1451
|
+
.lu-drawer[data-swipe-direction="down"]::before {
|
|
1452
|
+
content: "";
|
|
1453
|
+
position: absolute;
|
|
1454
|
+
inset-block-start: 0.75rem;
|
|
1455
|
+
inset-inline-start: 50%;
|
|
1456
|
+
inline-size: 2.5rem;
|
|
1457
|
+
block-size: 0.25rem;
|
|
1458
|
+
border-radius: 999px;
|
|
1459
|
+
background: var(--lu-input);
|
|
1460
|
+
translate: -50% 0;
|
|
1461
|
+
}
|
|
1462
|
+
.lu-drawer[data-swipe-direction="up"] {
|
|
1463
|
+
max-block-size: 85dvh;
|
|
1464
|
+
border-block-start: 0;
|
|
1465
|
+
border-radius: 0 0 var(--lu-radius) var(--lu-radius);
|
|
1466
|
+
}
|
|
1467
|
+
.lu-drawer:is([data-swipe-direction="left"], [data-swipe-direction="right"]) {
|
|
1468
|
+
inline-size: min(22rem, 100vw - 3rem);
|
|
1469
|
+
}
|
|
1470
|
+
.lu-drawer[data-swipe-direction="left"] {
|
|
1471
|
+
border-inline-start: 0;
|
|
1472
|
+
border-start-end-radius: var(--lu-radius);
|
|
1473
|
+
border-end-end-radius: var(--lu-radius);
|
|
1474
|
+
}
|
|
1475
|
+
.lu-drawer[data-swipe-direction="right"] {
|
|
1476
|
+
border-inline-end: 0;
|
|
1477
|
+
border-start-start-radius: var(--lu-radius);
|
|
1478
|
+
border-end-start-radius: var(--lu-radius);
|
|
1479
|
+
}
|
|
1480
|
+
.lu-drawer :where(h2) {
|
|
1481
|
+
margin: 0 0 0.5rem;
|
|
1482
|
+
font-size: 1.125rem;
|
|
1483
|
+
font-weight: 600;
|
|
1484
|
+
line-height: 1.3;
|
|
1485
|
+
}
|
|
1486
|
+
.lu-drawer :where(p) {
|
|
1487
|
+
margin: 0 0 1.5rem;
|
|
1488
|
+
color: var(--lu-muted-foreground);
|
|
1489
|
+
font-size: 0.875rem;
|
|
1490
|
+
line-height: 1.5;
|
|
1491
|
+
}
|
|
1492
|
+
.lu-drawer :where(footer) {
|
|
1493
|
+
display: flex;
|
|
1494
|
+
flex-wrap: wrap;
|
|
1495
|
+
justify-content: end;
|
|
1496
|
+
gap: 0.5rem;
|
|
1497
|
+
}
|
|
1498
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1499
|
+
.lu-drawer,
|
|
1500
|
+
.lu-drawer::backdrop {
|
|
1501
|
+
transition:
|
|
1502
|
+
translate 250ms ease-out,
|
|
1503
|
+
opacity 250ms ease-out,
|
|
1504
|
+
overlay 250ms allow-discrete,
|
|
1505
|
+
display 250ms allow-discrete;
|
|
1506
|
+
}
|
|
1507
|
+
.lu-drawer[data-swiping],
|
|
1508
|
+
.lu-drawer[data-swiping]::backdrop {
|
|
1509
|
+
transition: none;
|
|
1510
|
+
}
|
|
1511
|
+
.lu-drawer:not([open])::backdrop {
|
|
1512
|
+
opacity: 0;
|
|
1513
|
+
}
|
|
1514
|
+
.lu-drawer[data-swipe-direction="down"]:not([open]) {
|
|
1515
|
+
translate: 0 100%;
|
|
1516
|
+
}
|
|
1517
|
+
.lu-drawer[data-swipe-direction="up"]:not([open]) {
|
|
1518
|
+
translate: 0 -100%;
|
|
1519
|
+
}
|
|
1520
|
+
.lu-drawer[data-swipe-direction="left"]:not([open]) {
|
|
1521
|
+
translate: -100% 0;
|
|
1522
|
+
}
|
|
1523
|
+
.lu-drawer[data-swipe-direction="right"]:not([open]) {
|
|
1524
|
+
translate: 100% 0;
|
|
1525
|
+
}
|
|
1526
|
+
@starting-style {
|
|
1527
|
+
.lu-drawer[open]::backdrop {
|
|
1528
|
+
opacity: 0;
|
|
1529
|
+
}
|
|
1530
|
+
.lu-drawer[data-swipe-direction="down"][open] {
|
|
1531
|
+
translate: 0 100%;
|
|
1532
|
+
}
|
|
1533
|
+
.lu-drawer[data-swipe-direction="up"][open] {
|
|
1534
|
+
translate: 0 -100%;
|
|
1535
|
+
}
|
|
1536
|
+
.lu-drawer[data-swipe-direction="left"][open] {
|
|
1537
|
+
translate: -100% 0;
|
|
1538
|
+
}
|
|
1539
|
+
.lu-drawer[data-swipe-direction="right"][open] {
|
|
1540
|
+
translate: 100% 0;
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
/* Number Field (TASK-375) ------------------------------------------------------------------- */
|
|
1546
|
+
|
|
1547
|
+
.lu-number-field {
|
|
1548
|
+
display: grid;
|
|
1549
|
+
gap: 0.375rem;
|
|
1550
|
+
justify-items: start;
|
|
1551
|
+
font-size: 0.875rem;
|
|
1552
|
+
}
|
|
1553
|
+
.lu-number-field :where(label) {
|
|
1554
|
+
font-weight: 500;
|
|
1555
|
+
}
|
|
1556
|
+
/* The group: one bordered control with the input between its buttons; focus rings all of it. */
|
|
1557
|
+
.lu-number-field > :where(div),
|
|
1558
|
+
.lu-number-field > :where(input:not([type="hidden"])) {
|
|
1559
|
+
display: inline-flex;
|
|
1560
|
+
align-items: stretch;
|
|
1561
|
+
border: 1px solid var(--lu-input);
|
|
1562
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1563
|
+
background: var(--lu-background);
|
|
1564
|
+
color: var(--lu-foreground);
|
|
1565
|
+
}
|
|
1566
|
+
.lu-number-field > div:focus-within,
|
|
1567
|
+
.lu-number-field > input:focus-visible {
|
|
1568
|
+
outline: 2px solid var(--lu-ring);
|
|
1569
|
+
outline-offset: 2px;
|
|
1570
|
+
}
|
|
1571
|
+
.lu-number-field :where(input:not([type="hidden"])) {
|
|
1572
|
+
box-sizing: border-box;
|
|
1573
|
+
inline-size: 8rem;
|
|
1574
|
+
min-block-size: 2.25rem;
|
|
1575
|
+
padding: 0.5rem 0.75rem;
|
|
1576
|
+
font: inherit;
|
|
1577
|
+
font-variant-numeric: tabular-nums;
|
|
1578
|
+
text-align: center;
|
|
1579
|
+
}
|
|
1580
|
+
.lu-number-field > div > :where(input) {
|
|
1581
|
+
border: 0;
|
|
1582
|
+
background: transparent;
|
|
1583
|
+
color: inherit;
|
|
1584
|
+
}
|
|
1585
|
+
.lu-number-field > div > input:focus-visible {
|
|
1586
|
+
outline: none;
|
|
1587
|
+
}
|
|
1588
|
+
.lu-number-field :where(input):disabled {
|
|
1589
|
+
opacity: 0.5;
|
|
1590
|
+
}
|
|
1591
|
+
.lu-number-field :where(button[data-action]) {
|
|
1592
|
+
display: grid;
|
|
1593
|
+
place-items: center;
|
|
1594
|
+
min-inline-size: 2.25rem;
|
|
1595
|
+
padding: 0;
|
|
1596
|
+
border: 0;
|
|
1597
|
+
background: var(--lu-muted);
|
|
1598
|
+
color: var(--lu-foreground);
|
|
1599
|
+
font: inherit;
|
|
1600
|
+
font-size: 1rem;
|
|
1601
|
+
cursor: pointer;
|
|
1602
|
+
}
|
|
1603
|
+
.lu-number-field :where(button[data-action="decrement"]) {
|
|
1604
|
+
border-inline-end: 1px solid var(--lu-input);
|
|
1605
|
+
}
|
|
1606
|
+
.lu-number-field :where(button[data-action="increment"]) {
|
|
1607
|
+
border-inline-start: 1px solid var(--lu-input);
|
|
1608
|
+
}
|
|
1609
|
+
.lu-number-field button[data-action]:hover:not(:disabled) {
|
|
1610
|
+
background: var(--lu-accent);
|
|
1611
|
+
}
|
|
1612
|
+
.lu-number-field button[data-action]:disabled {
|
|
1613
|
+
color: var(--lu-muted-foreground);
|
|
1614
|
+
cursor: not-allowed;
|
|
1615
|
+
}
|
|
1616
|
+
/* A scrub area reads as part of the label; dragging it shows the resize cursor everywhere. */
|
|
1617
|
+
.lu-number-field[data-scrubbing],
|
|
1618
|
+
.lu-number-field[data-scrubbing] * {
|
|
1619
|
+
cursor: ew-resize;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/* Separator and Avatar (TASK-374) ----------------------------------------------------------- */
|
|
1623
|
+
|
|
1624
|
+
/* A decorative line in --lu-border: a separator groups content, it is not needed to read it. */
|
|
1625
|
+
.lu-separator {
|
|
1626
|
+
flex: none;
|
|
1627
|
+
block-size: 1px;
|
|
1628
|
+
margin: 0.75rem 0;
|
|
1629
|
+
border: 0;
|
|
1630
|
+
background: var(--lu-border);
|
|
1631
|
+
}
|
|
1632
|
+
.lu-separator[data-orientation="vertical"] {
|
|
1633
|
+
inline-size: 1px;
|
|
1634
|
+
block-size: auto;
|
|
1635
|
+
margin: 0;
|
|
1636
|
+
}
|
|
1637
|
+
.lu-avatar {
|
|
1638
|
+
place-items: center;
|
|
1639
|
+
inline-size: 2.5rem;
|
|
1640
|
+
block-size: 2.5rem;
|
|
1641
|
+
overflow: hidden;
|
|
1642
|
+
border-radius: 50%;
|
|
1643
|
+
background: var(--lu-muted);
|
|
1644
|
+
color: var(--lu-muted-foreground);
|
|
1645
|
+
font-size: 0.875rem;
|
|
1646
|
+
font-weight: 500;
|
|
1647
|
+
line-height: 1;
|
|
1648
|
+
vertical-align: middle;
|
|
1649
|
+
user-select: none;
|
|
1650
|
+
}
|
|
1651
|
+
.lu-avatar > img {
|
|
1652
|
+
inline-size: 100%;
|
|
1653
|
+
block-size: 100%;
|
|
1654
|
+
object-fit: cover;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
/* OTP Field (TASK-376) ---------------------------------------------------------------------- */
|
|
1658
|
+
|
|
1659
|
+
.lu-otp-field {
|
|
1660
|
+
align-items: center;
|
|
1661
|
+
gap: 0.5rem;
|
|
1662
|
+
max-inline-size: 100%;
|
|
1663
|
+
}
|
|
1664
|
+
/* A box per character; the caret's box gets the focus ring while the input has focus. */
|
|
1665
|
+
.lu-otp-field > :where([data-slot]) {
|
|
1666
|
+
display: grid;
|
|
1667
|
+
place-items: center;
|
|
1668
|
+
box-sizing: border-box;
|
|
1669
|
+
flex: 0 1 2.5rem;
|
|
1670
|
+
min-inline-size: 1.75rem;
|
|
1671
|
+
block-size: 2.75rem;
|
|
1672
|
+
border: 1px solid var(--lu-input);
|
|
1673
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1674
|
+
background: var(--lu-background);
|
|
1675
|
+
color: var(--lu-foreground);
|
|
1676
|
+
font-size: 1.25rem;
|
|
1677
|
+
font-weight: 500;
|
|
1678
|
+
font-variant-numeric: tabular-nums;
|
|
1679
|
+
}
|
|
1680
|
+
.lu-otp-field > [data-slot][data-active] {
|
|
1681
|
+
outline: 2px solid var(--lu-ring);
|
|
1682
|
+
outline-offset: 2px;
|
|
1683
|
+
}
|
|
1684
|
+
/* The caret, in the caret's box while it is empty. */
|
|
1685
|
+
.lu-otp-field > [data-slot][data-active]:not([data-filled])::after {
|
|
1686
|
+
content: "";
|
|
1687
|
+
inline-size: 1px;
|
|
1688
|
+
block-size: 1.25rem;
|
|
1689
|
+
background: var(--lu-foreground);
|
|
1690
|
+
}
|
|
1691
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1692
|
+
.lu-otp-field > [data-slot][data-active]:not([data-filled])::after {
|
|
1693
|
+
animation: lu-otp-caret 1s steps(1) infinite;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
@keyframes lu-otp-caret {
|
|
1697
|
+
50% {
|
|
1698
|
+
opacity: 0;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
.lu-otp-field > :where([data-orientation="horizontal"]) {
|
|
1702
|
+
flex: 0 1 0.75rem;
|
|
1703
|
+
min-inline-size: 0.25rem;
|
|
1704
|
+
block-size: 2px;
|
|
1705
|
+
background: var(--lu-muted-foreground);
|
|
1706
|
+
}
|
|
1707
|
+
.lu-otp-field:has(input:disabled) {
|
|
1708
|
+
opacity: 0.5;
|
|
1709
|
+
}
|
|
1710
|
+
/* Without its script, the input is a plain field: style it as one. */
|
|
1711
|
+
.lu-otp-field:not(:defined) > :where(input) {
|
|
1712
|
+
box-sizing: border-box;
|
|
1713
|
+
min-block-size: 2.25rem;
|
|
1714
|
+
padding: 0.5rem 0.75rem;
|
|
1715
|
+
border: 1px solid var(--lu-input);
|
|
1716
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1717
|
+
background: var(--lu-background);
|
|
1718
|
+
color: var(--lu-foreground);
|
|
1719
|
+
font: inherit;
|
|
1720
|
+
letter-spacing: 0.5em;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/* Preview Card (TASK-381) ------------------------------------------------------------------- */
|
|
1724
|
+
|
|
1725
|
+
.lu-preview-card {
|
|
1726
|
+
--lu-side-offset: 8px;
|
|
1727
|
+
box-sizing: border-box;
|
|
1728
|
+
inline-size: max-content;
|
|
1729
|
+
max-inline-size: min(20rem, 100vw - 1rem);
|
|
1730
|
+
padding: 1rem;
|
|
1731
|
+
border: 1px solid var(--lu-border);
|
|
1732
|
+
border-radius: var(--lu-radius);
|
|
1733
|
+
background: var(--lu-popover);
|
|
1734
|
+
color: var(--lu-popover-foreground);
|
|
1735
|
+
font-size: 0.875rem;
|
|
1736
|
+
line-height: 1.5;
|
|
1737
|
+
box-shadow:
|
|
1738
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
1739
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1740
|
+
}
|
|
1741
|
+
.lu-preview-card :where(img) {
|
|
1742
|
+
display: block;
|
|
1743
|
+
max-inline-size: 100%;
|
|
1744
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1745
|
+
}
|
|
1746
|
+
.lu-preview-card :where(p) {
|
|
1747
|
+
margin: 0.25rem 0 0;
|
|
1748
|
+
color: var(--lu-muted-foreground);
|
|
1749
|
+
}
|
|
1750
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1751
|
+
.lu-preview-card {
|
|
1752
|
+
transition:
|
|
1753
|
+
opacity 150ms ease-out,
|
|
1754
|
+
scale 150ms ease-out,
|
|
1755
|
+
overlay 150ms allow-discrete,
|
|
1756
|
+
display 150ms allow-discrete;
|
|
1757
|
+
}
|
|
1758
|
+
.lu-preview-card:not(:popover-open) {
|
|
1759
|
+
opacity: 0;
|
|
1760
|
+
scale: 0.96;
|
|
1761
|
+
}
|
|
1762
|
+
@starting-style {
|
|
1763
|
+
.lu-preview-card:popover-open {
|
|
1764
|
+
opacity: 0;
|
|
1765
|
+
scale: 0.96;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
/* Toolbar (TASK-383) ------------------------------------------------------------------------ */
|
|
1771
|
+
|
|
1772
|
+
.lu-toolbar {
|
|
1773
|
+
display: flex;
|
|
1774
|
+
flex-wrap: wrap;
|
|
1775
|
+
align-items: center;
|
|
1776
|
+
gap: 0.25rem;
|
|
1777
|
+
inline-size: fit-content;
|
|
1778
|
+
max-inline-size: 100%;
|
|
1779
|
+
box-sizing: border-box;
|
|
1780
|
+
padding: 0.25rem;
|
|
1781
|
+
border: 1px solid var(--lu-border);
|
|
1782
|
+
border-radius: var(--lu-radius);
|
|
1783
|
+
background: var(--lu-background);
|
|
1784
|
+
}
|
|
1785
|
+
.lu-toolbar[data-orientation="vertical"] {
|
|
1786
|
+
flex-direction: column;
|
|
1787
|
+
align-items: stretch;
|
|
1788
|
+
}
|
|
1789
|
+
.lu-toolbar :where([role="group"]) {
|
|
1790
|
+
display: flex;
|
|
1791
|
+
flex-wrap: wrap;
|
|
1792
|
+
gap: 0.25rem;
|
|
1793
|
+
}
|
|
1794
|
+
.lu-toolbar[data-orientation="vertical"] :where([role="group"]) {
|
|
1795
|
+
flex-direction: column;
|
|
1796
|
+
}
|
|
1797
|
+
/* Separators run across the toolbar: a line from top to bottom in a row. */
|
|
1798
|
+
.lu-toolbar :where(hr) {
|
|
1799
|
+
flex: none;
|
|
1800
|
+
align-self: stretch;
|
|
1801
|
+
margin: 0 0.25rem;
|
|
1802
|
+
border: 0;
|
|
1803
|
+
background: var(--lu-border);
|
|
1804
|
+
}
|
|
1805
|
+
.lu-toolbar :where(hr[data-orientation="vertical"]) {
|
|
1806
|
+
inline-size: 1px;
|
|
1807
|
+
block-size: auto;
|
|
1808
|
+
}
|
|
1809
|
+
.lu-toolbar :where(hr[data-orientation="horizontal"]) {
|
|
1810
|
+
inline-size: auto;
|
|
1811
|
+
block-size: 1px;
|
|
1812
|
+
margin: 0.25rem 0;
|
|
1813
|
+
}
|
|
1814
|
+
/* A link is an item like the buttons: as tall, with room around its text (2.5.8). */
|
|
1815
|
+
.lu-toolbar :where(a) {
|
|
1816
|
+
display: inline-flex;
|
|
1817
|
+
align-items: center;
|
|
1818
|
+
min-block-size: 2.25rem;
|
|
1819
|
+
padding: 0 0.5rem;
|
|
1820
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1821
|
+
font-size: 0.875rem;
|
|
1822
|
+
}
|
|
1823
|
+
.lu-toolbar :where(a):focus-visible {
|
|
1824
|
+
outline: 2px solid var(--lu-ring);
|
|
1825
|
+
outline-offset: 2px;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
/* Scroll Area (TASK-384) -------------------------------------------------------------------- */
|
|
1829
|
+
|
|
1830
|
+
.lu-scroll-area {
|
|
1831
|
+
box-sizing: border-box;
|
|
1832
|
+
border: 1px solid var(--lu-border);
|
|
1833
|
+
border-radius: var(--lu-radius);
|
|
1834
|
+
background: var(--lu-background);
|
|
1835
|
+
}
|
|
1836
|
+
/* Inside the box, which clips: the ring is drawn inward. */
|
|
1837
|
+
.lu-scroll-area :where([data-viewport]):focus-visible {
|
|
1838
|
+
outline: 2px solid var(--lu-ring);
|
|
1839
|
+
outline-offset: -2px;
|
|
1840
|
+
}
|
|
1841
|
+
.lu-scroll-area :where([data-viewport]) > :where(div) {
|
|
1842
|
+
padding: 0.75rem 1rem;
|
|
1843
|
+
}
|
|
1844
|
+
.lu-scroll-area :where([data-scrollbar]) {
|
|
1845
|
+
padding: 2px;
|
|
1846
|
+
opacity: 0;
|
|
1847
|
+
}
|
|
1848
|
+
/* 4px at the track's ends, where the thumb's larger target (below) reaches. */
|
|
1849
|
+
.lu-scroll-area :where([data-scrollbar][data-orientation="vertical"]) {
|
|
1850
|
+
inline-size: 10px;
|
|
1851
|
+
padding-block: 4px;
|
|
1852
|
+
}
|
|
1853
|
+
.lu-scroll-area :where([data-scrollbar][data-orientation="horizontal"]) {
|
|
1854
|
+
block-size: 10px;
|
|
1855
|
+
padding-inline: 4px;
|
|
1856
|
+
}
|
|
1857
|
+
/* Shown while the pointer is over the area, while it scrolls, and while it has focus. */
|
|
1858
|
+
.lu-scroll-area :where([data-scrollbar]):is([data-hovering], [data-scrolling]),
|
|
1859
|
+
.lu-scroll-area:focus-within :where([data-scrollbar]) {
|
|
1860
|
+
opacity: 1;
|
|
1861
|
+
}
|
|
1862
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1863
|
+
.lu-scroll-area :where([data-scrollbar]) {
|
|
1864
|
+
transition: opacity 150ms ease-out;
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
/* The thumb: --lu-muted-foreground, 3:1 against the area, rounded. */
|
|
1868
|
+
.lu-scroll-area :where([data-thumb]) {
|
|
1869
|
+
position: relative;
|
|
1870
|
+
border-radius: 999px;
|
|
1871
|
+
background: var(--lu-muted-foreground);
|
|
1872
|
+
}
|
|
1873
|
+
/*
|
|
1874
|
+
* A 24px target for the pointer (WCAG 2.5.8, TASK-444 L7): the 6px thumb takes presses 16px
|
|
1875
|
+
* inward and over the scrollbar's padding, and 4px past its ends (its least length is 16px).
|
|
1876
|
+
*/
|
|
1877
|
+
.lu-scroll-area :where([data-thumb])::before {
|
|
1878
|
+
content: "";
|
|
1879
|
+
position: absolute;
|
|
1880
|
+
inset-block: -4px;
|
|
1881
|
+
inset-inline: -16px -2px;
|
|
1882
|
+
}
|
|
1883
|
+
.lu-scroll-area :where([data-orientation="horizontal"] > [data-thumb])::before {
|
|
1884
|
+
inset-block: -16px -2px;
|
|
1885
|
+
inset-inline: -4px;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
/* Menubar (TASK-379) ------------------------------------------------------------------------ */
|
|
1889
|
+
|
|
1890
|
+
.lu-menubar {
|
|
1891
|
+
display: inline-flex;
|
|
1892
|
+
gap: 0.125rem;
|
|
1893
|
+
padding: 0.25rem;
|
|
1894
|
+
border: 1px solid var(--lu-border);
|
|
1895
|
+
border-radius: var(--lu-radius);
|
|
1896
|
+
background: var(--lu-background);
|
|
1897
|
+
}
|
|
1898
|
+
.lu-menubar > lu-menu > [role="menuitem"] {
|
|
1899
|
+
min-block-size: 2rem;
|
|
1900
|
+
padding: 0.25rem 0.75rem;
|
|
1901
|
+
border: 0;
|
|
1902
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
1903
|
+
background: transparent;
|
|
1904
|
+
color: var(--lu-foreground);
|
|
1905
|
+
font: inherit;
|
|
1906
|
+
font-size: 0.875rem;
|
|
1907
|
+
font-weight: 500;
|
|
1908
|
+
text-align: start;
|
|
1909
|
+
cursor: pointer;
|
|
1910
|
+
}
|
|
1911
|
+
.lu-menubar > lu-menu > [role="menuitem"]:is(:hover, [aria-expanded="true"]) {
|
|
1912
|
+
background: var(--lu-accent);
|
|
1913
|
+
color: var(--lu-accent-foreground);
|
|
1914
|
+
}
|
|
1915
|
+
.lu-menubar > lu-menu > [role="menuitem"]:focus-visible {
|
|
1916
|
+
outline: 2px solid var(--lu-ring);
|
|
1917
|
+
outline-offset: -2px;
|
|
1918
|
+
}
|
|
1919
|
+
.lu-menubar > lu-menu > [role="menuitem"]:disabled {
|
|
1920
|
+
opacity: 0.5;
|
|
1921
|
+
cursor: not-allowed;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
/* Navigation Menu (TASK-380) ---------------------------------------------------------------- */
|
|
1925
|
+
|
|
1926
|
+
.lu-navigation-menu :where(ul) {
|
|
1927
|
+
margin: 0;
|
|
1928
|
+
padding: 0;
|
|
1929
|
+
list-style: none;
|
|
1930
|
+
}
|
|
1931
|
+
.lu-navigation-menu > ul {
|
|
1932
|
+
display: flex;
|
|
1933
|
+
flex-wrap: wrap;
|
|
1934
|
+
gap: 0.25rem;
|
|
1935
|
+
}
|
|
1936
|
+
.lu-navigation-menu[data-orientation="vertical"] > ul {
|
|
1937
|
+
flex-direction: column;
|
|
1938
|
+
align-items: start;
|
|
1939
|
+
}
|
|
1940
|
+
.lu-navigation-menu > ul > li {
|
|
1941
|
+
display: flex;
|
|
1942
|
+
}
|
|
1943
|
+
.lu-navigation-menu > ul > li > :is(button, a) {
|
|
1944
|
+
display: inline-flex;
|
|
1945
|
+
align-items: center;
|
|
1946
|
+
gap: 0.25rem;
|
|
1947
|
+
min-block-size: 2.25rem;
|
|
1948
|
+
padding: 0.375rem 0.75rem;
|
|
1949
|
+
border: 0;
|
|
1950
|
+
border-radius: calc(var(--lu-radius) - 2px);
|
|
1951
|
+
background: transparent;
|
|
1952
|
+
color: var(--lu-foreground);
|
|
1953
|
+
font: inherit;
|
|
1954
|
+
font-size: 0.875rem;
|
|
1955
|
+
font-weight: 500;
|
|
1956
|
+
text-decoration: none;
|
|
1957
|
+
cursor: pointer;
|
|
1958
|
+
}
|
|
1959
|
+
.lu-navigation-menu > ul > li > :is(button, a):is(:hover, [aria-expanded="true"]) {
|
|
1960
|
+
background: var(--lu-accent);
|
|
1961
|
+
color: var(--lu-accent-foreground);
|
|
1962
|
+
}
|
|
1963
|
+
/* The current page: underlined, a shape and not only a colour. */
|
|
1964
|
+
.lu-navigation-menu a[aria-current="page"] {
|
|
1965
|
+
text-decoration: underline 2px;
|
|
1966
|
+
text-underline-offset: 0.35em;
|
|
1967
|
+
}
|
|
1968
|
+
.lu-navigation-menu :is(button, a):focus-visible {
|
|
1969
|
+
outline: 2px solid var(--lu-ring);
|
|
1970
|
+
outline-offset: 2px;
|
|
1971
|
+
}
|
|
1972
|
+
.lu-navigation-menu button[aria-expanded="true"] > [aria-hidden="true"] {
|
|
1973
|
+
rotate: 180deg;
|
|
1974
|
+
}
|
|
1975
|
+
.lu-navigation-menu [popover] {
|
|
1976
|
+
--lu-side-offset: 4px;
|
|
1977
|
+
box-sizing: border-box;
|
|
1978
|
+
min-inline-size: 12rem;
|
|
1979
|
+
max-inline-size: min(28rem, 100vw - 1rem);
|
|
1980
|
+
padding: 0.375rem;
|
|
1981
|
+
border: 1px solid var(--lu-border);
|
|
1982
|
+
border-radius: var(--lu-radius);
|
|
1983
|
+
background: var(--lu-popover);
|
|
1984
|
+
color: var(--lu-popover-foreground);
|
|
1985
|
+
box-shadow:
|
|
1986
|
+
0 10px 15px -3px rgb(0 0 0 / 0.1),
|
|
1987
|
+
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1988
|
+
}
|
|
1989
|
+
.lu-navigation-menu [popover] a {
|
|
1990
|
+
display: block;
|
|
1991
|
+
padding: 0.5rem 0.75rem;
|
|
1992
|
+
border-radius: calc(var(--lu-radius) - 4px);
|
|
1993
|
+
color: inherit;
|
|
1994
|
+
font-size: 0.875rem;
|
|
1995
|
+
text-decoration: none;
|
|
1996
|
+
}
|
|
1997
|
+
.lu-navigation-menu [popover] a:is(:hover, :focus-visible) {
|
|
1998
|
+
background: var(--lu-accent);
|
|
1999
|
+
color: var(--lu-accent-foreground);
|
|
2000
|
+
}
|
|
2001
|
+
/* Fade in and out, sliding in from where the previous content was; `overlay` keeps a content in
|
|
2002
|
+
the top layer while it fades out, in Chromium only. */
|
|
2003
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2004
|
+
.lu-navigation-menu button > [aria-hidden="true"] {
|
|
2005
|
+
transition: rotate 150ms ease;
|
|
2006
|
+
}
|
|
2007
|
+
.lu-navigation-menu [popover] {
|
|
2008
|
+
transition:
|
|
2009
|
+
opacity 150ms ease,
|
|
2010
|
+
translate 150ms ease,
|
|
2011
|
+
overlay 150ms allow-discrete,
|
|
2012
|
+
display 150ms allow-discrete;
|
|
2013
|
+
}
|
|
2014
|
+
.lu-navigation-menu [popover]:not(:popover-open) {
|
|
2015
|
+
opacity: 0;
|
|
2016
|
+
}
|
|
2017
|
+
@starting-style {
|
|
2018
|
+
.lu-navigation-menu [popover]:popover-open {
|
|
2019
|
+
opacity: 0;
|
|
2020
|
+
translate: 0 -4px;
|
|
2021
|
+
}
|
|
2022
|
+
.lu-navigation-menu [popover][data-activation-direction="right"]:popover-open {
|
|
2023
|
+
translate: 1rem 0;
|
|
2024
|
+
}
|
|
2025
|
+
.lu-navigation-menu [popover][data-activation-direction="left"]:popover-open {
|
|
2026
|
+
translate: -1rem 0;
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
/* Forced colours (TASK-441 M38) ------------------------------------------------------------- */
|
|
2032
|
+
|
|
2033
|
+
/*
|
|
2034
|
+
* A forced palette drops shadows and gradients and paints author backgrounds as Canvas, so the
|
|
2035
|
+
* state indicators drawn with them vanish; system colours, which it keeps, draw them again. A
|
|
2036
|
+
* transparent border shows there: a border that must stay hidden is Canvas.
|
|
2037
|
+
*/
|
|
2038
|
+
@media (forced-colors: active) {
|
|
2039
|
+
.lu-switch::before {
|
|
2040
|
+
background: ButtonText;
|
|
2041
|
+
}
|
|
2042
|
+
.lu-switch:checked {
|
|
2043
|
+
border-color: Highlight;
|
|
2044
|
+
background: Highlight;
|
|
2045
|
+
}
|
|
2046
|
+
.lu-switch:checked::before {
|
|
2047
|
+
background: HighlightText;
|
|
2048
|
+
}
|
|
2049
|
+
.lu-toggle[aria-pressed="true"] {
|
|
2050
|
+
border-color: Highlight;
|
|
2051
|
+
background: Highlight;
|
|
2052
|
+
color: HighlightText;
|
|
2053
|
+
}
|
|
2054
|
+
/* The ring is outside, on Canvas: Firefox would draw it in the text colour, HighlightText, which
|
|
2055
|
+
no contrast theme pairs with Canvas (TASK-462). */
|
|
2056
|
+
.lu-toggle[aria-pressed="true"]:focus-visible {
|
|
2057
|
+
outline-color: CanvasText;
|
|
2058
|
+
}
|
|
2059
|
+
.lu-tabs [role="tab"] {
|
|
2060
|
+
border-block-end: 2px solid Canvas;
|
|
2061
|
+
}
|
|
2062
|
+
.lu-tabs [aria-orientation="vertical"] [role="tab"] {
|
|
2063
|
+
border-block-end: 0;
|
|
2064
|
+
border-inline-end-color: Canvas;
|
|
2065
|
+
}
|
|
2066
|
+
.lu-tabs [role="tab"][aria-selected="true"] {
|
|
2067
|
+
border-block-end-color: Highlight;
|
|
2068
|
+
}
|
|
2069
|
+
.lu-tabs [aria-orientation="vertical"] [role="tab"][aria-selected="true"] {
|
|
2070
|
+
border-inline-end-color: Highlight;
|
|
2071
|
+
}
|
|
2072
|
+
.lu-tabs [data-indicator] {
|
|
2073
|
+
border-color: Highlight;
|
|
2074
|
+
}
|
|
2075
|
+
.lu-tabs:defined [role="tablist"]:has(> [data-indicator]) [role="tab"][aria-selected="true"] {
|
|
2076
|
+
border-color: Canvas;
|
|
2077
|
+
}
|
|
2078
|
+
.lu-progress > progress::-webkit-progress-value,
|
|
2079
|
+
.lu-meter > meter::-webkit-meter-optimum-value,
|
|
2080
|
+
.lu-meter > meter::-webkit-meter-suboptimum-value,
|
|
2081
|
+
.lu-meter > meter::-webkit-meter-even-less-good-value {
|
|
2082
|
+
background: Highlight;
|
|
2083
|
+
}
|
|
2084
|
+
.lu-progress > progress::-moz-progress-bar,
|
|
2085
|
+
.lu-meter > meter::-moz-meter-bar {
|
|
2086
|
+
background: Highlight;
|
|
2087
|
+
}
|
|
2088
|
+
/* The sliding segment is a gradient: kept, in system colours. */
|
|
2089
|
+
.lu-progress > progress:indeterminate {
|
|
2090
|
+
forced-color-adjust: none;
|
|
2091
|
+
border-color: CanvasText;
|
|
2092
|
+
background-color: Canvas;
|
|
2093
|
+
background-image: linear-gradient(
|
|
2094
|
+
to right,
|
|
2095
|
+
transparent 0 35%,
|
|
2096
|
+
Highlight 35% 65%,
|
|
2097
|
+
transparent 65%
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
.lu-slider > div > div > :where(div) {
|
|
2101
|
+
background: Highlight;
|
|
2102
|
+
}
|
|
2103
|
+
.lu-scroll-area :where([data-thumb]) {
|
|
2104
|
+
background: CanvasText;
|
|
2105
|
+
}
|
|
2106
|
+
.lu-menu :where([role^="menuitem"][data-highlighted], [aria-expanded="true"]) {
|
|
2107
|
+
background: Highlight;
|
|
2108
|
+
color: HighlightText;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|