@threadlabs/looma 0.17.4 → 0.18.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/components/ui-avatar/ui-avatar.html +8 -4
- package/components/ui-badge/ui-badge.html +28 -34
- package/components/ui-button/ui-button.html +1 -1
- package/components/ui-combobox/ui-combobox.html +4 -48
- package/components/ui-icon-button/ui-icon-button.html +10 -0
- package/components/ui-input/ui-input.html +1 -1
- package/components/ui-input-group/ui-input-group.html +1 -1
- package/components/ui-listbox/ui-listbox.html +88 -12
- package/components/ui-listbox/ui-listbox.js +162 -18
- package/components/ui-menu/ui-menu.js +14 -2
- package/components/ui-menu-item/ui-menu-item.html +3 -0
- package/components/ui-popover/ui-popover.js +13 -2
- package/components/ui-select/ui-select.html +1 -1
- package/components/ui-spinner/ui-spinner.html +47 -14
- package/components/ui-textarea/ui-textarea.html +1 -1
- package/dist/index.js +1 -1
- package/editor/chunks/extensions.js +5 -0
- package/package.json +1 -1
- package/styles/ui-avatar.css +6 -2
- package/styles/ui-badge.css +30 -40
- package/styles/ui-button.css +1 -1
- package/styles/ui-combobox.css +0 -52
- package/styles/ui-icon-button.css +10 -0
- package/styles/ui-input-group.css +1 -1
- package/styles/ui-input.css +1 -1
- package/styles/ui-listbox.css +33 -8
- package/styles/ui-menu-item.css +3 -0
- package/styles/ui-select.css +1 -1
- package/styles/ui-spinner.css +40 -15
- package/styles/ui-textarea.css +1 -1
- package/tokens.css +67 -2
- package/vanilla/UiCombobox.js +9 -1
- package/vanilla/UiListbox.d.ts +3 -1
- package/vanilla/UiListbox.js +65 -18
- package/vanilla/UiSpinner.js +19 -1
- package/vue/UiAvatar.vue +11 -2
- package/vue/UiBadge.vue +30 -36
- package/vue/UiButton.vue +1 -1
- package/vue/UiCombobox.vue +4 -49
- package/vue/UiIconButton.vue +13 -0
- package/vue/UiInput.vue +1 -1
- package/vue/UiInputGroup.vue +1 -1
- package/vue/UiListbox.d.ts +18 -5
- package/vue/UiListbox.vue +142 -25
- package/vue/UiMenuItem.vue +3 -0
- package/vue/UiSelect.vue +1 -1
- package/vue/UiSpinner.vue +47 -14
- package/vue/UiTextarea.vue +1 -1
- package/vue/chunks/UiAvatar.js +2 -1
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiButton.js +1 -1
- package/vue/chunks/UiCombobox.js +11 -2
- package/vue/chunks/UiIconButton.js +1 -1
- package/vue/chunks/UiInput.js +1 -1
- package/vue/chunks/UiInputGroup.js +1 -1
- package/vue/chunks/UiListbox.js +134 -20
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiSelect.js +1 -1
- package/vue/chunks/UiSpinner.js +29 -3
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/components.css +354 -342
|
@@ -8638,6 +8638,11 @@ function parseHtmlSlice(schema, value) {
|
|
|
8638
8638
|
if (/\s$/.test(child.textContent) || /^\s/.test(next.textContent)) continue;
|
|
8639
8639
|
wrapper.insertBefore(parsed.createTextNode(" "), next);
|
|
8640
8640
|
}
|
|
8641
|
+
for (const pre of parsed.body.querySelectorAll("pre")) {
|
|
8642
|
+
let last = pre;
|
|
8643
|
+
while (last.lastChild) last = last.lastChild;
|
|
8644
|
+
if (last.nodeType === Node.TEXT_NODE) last.textContent = last.textContent?.replace(/\r?\n$/, "") ?? "";
|
|
8645
|
+
}
|
|
8641
8646
|
const container = document.createElement("div");
|
|
8642
8647
|
container.append(purify.sanitize(parsed.body.innerHTML, {
|
|
8643
8648
|
USE_PROFILES: { html: true },
|
package/package.json
CHANGED
package/styles/ui-avatar.css
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
inline-size: 2.5rem;
|
|
31
31
|
block-size: 2.5rem;
|
|
32
32
|
border-radius: var(--ui-avatar-radius, var(--ui-radius-round));
|
|
33
|
-
border: 1px solid var(--ui-avatar-border, var(--ui-
|
|
33
|
+
border: 1px solid var(--ui-avatar-border, color-mix(in srgb, var(--ui-accent-solid) 35%, var(--ui-surface-default)));
|
|
34
34
|
background: var(--ui-avatar-surface, var(--ui-accent-soft));
|
|
35
35
|
color: var(--ui-avatar-text, var(--ui-accent-subtle-text, var(--ui-accent-solid)));
|
|
36
36
|
font: inherit;
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
font-size: var(--ui-font-size-xs);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
:scope[data-ui-avatar-state~="hasImage"] {
|
|
50
|
+
border-color: var(--ui-avatar-border, var(--ui-border-strong));
|
|
51
|
+
}
|
|
52
|
+
|
|
49
53
|
:scope[data-ui-avatar-state~="shape=square"] {
|
|
50
54
|
border-radius: var(--ui-avatar-radius, var(--ui-radius-md));
|
|
51
55
|
}
|
|
@@ -53,7 +57,7 @@
|
|
|
53
57
|
/* An outline, not a dot: the avatar clips its content to the circle, and an outline is drawn
|
|
54
58
|
outside the box, so the ring survives the clip and the overlap in an Avatar Group. */
|
|
55
59
|
:scope[data-ui-avatar-state~="active"] {
|
|
56
|
-
outline:
|
|
60
|
+
outline: 1px solid var(--ui-avatar-active-ring, var(--ui-accent-solid));
|
|
57
61
|
outline-offset: 1px;
|
|
58
62
|
}
|
|
59
63
|
|
package/styles/ui-badge.css
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
/* This component's hooks style the element they are set on, and never a nested one. */
|
|
48
48
|
|
|
49
49
|
:scope {
|
|
50
|
-
--_badge-surface: var(--ui-surface-subtle);
|
|
50
|
+
--_badge-surface: color-mix(in srgb, var(--ui-surface-subtle) 80%, var(--ui-surface-default));
|
|
51
51
|
--_badge-text: var(--ui-text-secondary);
|
|
52
52
|
/* Sit between the soft fill and its stronger theme ink. */
|
|
53
53
|
--_badge-border: color-mix(in srgb, var(--_badge-surface) 75%, var(--_badge-text) 25%);
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
surface, text, and border hooks. Each value is invalid, so the tone shows, while it is unset. The
|
|
56
56
|
mixes keep 4.5:1 text contrast for any colour, in a light theme or a dark one. */
|
|
57
57
|
--_ui-badge-color: var(--ui-badge-color);
|
|
58
|
-
--_badge-color-wash: color-mix(in oklab, var(--_ui-badge-color)
|
|
58
|
+
--_badge-color-wash: color-mix(in oklab, var(--_ui-badge-color) 13%, var(--ui-surface-default));
|
|
59
59
|
--_badge-color-ink: color-mix(in oklab, var(--_ui-badge-color) 35%, var(--ui-text-primary));
|
|
60
60
|
--_badge-color-surface: var(--_badge-color-wash);
|
|
61
61
|
--_badge-color-border: color-mix(in srgb, var(--_badge-color-wash) 75%, var(--_badge-color-ink) 25%);
|
|
@@ -123,32 +123,32 @@
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
:scope[data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=accent"] {
|
|
126
|
-
--_badge-surface: color-mix(in srgb, var(--ui-accent-solid)
|
|
127
|
-
--_badge-border: color-mix(in srgb, var(--ui-accent-solid)
|
|
126
|
+
--_badge-surface: color-mix(in srgb, var(--ui-accent-solid) 19%, var(--ui-surface-default));
|
|
127
|
+
--_badge-border: color-mix(in srgb, var(--ui-accent-solid) 25%, var(--ui-surface-default));
|
|
128
128
|
--_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
:scope[data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=danger"] {
|
|
132
|
-
--_badge-surface: color-mix(in srgb, var(--ui-danger-solid)
|
|
133
|
-
--_badge-border: color-mix(in srgb, var(--ui-danger-solid)
|
|
132
|
+
--_badge-surface: color-mix(in srgb, var(--ui-danger-solid) 19%, var(--ui-surface-default));
|
|
133
|
+
--_badge-border: color-mix(in srgb, var(--ui-danger-solid) 25%, var(--ui-surface-default));
|
|
134
134
|
--_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
:scope[data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=success"] {
|
|
138
|
-
--_badge-surface: color-mix(in srgb, var(--ui-success-solid)
|
|
139
|
-
--_badge-border: color-mix(in srgb, var(--ui-success-solid)
|
|
138
|
+
--_badge-surface: color-mix(in srgb, var(--ui-success-solid) 19%, var(--ui-surface-default));
|
|
139
|
+
--_badge-border: color-mix(in srgb, var(--ui-success-solid) 25%, var(--ui-surface-default));
|
|
140
140
|
--_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
:scope[data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=warning"] {
|
|
144
|
-
--_badge-surface: color-mix(in srgb, var(--ui-warning-solid)
|
|
145
|
-
--_badge-border: color-mix(in srgb, var(--ui-warning-solid)
|
|
144
|
+
--_badge-surface: color-mix(in srgb, var(--ui-warning-solid) 19%, var(--ui-surface-default));
|
|
145
|
+
--_badge-border: color-mix(in srgb, var(--ui-warning-solid) 25%, var(--ui-surface-default));
|
|
146
146
|
--_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
:scope[data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=info"] {
|
|
150
|
-
--_badge-surface: color-mix(in srgb, var(--ui-info-solid)
|
|
151
|
-
--_badge-border: color-mix(in srgb, var(--ui-info-solid)
|
|
150
|
+
--_badge-surface: color-mix(in srgb, var(--ui-info-solid) 19%, var(--ui-surface-default));
|
|
151
|
+
--_badge-border: color-mix(in srgb, var(--ui-info-solid) 25%, var(--ui-surface-default));
|
|
152
152
|
--_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -194,54 +194,48 @@
|
|
|
194
194
|
--_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
/*
|
|
198
|
-
|
|
199
|
-
label never runs into it. */
|
|
197
|
+
/* The clipped point needs an inset surface over an outer border-colour shape: a native border
|
|
198
|
+
has no diagonal edge to follow. Keep this edge for every tag variant. */
|
|
200
199
|
:scope[data-ui-badge-state~="shape=tag"] {
|
|
201
200
|
--_badge-point: var(--ui-badge-point, var(--ui-space-2));
|
|
202
201
|
|
|
202
|
+
position: relative;
|
|
203
|
+
isolation: isolate;
|
|
203
204
|
border-color: transparent;
|
|
204
205
|
border-radius: 0;
|
|
206
|
+
background: var(--ui-badge-border, var(--_badge-color-border, var(--_badge-border)));
|
|
205
207
|
padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
206
208
|
clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);
|
|
207
209
|
}
|
|
208
210
|
|
|
209
|
-
:scope[data-ui-badge-state~="shape=tag"]
|
|
210
|
-
padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));
|
|
211
|
-
padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
212
|
-
clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* The tag clips its point, including the native border. Draw the outer shape in the border
|
|
216
|
-
colour and an inset inner shape in the surface colour to keep a visible diagonal edge. */
|
|
217
|
-
:scope[data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"] {
|
|
218
|
-
position: relative;
|
|
219
|
-
isolation: isolate;
|
|
220
|
-
background: var(--ui-badge-border, var(--_badge-color-border, var(--_badge-border)));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
:scope[data-ui-badge-state~="variant=outline"][data-ui-badge-state~="shape=tag"]::before {
|
|
211
|
+
:scope[data-ui-badge-state~="shape=tag"]::before {
|
|
224
212
|
content: "";
|
|
225
213
|
position: absolute;
|
|
226
|
-
inset:
|
|
214
|
+
inset: 0;
|
|
227
215
|
z-index: -1;
|
|
228
216
|
background: var(--_badge-outline-surface);
|
|
229
217
|
clip-path: polygon(0 0, calc(100% - var(--_badge-point)) 0, 100% 50%, calc(100% - var(--_badge-point)) 100%, 0 100%);
|
|
230
218
|
pointer-events: none;
|
|
231
219
|
}
|
|
232
220
|
|
|
233
|
-
:scope[data-ui-badge-state~="
|
|
221
|
+
:scope[data-ui-badge-state~="shape=tag"]:dir(rtl) {
|
|
222
|
+
padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));
|
|
223
|
+
padding-inline-start: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
|
|
224
|
+
clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
:scope[data-ui-badge-state~="shape=tag"]:dir(rtl)::before {
|
|
234
228
|
clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
|
|
235
229
|
}
|
|
236
230
|
|
|
237
231
|
@media (forced-colors: active) {
|
|
238
|
-
:scope[data-ui-badge-state~="
|
|
232
|
+
:scope[data-ui-badge-state~="shape=tag"] {
|
|
239
233
|
forced-color-adjust: none;
|
|
240
234
|
background: CanvasText;
|
|
241
235
|
color: CanvasText;
|
|
242
236
|
}
|
|
243
237
|
|
|
244
|
-
:scope[data-ui-badge-state~="
|
|
238
|
+
:scope[data-ui-badge-state~="shape=tag"]::before {
|
|
245
239
|
background: Canvas;
|
|
246
240
|
}
|
|
247
241
|
}
|
|
@@ -263,12 +257,8 @@
|
|
|
263
257
|
/* A solid colour fills with the ink. Its text is the page surface, mixed at 0% only so that it too is
|
|
264
258
|
invalid while the hook is unset. */
|
|
265
259
|
|
|
266
|
-
/*
|
|
267
|
-
|
|
268
|
-
label never runs into it. */
|
|
269
|
-
|
|
270
|
-
/* The tag clips its point, including the native border. Draw the outer shape in the border
|
|
271
|
-
colour and an inset inner shape in the surface colour to keep a visible diagonal edge. */
|
|
260
|
+
/* The clipped point needs an inset surface over an outer border-colour shape: a native border
|
|
261
|
+
has no diagonal edge to follow. Keep this edge for every tag variant. */
|
|
272
262
|
|
|
273
263
|
@media (forced-colors: active) {
|
|
274
264
|
}
|
package/styles/ui-button.css
CHANGED
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
border-color: transparent;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
:scope[data-ui-button-state~="variant=ghost"]:active:not(:disabled, [aria-disabled="true"]) {
|
|
253
|
+
:scope[data-ui-button-state~="variant=ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]) {
|
|
254
254
|
background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
|
|
255
255
|
border-color: transparent;
|
|
256
256
|
box-shadow: var(--ui-pressed);
|
package/styles/ui-combobox.css
CHANGED
|
@@ -254,21 +254,6 @@
|
|
|
254
254
|
[hidden] {
|
|
255
255
|
display: none;
|
|
256
256
|
}
|
|
257
|
-
.option {
|
|
258
|
-
padding: var(--ui-space-2) var(--ui-space-3);
|
|
259
|
-
border-radius: var(--ui-radius-sm);
|
|
260
|
-
cursor: pointer;
|
|
261
|
-
overflow-wrap: anywhere;
|
|
262
|
-
}
|
|
263
|
-
.option:hover, .option.active {
|
|
264
|
-
background: var(--ui-surface-muted);
|
|
265
|
-
outline: 1px solid var(--ui-focus-ring);
|
|
266
|
-
outline-offset: -1px;
|
|
267
|
-
}
|
|
268
|
-
.option[aria-disabled="true"] {
|
|
269
|
-
color: var(--ui-disabled-text);
|
|
270
|
-
cursor: not-allowed;
|
|
271
|
-
}
|
|
272
257
|
.option[aria-disabled="true"] .primary,
|
|
273
258
|
.option[aria-disabled="true"] .secondary {
|
|
274
259
|
color: var(--ui-disabled-text);
|
|
@@ -336,39 +321,6 @@
|
|
|
336
321
|
}
|
|
337
322
|
}
|
|
338
323
|
|
|
339
|
-
/* Multiple mode: every option carries a checkbox, so a list that takes several answers says so
|
|
340
|
-
before anything is picked. aria-selected is the state; this draws it.
|
|
341
|
-
Longhands, not shorthands: lowering drops a shorthand that omits a component. */
|
|
342
|
-
:scope[data-ui-combobox-state~="multiple"] .option {
|
|
343
|
-
display: flex;
|
|
344
|
-
gap: var(--ui-space-2);
|
|
345
|
-
align-items: center;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
:scope[data-ui-combobox-state~="multiple"] .option::before {
|
|
349
|
-
content: "";
|
|
350
|
-
flex: none;
|
|
351
|
-
inline-size: 1.125rem;
|
|
352
|
-
block-size: 1.125rem;
|
|
353
|
-
border-style: solid;
|
|
354
|
-
border-width: 1px;
|
|
355
|
-
border-color: var(--ui-control-border-hover, var(--ui-border-strong));
|
|
356
|
-
border-radius: var(--ui-radius-sm);
|
|
357
|
-
background-color: var(--ui-control-surface, var(--ui-surface-default));
|
|
358
|
-
background-repeat: no-repeat;
|
|
359
|
-
background-position: center;
|
|
360
|
-
background-size: 0.7rem;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
:scope[data-ui-combobox-state~="multiple"] .option[aria-selected="true"]::before {
|
|
364
|
-
border-color: var(--ui-accent-solid);
|
|
365
|
-
background-color: var(--ui-accent-solid);
|
|
366
|
-
background-image: var(
|
|
367
|
-
--_ui-combobox-option-check,
|
|
368
|
-
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E")
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
324
|
/* Multiple mode keeps one control height. Chips and the input scroll within the entry,
|
|
373
325
|
while the clear and disclosure controls remain fixed at the end of the field. */
|
|
374
326
|
:scope[data-ui-combobox-state~="multiple"] .field {
|
|
@@ -448,10 +400,6 @@
|
|
|
448
400
|
@media (forced-colors: active) {
|
|
449
401
|
}
|
|
450
402
|
|
|
451
|
-
/* Multiple mode: every option carries a checkbox, so a list that takes several answers says so
|
|
452
|
-
before anything is picked. aria-selected is the state; this draws it.
|
|
453
|
-
Longhands, not shorthands: lowering drops a shorthand that omits a component. */
|
|
454
|
-
|
|
455
403
|
/* Multiple mode keeps one control height. Chips and the input scroll within the entry,
|
|
456
404
|
while the clear and disclosure controls remain fixed at the end of the field. */
|
|
457
405
|
/* Size variants keep their control height as selections are added. */
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
syntax: "*";
|
|
4
4
|
inherits: false;
|
|
5
5
|
}
|
|
6
|
+
@property --ui-icon-button-active-surface {
|
|
7
|
+
syntax: "*";
|
|
8
|
+
inherits: false;
|
|
9
|
+
}
|
|
6
10
|
@property --ui-icon-button-border {
|
|
7
11
|
syntax: "*";
|
|
8
12
|
inherits: false;
|
|
@@ -247,6 +251,12 @@
|
|
|
247
251
|
background-color: var(--ui-icon-button-solid-hover-surface, var(--ui-accent-hover));
|
|
248
252
|
}
|
|
249
253
|
|
|
254
|
+
:scope[data-ui-icon-button-state~="variant=ghost"][aria-expanded="true"]:enabled:not([aria-disabled="true"]) {
|
|
255
|
+
background-color: var(--ui-icon-button-active-surface, color-mix(in srgb, currentColor 16%, transparent));
|
|
256
|
+
color: var(--ui-icon-button-hover-text, var(--ui-text-primary));
|
|
257
|
+
box-shadow: var(--ui-pressed);
|
|
258
|
+
}
|
|
259
|
+
|
|
250
260
|
:scope:active:enabled:not([aria-disabled="true"]) {
|
|
251
261
|
transform: scale(var(--ui-icon-button-active-scale, 0.96));
|
|
252
262
|
}
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
:scope:hover:not(:has(input:focus, input:disabled)) {
|
|
71
|
+
:scope:hover:not(:has(input:focus, input:disabled, input:read-only, [aria-invalid="true"], :is(:user-invalid, [data-user-invalid]))) {
|
|
72
72
|
border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
|
|
73
73
|
}
|
|
74
74
|
|
package/styles/ui-input.css
CHANGED
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
opacity: 1;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
:scope:hover:not(:focus):not(:disabled) {
|
|
114
|
+
:scope:hover:not(:focus):not(:disabled):not(:read-only):not([aria-invalid="true"]):not(:is(:user-invalid, [data-user-invalid])) {
|
|
115
115
|
border-color: var(--ui-input-border-hover, var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary))));
|
|
116
116
|
}
|
|
117
117
|
|
package/styles/ui-listbox.css
CHANGED
|
@@ -21,29 +21,55 @@
|
|
|
21
21
|
}
|
|
22
22
|
@scope ([data-component~="ui-listbox"]) to ([data-component], [data-slotted]) {
|
|
23
23
|
:scope {
|
|
24
|
+
position: relative;
|
|
24
25
|
box-sizing: border-box;
|
|
25
26
|
display: block;
|
|
26
27
|
inline-size: 100%;
|
|
27
28
|
min-inline-size: 0;
|
|
28
|
-
min-block-size: var(--ui-control-min-block-size);
|
|
29
29
|
margin: 0;
|
|
30
30
|
padding: var(--ui-space-1);
|
|
31
31
|
border: 1px solid var(--ui-listbox-border, var(--ui-control-border));
|
|
32
32
|
border-radius: var(--ui-listbox-radius, var(--ui-field-radius, var(--ui-radius-md)));
|
|
33
33
|
background: var(--ui-listbox-surface, var(--ui-control-surface));
|
|
34
34
|
color: var(--ui-text-primary);
|
|
35
|
-
color-scheme: light dark;
|
|
36
35
|
font: inherit;
|
|
37
36
|
line-height: var(--ui-line-height-md);
|
|
38
37
|
box-shadow: var(--ui-control-inset);
|
|
38
|
+
outline: none;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
.choices {
|
|
42
|
+
max-block-size: calc(max(2, var(--_rows, 5)) * var(--ui-control-size-md));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:scope:not([data-enhanced]) {
|
|
46
|
+
padding: 0;
|
|
47
|
+
border: 0;
|
|
48
|
+
background: transparent;
|
|
49
|
+
box-shadow: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:scope:not([data-enhanced]) .choices,
|
|
53
|
+
:scope[data-enhanced] .fallback {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.fallback {
|
|
58
|
+
box-sizing: border-box;
|
|
59
|
+
inline-size: 100%;
|
|
44
60
|
font: inherit;
|
|
45
61
|
}
|
|
46
62
|
|
|
63
|
+
.validity {
|
|
64
|
+
position: absolute;
|
|
65
|
+
inline-size: 1px;
|
|
66
|
+
block-size: 1px;
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
clip-path: inset(50%);
|
|
69
|
+
opacity: 0;
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
47
73
|
:scope:focus-visible {
|
|
48
74
|
border-color: var(--ui-control-focus);
|
|
49
75
|
outline: 2px solid var(--ui-focus-ring);
|
|
@@ -51,12 +77,11 @@
|
|
|
51
77
|
box-shadow: var(--ui-listbox-focus-shadow, var(--ui-focus-halo));
|
|
52
78
|
}
|
|
53
79
|
|
|
54
|
-
:scope[aria-invalid="true"]
|
|
55
|
-
:scope:is(:user-invalid, [data-user-invalid]) {
|
|
80
|
+
:scope[aria-invalid="true"] {
|
|
56
81
|
border-color: var(--ui-listbox-invalid-border, var(--ui-field-danger, var(--ui-danger)));
|
|
57
82
|
}
|
|
58
83
|
|
|
59
|
-
:scope
|
|
84
|
+
:scope[aria-disabled="true"] {
|
|
60
85
|
background: var(--ui-control-surface-disabled);
|
|
61
86
|
color: var(--ui-disabled-text);
|
|
62
87
|
box-shadow: none;
|
package/styles/ui-menu-item.css
CHANGED
package/styles/ui-select.css
CHANGED
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
background-size: 1.125rem 1.125rem;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
:scope:hover:not(:focus):not(:disabled) {
|
|
81
|
+
:scope:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(:is(:user-invalid, [data-user-invalid])) {
|
|
82
82
|
border-color: var(--ui-select-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary)));
|
|
83
83
|
}
|
|
84
84
|
|
package/styles/ui-spinner.css
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
/* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
|
|
2
|
-
@keyframes ui-spinner-
|
|
2
|
+
@keyframes ui-spinner-rotate {
|
|
3
|
+
100% {
|
|
4
|
+
transform: rotate(1turn);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
@keyframes ui-spinner-dash {
|
|
3
8
|
0% {
|
|
4
|
-
|
|
9
|
+
stroke-dasharray: 1, 150;
|
|
10
|
+
stroke-dashoffset: 0;
|
|
5
11
|
}
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
50% {
|
|
13
|
+
stroke-dasharray: 90, 150;
|
|
14
|
+
stroke-dashoffset: -35;
|
|
8
15
|
}
|
|
9
16
|
100% {
|
|
10
|
-
|
|
17
|
+
stroke-dasharray: 90, 150;
|
|
18
|
+
stroke-dashoffset: -124;
|
|
11
19
|
}
|
|
12
20
|
}
|
|
13
21
|
@scope ([data-component~="ui-spinner"]) to ([data-component], [data-slotted]) {
|
|
14
|
-
/*
|
|
15
|
-
and the label (or the text beside it) still says what is happening. */
|
|
22
|
+
/* A rounded SVG arc grows and recedes over a quiet full-circle track. */
|
|
16
23
|
:scope {
|
|
17
24
|
display: inline-flex;
|
|
18
25
|
flex: none;
|
|
@@ -21,22 +28,41 @@
|
|
|
21
28
|
box-sizing: border-box;
|
|
22
29
|
inline-size: 1em;
|
|
23
30
|
block-size: 1em;
|
|
24
|
-
border: 2px solid transparent;
|
|
25
|
-
border-block-start-color: currentColor;
|
|
26
|
-
border-inline-end-color: color-mix(in srgb, currentColor 52%, transparent);
|
|
27
|
-
border-radius: 50%;
|
|
28
31
|
color: currentColor;
|
|
29
32
|
font-size: var(--ui-font-size-lg);
|
|
30
33
|
line-height: 1;
|
|
31
|
-
animation: ui-spinner-chase 1s linear infinite;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
:scope[data-ui-spinner-state~="size=sm"] {
|
|
35
37
|
font-size: var(--ui-font-size-md);
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
svg {
|
|
41
|
+
display: block;
|
|
42
|
+
inline-size: 100%;
|
|
43
|
+
block-size: 100%;
|
|
44
|
+
animation: ui-spinner-rotate 2s linear infinite;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
circle {
|
|
48
|
+
stroke-width: 3;
|
|
49
|
+
stroke-linecap: round;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.track {
|
|
53
|
+
stroke: color-mix(in srgb, currentColor 16%, transparent);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.arc {
|
|
57
|
+
stroke: currentColor;
|
|
58
|
+
stroke-dasharray: 90, 150;
|
|
59
|
+
stroke-dashoffset: 0;
|
|
60
|
+
animation: ui-spinner-dash 1.5s ease-in-out infinite;
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
@media (prefers-reduced-motion: reduce) {
|
|
39
|
-
|
|
64
|
+
svg,
|
|
65
|
+
.arc {
|
|
40
66
|
animation: none;
|
|
41
67
|
}
|
|
42
68
|
}
|
|
@@ -47,8 +73,7 @@
|
|
|
47
73
|
}
|
|
48
74
|
}
|
|
49
75
|
@scope ([data-component~="ui-spinner"]) to ([data-component]) {
|
|
50
|
-
/*
|
|
51
|
-
and the label (or the text beside it) still says what is happening. */
|
|
76
|
+
/* A rounded SVG arc grows and recedes over a quiet full-circle track. */
|
|
52
77
|
|
|
53
78
|
@media (prefers-reduced-motion: reduce) {
|
|
54
79
|
}
|
package/styles/ui-textarea.css
CHANGED
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
opacity: 1;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
:scope:hover:not(:focus):not(:disabled) {
|
|
60
|
+
:scope:hover:not(:focus):not(:disabled):not(:read-only):not([aria-invalid="true"]):not(:is(:user-invalid, [data-user-invalid])) {
|
|
61
61
|
border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
|
|
62
62
|
}
|
|
63
63
|
|
package/tokens.css
CHANGED
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
/* Lines divide content; stronger edges enclose surfaces; control edges identify inputs. */
|
|
135
135
|
--ui-border-divider: color-mix(in oklab, var(--ui-border) 50%, var(--ui-border-strong));
|
|
136
136
|
--ui-border-strong: color-mix(in oklab, var(--ui-text) 25%, var(--ui-surface));
|
|
137
|
-
--ui-control-border: color-mix(in oklab, var(--ui-text)
|
|
137
|
+
--ui-control-border: color-mix(in oklab, var(--ui-text) 43%, var(--ui-surface));
|
|
138
138
|
|
|
139
139
|
/* States: toward the ink for pressure, toward the page for a tint. In a dark theme the ink is
|
|
140
140
|
light, so the same mixes brighten instead of darkening, without a second set of values. */
|
|
@@ -205,7 +205,7 @@
|
|
|
205
205
|
--ui-action-secondary-text: var(--ui-text);
|
|
206
206
|
--ui-control-surface: var(--ui-surface);
|
|
207
207
|
--ui-control-surface-disabled: var(--ui-surface-muted);
|
|
208
|
-
--ui-control-border-hover: var(--ui-
|
|
208
|
+
--ui-control-border-hover: color-mix(in oklab, var(--ui-text) 50%, var(--ui-surface));
|
|
209
209
|
--ui-control-placeholder: var(--ui-text-secondary);
|
|
210
210
|
--ui-control-focus: var(--ui-focus-ring);
|
|
211
211
|
/* Derived from the ring, not a near-white tint, so the halo shows on any surface. */
|
|
@@ -287,3 +287,68 @@
|
|
|
287
287
|
outline: none;
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
|
+
|
|
291
|
+
/* Combobox suggestions and visible Listbox choices share the same row and checkmark. */
|
|
292
|
+
@layer components {
|
|
293
|
+
[data-ui-choice-option] {
|
|
294
|
+
padding: var(--ui-space-2) var(--ui-space-3);
|
|
295
|
+
border-radius: var(--ui-radius-sm);
|
|
296
|
+
cursor: pointer;
|
|
297
|
+
overflow-wrap: anywhere;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
[data-ui-choice-option]:is(:hover, .active) {
|
|
301
|
+
background: var(--ui-surface-muted);
|
|
302
|
+
outline: 1px solid var(--ui-focus-ring);
|
|
303
|
+
outline-offset: -1px;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
[data-ui-choice-option][aria-disabled="true"],
|
|
307
|
+
[data-ui-choice-option][aria-disabled="true"]:hover {
|
|
308
|
+
color: var(--ui-disabled-text);
|
|
309
|
+
background: transparent;
|
|
310
|
+
outline: none;
|
|
311
|
+
cursor: not-allowed;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
[data-ui-choice-option]:not([data-multiple])[aria-selected="true"] {
|
|
315
|
+
background: color-mix(in srgb, var(--ui-accent-solid) 10%, var(--ui-control-surface));
|
|
316
|
+
box-shadow: inset 2px 0 var(--ui-accent-solid);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
[data-ui-choice-option][data-multiple] {
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: var(--ui-space-2);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
[data-ui-choice-option][data-multiple]::before {
|
|
326
|
+
content: "";
|
|
327
|
+
flex: none;
|
|
328
|
+
inline-size: 1.125rem;
|
|
329
|
+
block-size: 1.125rem;
|
|
330
|
+
border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));
|
|
331
|
+
border-radius: var(--ui-radius-sm);
|
|
332
|
+
background-color: var(--ui-control-surface);
|
|
333
|
+
background-repeat: no-repeat;
|
|
334
|
+
background-position: center;
|
|
335
|
+
background-size: 0.7rem;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
[data-ui-choice-option][data-multiple][aria-selected="true"]::before {
|
|
339
|
+
border-color: var(--ui-accent-solid);
|
|
340
|
+
background-color: var(--ui-accent-solid);
|
|
341
|
+
background-image: var(
|
|
342
|
+
--_ui-combobox-option-check,
|
|
343
|
+
var(
|
|
344
|
+
--ui-choice-check-icon,
|
|
345
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E")
|
|
346
|
+
)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
[aria-disabled="true"] [data-ui-choice-option] {
|
|
351
|
+
color: var(--ui-disabled-text);
|
|
352
|
+
cursor: not-allowed;
|
|
353
|
+
}
|
|
354
|
+
}
|