@adia-ai/web-components 0.7.2 → 0.7.4
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/CHANGELOG.md +42 -0
- package/components/accordion/accordion.css +2 -2
- package/components/action-list/action-list.css +2 -2
- package/components/agent-artifact/agent-artifact.css +31 -31
- package/components/agent-feedback-bar/agent-feedback-bar.css +10 -10
- package/components/agent-questions/agent-questions.css +59 -57
- package/components/agent-reasoning/agent-reasoning.css +54 -54
- package/components/agent-suggestions/agent-suggestions.css +4 -4
- package/components/agent-trace/agent-trace.css +53 -53
- package/components/alert/alert.css +53 -53
- package/components/avatar/avatar.css +27 -27
- package/components/badge/badge.css +56 -53
- package/components/block/block.css +16 -16
- package/components/blockquote/blockquote.css +16 -16
- package/components/breadcrumb/breadcrumb.css +23 -23
- package/components/button/button.css +99 -100
- package/components/calendar-grid/calendar-grid.css +95 -92
- package/components/calendar-picker/calendar-picker.css +141 -139
- package/components/canvas/canvas.css +12 -12
- package/components/card/card.css +83 -83
- package/components/chart/chart.css +218 -218
- package/components/chart-legend/chart-legend.css +26 -26
- package/components/check/check.css +40 -40
- package/components/code/code.css +125 -125
- package/components/col/col.a2ui.json +1 -1
- package/components/col/col.css +15 -15
- package/components/col/col.d.ts +1 -1
- package/components/col/col.yaml +6 -3
- package/components/color-picker/color-picker.css +55 -55
- package/components/combobox/combobox.css +64 -62
- package/components/command/command.css +91 -91
- package/components/context-menu/context-menu.css +1 -1
- package/components/date-range-picker/date-range-picker.css +59 -59
- package/components/datetime-picker/datetime-picker.css +25 -25
- package/components/demo-toggle/demo-toggle.css +27 -27
- package/components/description-list/description-list.css +18 -18
- package/components/divider/divider.css +24 -24
- package/components/embed/embed.css +6 -6
- package/components/empty-state/empty-state.css +29 -29
- package/components/feed/feed.css +12 -12
- package/components/field/field.css +28 -28
- package/components/field/field.test.js +2 -2
- package/components/fields/fields.css +5 -5
- package/components/grid/grid.a2ui.json +11 -1
- package/components/grid/grid.css +26 -7
- package/components/grid/grid.d.ts +5 -1
- package/components/grid/grid.yaml +18 -3
- package/components/heatmap/heatmap.css +61 -61
- package/components/icon/icon.css +12 -12
- package/components/image/image.css +14 -14
- package/components/inline-edit/inline-edit.css +16 -16
- package/components/inline-message/inline-message.css +16 -16
- package/components/input/input.css +69 -66
- package/components/inspector/inspector.css +6 -6
- package/components/integration-card/integration-card.css +41 -41
- package/components/integration-card/integration-card.test.js +4 -4
- package/components/kbd/kbd.css +47 -40
- package/components/link/link.css +12 -12
- package/components/list/list.css +8 -8
- package/components/list-window/list-window.css +10 -10
- package/components/loading-overlay/loading-overlay.css +17 -18
- package/components/loading-overlay/loading-overlay.test.js +8 -8
- package/components/mark/mark.css +16 -16
- package/components/menu/menu.css +9 -9
- package/components/modal/modal.class.js +5 -9
- package/components/modal/modal.css +43 -43
- package/components/nav/nav.css +40 -40
- package/components/nav-group/nav-group.css +54 -54
- package/components/nav-item/nav-item.css +44 -44
- package/components/noodles/noodles.css +31 -31
- package/components/number-format/number-format.css +4 -4
- package/components/option-card/option-card.css +70 -70
- package/components/otp-input/otp-input.css +29 -29
- package/components/page/page.a2ui.json +1 -1
- package/components/page/page.css +27 -27
- package/components/page/page.d.ts +1 -1
- package/components/page/page.yaml +1 -1
- package/components/pagination/pagination.css +6 -6
- package/components/pane/pane.css +57 -57
- package/components/password-strength/password-strength.css +32 -32
- package/components/pipeline-status/pipeline-status.css +67 -67
- package/components/popover/popover.css +11 -11
- package/components/preview/preview.css +21 -21
- package/components/progress/progress.css +23 -23
- package/components/progress-row/progress-row.css +17 -17
- package/components/qr-code/qr-code.css +4 -4
- package/components/radio/radio.css +39 -39
- package/components/range/range.css +58 -55
- package/components/rating/rating.css +28 -28
- package/components/relative-time/relative-time.css +6 -6
- package/components/richtext/richtext.css +133 -133
- package/components/row/row.a2ui.json +1 -1
- package/components/row/row.css +24 -22
- package/components/row/row.d.ts +1 -1
- package/components/row/row.yaml +4 -2
- package/components/search/search.css +5 -5
- package/components/segment/segment.css +29 -24
- package/components/segmented/segmented.css +30 -25
- package/components/select/select.css +95 -93
- package/components/skeleton/skeleton.css +14 -14
- package/components/skip-nav/skip-nav.css +4 -4
- package/components/slider/slider.css +61 -61
- package/components/spinner/spinner.css +40 -40
- package/components/spinner/spinner.test.js +10 -12
- package/components/stack/stack.css +11 -11
- package/components/stat/stat.css +27 -27
- package/components/step-progress/step-progress.css +20 -20
- package/components/stepper/stepper.css +29 -29
- package/components/stream/stream.css +12 -12
- package/components/swatch/swatch.css +68 -68
- package/components/swiper/swiper.class.js +5 -12
- package/components/swiper/swiper.css +57 -57
- package/components/switch/switch.css +53 -53
- package/components/table/table.css +166 -163
- package/components/table-toolbar/table-toolbar.css +33 -33
- package/components/tabs/tabs.css +54 -51
- package/components/tag/tag.css +74 -71
- package/components/tag/tag.test.js +14 -14
- package/components/tags-input/tags-input.css +51 -49
- package/components/text/text.css +44 -44
- package/components/textarea/textarea.css +49 -46
- package/components/time-picker/time-picker.css +47 -47
- package/components/timeline/timeline.css +54 -54
- package/components/toast/toast.css +58 -58
- package/components/toc/toc.css +28 -28
- package/components/toggle-group/toggle-group.css +9 -6
- package/components/toggle-scheme/toggle-scheme.css +2 -2
- package/components/toolbar/toolbar.css +18 -18
- package/components/tooltip/tooltip.css +2 -2
- package/components/tour/tour.css +4 -4
- package/components/tree/tree.class.js +89 -16
- package/components/tree/tree.css +37 -37
- package/components/tree/tree.test.js +49 -0
- package/components/upload/upload.css +49 -49
- package/dist/host.min.css +1 -0
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +3 -3
- package/package.json +1 -1
- package/styles/api/sizing.css +52 -16
- package/styles/foundation/space.css +25 -8
- package/styles/host.css +48 -0
- package/styles/prose.css +187 -170
- package/styles/type/scale.css +6 -0
- package/styles/typography.css +10 -5
- package/styles/verse.css +122 -0
|
@@ -10,18 +10,18 @@ toggle-option-ui:not([disabled]):hover {
|
|
|
10
10
|
@scope (toggle-group-ui) {
|
|
11
11
|
:where(:scope) {
|
|
12
12
|
/* ── Tokens ── */
|
|
13
|
-
--toggle-group-border-width
|
|
14
|
-
--toggle-group-border-color
|
|
15
|
-
--toggle-group-radius
|
|
16
|
-
--toggle-group-height
|
|
13
|
+
--toggle-group-border-width: 1px;
|
|
14
|
+
--toggle-group-border-color: var(--a-ui-border);
|
|
15
|
+
--toggle-group-radius: var(--a-radius);
|
|
16
|
+
--toggle-group-height: var(--a-size);
|
|
17
17
|
text-align: start; /* §text-align-reset — blocks inheritance from centered ancestors */
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
:scope {
|
|
21
21
|
box-sizing: border-box;
|
|
22
22
|
display: flex;
|
|
23
|
-
border: var(--toggle-group-border-width
|
|
24
|
-
border-radius: var(--toggle-group-radius
|
|
23
|
+
border: var(--toggle-group-border-width) solid var(--toggle-group-border-color);
|
|
24
|
+
border-radius: var(--toggle-group-radius);
|
|
25
25
|
overflow: hidden;
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -70,6 +70,9 @@ toggle-option-ui:not([disabled]):hover {
|
|
|
70
70
|
background: var(--toggle-option-bg);
|
|
71
71
|
color: var(--toggle-option-fg);
|
|
72
72
|
font: inherit;
|
|
73
|
+
/* font-family floor — see segment.css rationale (inline default; this
|
|
74
|
+
scope's tokens don't use the -default suffix). */
|
|
75
|
+
font-family: var(--toggle-option-font-family, var(--a-font-family-ui));
|
|
73
76
|
font-size: var(--toggle-option-font-size);
|
|
74
77
|
cursor: pointer;
|
|
75
78
|
transition:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@scope (toggle-scheme-ui) {
|
|
2
2
|
:where(:scope) {
|
|
3
|
-
--toggle-scheme-icon-transition
|
|
3
|
+
--toggle-scheme-icon-transition: var(--a-duration-fast) var(--a-easing);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
:scope {
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
:scope > [part="button"] {
|
|
21
|
-
transition: color var(--toggle-scheme-icon-transition
|
|
21
|
+
transition: color var(--toggle-scheme-icon-transition);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
@scope (toolbar-ui) {
|
|
2
2
|
:where(:scope) {
|
|
3
3
|
/* ── Layout ── */
|
|
4
|
-
--toolbar-gap
|
|
5
|
-
--toolbar-radius
|
|
6
|
-
--toolbar-px
|
|
7
|
-
--toolbar-py
|
|
4
|
+
--toolbar-gap: var(--a-space-1);
|
|
5
|
+
--toolbar-radius: var(--a-radius-md);
|
|
6
|
+
--toolbar-px: var(--a-space-1);
|
|
7
|
+
--toolbar-py: var(--a-space-1);
|
|
8
8
|
|
|
9
9
|
/* ── Colors ── */
|
|
10
|
-
--toolbar-bg
|
|
11
|
-
--toolbar-fg
|
|
12
|
-
--toolbar-border
|
|
10
|
+
--toolbar-bg: transparent;
|
|
11
|
+
--toolbar-fg: var(--a-fg);
|
|
12
|
+
--toolbar-border: var(--a-border-subtle);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/* ── Base ── */
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
display: flex;
|
|
19
19
|
flex-direction: row;
|
|
20
20
|
align-items: center;
|
|
21
|
-
gap: var(--toolbar-gap
|
|
22
|
-
padding: var(--toolbar-py
|
|
23
|
-
border-radius: var(--toolbar-radius
|
|
24
|
-
color: var(--toolbar-fg
|
|
21
|
+
gap: var(--toolbar-gap);
|
|
22
|
+
padding: var(--toolbar-py) var(--toolbar-px);
|
|
23
|
+
border-radius: var(--toolbar-radius);
|
|
24
|
+
color: var(--toolbar-fg);
|
|
25
25
|
min-width: 0; /* allow shrinking within flex/grid parents */
|
|
26
26
|
overflow: hidden; /* prevent pre-measurement flash before reflow */
|
|
27
27
|
}
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
|
|
35
35
|
/* ── Bordered ── */
|
|
36
36
|
:scope[bordered] {
|
|
37
|
-
border: 1px solid var(--toolbar-border
|
|
38
|
-
background: var(--toolbar-bg
|
|
37
|
+
border: 1px solid var(--toolbar-border);
|
|
38
|
+
background: var(--toolbar-bg);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/* ── Gap variants ── */
|
|
42
|
-
:scope[gap="sm"] { --toolbar-gap
|
|
43
|
-
:scope[gap="md"] { --toolbar-gap
|
|
44
|
-
:scope[gap="lg"] { --toolbar-gap
|
|
42
|
+
:scope[gap="sm"] { --toolbar-gap: var(--a-space-1); }
|
|
43
|
+
:scope[gap="md"] { --toolbar-gap: var(--a-space-2); }
|
|
44
|
+
:scope[gap="lg"] { --toolbar-gap: var(--a-space-3); }
|
|
45
45
|
|
|
46
46
|
/* ── Align ── */
|
|
47
47
|
:scope[align="start"] { justify-content: flex-start; }
|
|
@@ -102,9 +102,9 @@ toolbar-ui [data-toolbar-spillover-menu]:popover-open {
|
|
|
102
102
|
background: var(--a-bg-subtle);
|
|
103
103
|
box-shadow: var(--a-shadow-lg);
|
|
104
104
|
min-width: 10rem;
|
|
105
|
-
font-family:
|
|
105
|
+
font-family: var(--toolbar-font-family, var(--a-font-family-ui));
|
|
106
106
|
font-size: var(--a-ui-size);
|
|
107
|
-
color: var(--toolbar-fg
|
|
107
|
+
color: var(--toolbar-fg);
|
|
108
108
|
/* Stack overflow items as rows (each row can be a group with its own gap). */
|
|
109
109
|
display: flex;
|
|
110
110
|
flex-direction: column;
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
/* Host (anchor) tokens. The popover itself escapes to top-layer and
|
|
4
4
|
cannot inherit these — top-layer rules below reference --a-*
|
|
5
5
|
directly per documented exception. */
|
|
6
|
-
--tooltip-host-display
|
|
6
|
+
--tooltip-host-display: inline-flex;
|
|
7
7
|
}
|
|
8
8
|
:scope {
|
|
9
9
|
/* ── Base ── */
|
|
10
10
|
box-sizing: border-box;
|
|
11
|
-
display: var(--tooltip-host-display
|
|
11
|
+
display: var(--tooltip-host-display);
|
|
12
12
|
position: relative;
|
|
13
13
|
}
|
|
14
14
|
}
|
package/components/tour/tour.css
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
@scope (tour-ui) {
|
|
2
2
|
:where(:scope) {
|
|
3
|
-
--tour-scrim
|
|
4
|
-
--tour-spotlight-padding
|
|
5
|
-
--tour-spotlight-radius
|
|
3
|
+
--tour-scrim: var(--a-scrim-dialog);
|
|
4
|
+
--tour-spotlight-padding: var(--a-space-2);
|
|
5
|
+
--tour-spotlight-radius: var(--a-radius-md);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
:scope {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
box-shadow: var(--tour-popover-shadow, var(--a-shadow-lg));
|
|
68
68
|
min-width: var(--tour-popover-min-width, 18rem);
|
|
69
69
|
max-width: var(--tour-popover-max-width, 22rem);
|
|
70
|
-
font-family:
|
|
70
|
+
font-family: var(--tour-font-family, var(--a-font-family-ui));
|
|
71
71
|
font-size: var(--a-ui-size);
|
|
72
72
|
color: var(--a-fg);
|
|
73
73
|
/* Above the spotlight (1000) so the user can read + click it */
|
|
@@ -266,6 +266,11 @@ export class UITreeItem extends UIElement {
|
|
|
266
266
|
|
|
267
267
|
static template = () => null;
|
|
268
268
|
|
|
269
|
+
// FB-96: late-adoption of interpolated [slot="actions"]/[slot="caret"]
|
|
270
|
+
// children — see connected() + #adoptSlotted().
|
|
271
|
+
#slotObserver = null;
|
|
272
|
+
#adopting = false;
|
|
273
|
+
|
|
269
274
|
get hasChildren() {
|
|
270
275
|
return this.querySelector(':scope > tree-item-ui') !== null;
|
|
271
276
|
}
|
|
@@ -303,6 +308,17 @@ export class UITreeItem extends UIElement {
|
|
|
303
308
|
row.setAttribute('role', 'treeitem');
|
|
304
309
|
if (!row.hasAttribute('tabindex')) row.setAttribute('tabindex', '0');
|
|
305
310
|
}
|
|
311
|
+
|
|
312
|
+
// FB-96: declarative [slot="actions"]/[slot="caret"] children rendered via
|
|
313
|
+
// the template engine (`.map()`/`repeat()`/conditional) arrive in a LATER
|
|
314
|
+
// reactive tick — AFTER #stamp() — nested in the engine's display:contents
|
|
315
|
+
// wrapper spans. So neither a connect-time read nor a `:scope >` direct-child
|
|
316
|
+
// query sees them, and e.g. a `<button-ui slot="actions">` is left as a bare
|
|
317
|
+
// role=button child of the group/tree (axe `aria-required-children`). Adopt
|
|
318
|
+
// what's present now, then observe for the late arrivals.
|
|
319
|
+
this.#adoptSlotted();
|
|
320
|
+
this.#slotObserver = new MutationObserver(() => this.#adoptSlotted());
|
|
321
|
+
this.#slotObserver.observe(this, { childList: true, subtree: true });
|
|
306
322
|
}
|
|
307
323
|
|
|
308
324
|
#stamp() {
|
|
@@ -310,15 +326,18 @@ export class UITreeItem extends UIElement {
|
|
|
310
326
|
row.setAttribute('slot', 'row');
|
|
311
327
|
row.setAttribute('tabindex', '0');
|
|
312
328
|
|
|
313
|
-
// Caret — adopt a declarative [slot="caret"] child if
|
|
314
|
-
//
|
|
315
|
-
|
|
329
|
+
// Caret — adopt a declarative [slot="caret"] child if one is already present
|
|
330
|
+
// (incl. inside the engine's display:contents wrappers, FB-96), else stamp
|
|
331
|
+
// the default, marked so #adoptSlotted() can drop it if a declared caret
|
|
332
|
+
// arrives late.
|
|
333
|
+
const declaredCaret = this.#logicalSlotChildren('caret')[0];
|
|
316
334
|
if (declaredCaret) {
|
|
317
335
|
row.appendChild(declaredCaret);
|
|
318
336
|
} else {
|
|
319
337
|
const caret = document.createElement('icon-ui');
|
|
320
338
|
caret.setAttribute('slot', 'caret');
|
|
321
339
|
caret.setAttribute('name', 'caret-right');
|
|
340
|
+
caret.dataset.treeCaretDefault = '1';
|
|
322
341
|
row.appendChild(caret);
|
|
323
342
|
}
|
|
324
343
|
|
|
@@ -343,19 +362,16 @@ export class UITreeItem extends UIElement {
|
|
|
343
362
|
if (this.badge) badgeEl.textContent = this.badge;
|
|
344
363
|
row.appendChild(badgeEl);
|
|
345
364
|
|
|
346
|
-
// Actions —
|
|
347
|
-
//
|
|
348
|
-
//
|
|
349
|
-
// #
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
actions.setAttribute('slot', 'actions');
|
|
357
|
-
row.appendChild(actions);
|
|
358
|
-
}
|
|
365
|
+
// Actions — stamp an empty placeholder; the real declarative [slot="actions"]
|
|
366
|
+
// children (FEEDBACK-89) are moved into the row by #adoptSlotted(), which
|
|
367
|
+
// runs in connected() AND on later mutations, so interpolated buttons that
|
|
368
|
+
// arrive after #stamp (nested in the engine's display:contents wrappers,
|
|
369
|
+
// FB-96) get adopted too. The placeholder is dropped once a real one lands.
|
|
370
|
+
// (#onClick excludes [slot="actions"] * from row selection — adoption-safe.)
|
|
371
|
+
const actions = document.createElement('span');
|
|
372
|
+
actions.setAttribute('slot', 'actions');
|
|
373
|
+
actions.dataset.treeActionsPlaceholder = '1';
|
|
374
|
+
row.appendChild(actions);
|
|
359
375
|
|
|
360
376
|
this.prepend(row);
|
|
361
377
|
}
|
|
@@ -385,4 +401,61 @@ export class UITreeItem extends UIElement {
|
|
|
385
401
|
const badgeEl = row.querySelector('[slot="badge"]');
|
|
386
402
|
if (badgeEl) badgeEl.textContent = this.badge || '';
|
|
387
403
|
}
|
|
404
|
+
|
|
405
|
+
// ── FB-96: wrapper-piercing, late adoption of slotted row children ──
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Collect this item's logical `[slot="<slot>"]` children — direct, or nested
|
|
409
|
+
* inside the template engine's `display:contents` wrapper spans (which carry
|
|
410
|
+
* `role="presentation"` since 0.7.2) — but NOT inside a nested `<tree-item-ui>`
|
|
411
|
+
* (a plain descendant query would wrongly grab a child item's actions/caret).
|
|
412
|
+
*/
|
|
413
|
+
#logicalSlotChildren(slot) {
|
|
414
|
+
const out = [];
|
|
415
|
+
const walk = (parent) => {
|
|
416
|
+
for (const ch of parent.children) {
|
|
417
|
+
if (ch.matches('tree-item-ui')) continue; // nested-item boundary
|
|
418
|
+
if (ch.getAttribute('slot') === slot) { out.push(ch); continue; }
|
|
419
|
+
// pierce the engine's transparent wrapper spans
|
|
420
|
+
if (ch.matches('[role="presentation"]') || ch.style?.display === 'contents') walk(ch);
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
walk(this);
|
|
424
|
+
return out;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Move declarative `[slot="actions"]`/`[slot="caret"]` children into the
|
|
429
|
+
* stamped row. Idempotent + re-entrancy-guarded (it mutates `this`, which
|
|
430
|
+
* re-fires #slotObserver). Drops the auto-stamped placeholder/default once a
|
|
431
|
+
* real child is adopted. (FEEDBACK-89 + FB-96.)
|
|
432
|
+
*/
|
|
433
|
+
#adoptSlotted() {
|
|
434
|
+
if (this.#adopting) return;
|
|
435
|
+
const row = this.querySelector(':scope > [slot="row"]');
|
|
436
|
+
if (!row) return;
|
|
437
|
+
this.#adopting = true;
|
|
438
|
+
try {
|
|
439
|
+
const actions = this.#logicalSlotChildren('actions')
|
|
440
|
+
.filter((el) => !el.dataset.treeActionsPlaceholder && el.parentElement !== row);
|
|
441
|
+
if (actions.length) {
|
|
442
|
+
row.querySelector(':scope > [slot="actions"][data-tree-actions-placeholder]')?.remove();
|
|
443
|
+
for (const el of actions) row.appendChild(el);
|
|
444
|
+
}
|
|
445
|
+
const caret = this.#logicalSlotChildren('caret')
|
|
446
|
+
.find((el) => !el.dataset.treeCaretDefault && el.parentElement !== row);
|
|
447
|
+
if (caret) {
|
|
448
|
+
row.querySelector(':scope > [slot="caret"][data-tree-caret-default]')?.remove();
|
|
449
|
+
row.prepend(caret);
|
|
450
|
+
}
|
|
451
|
+
} finally {
|
|
452
|
+
this.#slotObserver?.takeRecords(); // drain self-mutations — no re-entrant pass
|
|
453
|
+
this.#adopting = false;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
disconnected() {
|
|
458
|
+
this.#slotObserver?.disconnect();
|
|
459
|
+
this.#slotObserver = null;
|
|
460
|
+
}
|
|
388
461
|
}
|
package/components/tree/tree.css
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
@scope (tree-ui) {
|
|
2
2
|
:where(:scope) {
|
|
3
3
|
/* ── Layout ── */
|
|
4
|
-
--tree-row-height
|
|
5
|
-
--tree-row-radius
|
|
6
|
-
--tree-row-px
|
|
7
|
-
--tree-row-gap
|
|
8
|
-
--tree-actions-gap
|
|
9
|
-
--tree-indent
|
|
10
|
-
--tree-caret-size
|
|
11
|
-
--tree-icon-size
|
|
4
|
+
--tree-row-height: var(--a-size);
|
|
5
|
+
--tree-row-radius: var(--a-radius-sm);
|
|
6
|
+
--tree-row-px: var(--a-space-1);
|
|
7
|
+
--tree-row-gap: var(--a-space-1);
|
|
8
|
+
--tree-actions-gap: var(--a-space-0-5);
|
|
9
|
+
--tree-indent: var(--a-space-4);
|
|
10
|
+
--tree-caret-size: var(--a-space-2);
|
|
11
|
+
--tree-icon-size: var(--a-space-3);
|
|
12
12
|
|
|
13
13
|
/* ── Typography ── */
|
|
14
|
-
--tree-font-size
|
|
14
|
+
--tree-font-size: var(--a-ui-size);
|
|
15
15
|
|
|
16
16
|
/* ── Colors ── */
|
|
17
|
-
--tree-fg
|
|
18
|
-
--tree-fg-muted
|
|
19
|
-
--tree-bg-hover
|
|
20
|
-
--tree-bg-selected
|
|
17
|
+
--tree-fg: var(--a-fg);
|
|
18
|
+
--tree-fg-muted: var(--a-fg-muted);
|
|
19
|
+
--tree-bg-hover: var(--a-bg-muted);
|
|
20
|
+
--tree-bg-selected: var(--a-bg-hover);
|
|
21
21
|
|
|
22
22
|
/* ── Transition ── */
|
|
23
|
-
--tree-duration
|
|
24
|
-
--tree-easing
|
|
23
|
+
--tree-duration: var(--a-duration-fast);
|
|
24
|
+
--tree-easing: var(--a-easing);
|
|
25
25
|
|
|
26
26
|
/* ── State ── */
|
|
27
|
-
--tree-focus-ring
|
|
27
|
+
--tree-focus-ring: var(--a-focus-ring);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
:scope {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
box-sizing: border-box;
|
|
33
33
|
display: flex;
|
|
34
34
|
flex-direction: column;
|
|
35
|
-
font-size: var(--tree-font-size
|
|
36
|
-
color: var(--tree-fg
|
|
35
|
+
font-size: var(--tree-font-size);
|
|
36
|
+
color: var(--tree-fg);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -69,35 +69,35 @@
|
|
|
69
69
|
[slot="row"] {
|
|
70
70
|
display: flex;
|
|
71
71
|
align-items: center;
|
|
72
|
-
gap: var(--tree-row-gap
|
|
73
|
-
height: var(--tree-row-height
|
|
74
|
-
padding-inline-end: var(--tree-row-px
|
|
75
|
-
border-radius: var(--tree-row-radius
|
|
72
|
+
gap: var(--tree-row-gap);
|
|
73
|
+
height: var(--tree-row-height);
|
|
74
|
+
padding-inline-end: var(--tree-row-px);
|
|
75
|
+
border-radius: var(--tree-row-radius);
|
|
76
76
|
cursor: pointer;
|
|
77
77
|
user-select: none;
|
|
78
78
|
white-space: nowrap;
|
|
79
79
|
transition:
|
|
80
|
-
background var(--tree-duration
|
|
81
|
-
color var(--tree-duration
|
|
80
|
+
background var(--tree-duration) var(--tree-easing),
|
|
81
|
+
color var(--tree-duration) var(--tree-easing);
|
|
82
82
|
outline: none;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
[slot="row"]:hover {
|
|
86
|
-
background: var(--tree-bg-hover
|
|
86
|
+
background: var(--tree-bg-hover);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
[slot="row"]:focus-visible {
|
|
90
|
-
box-shadow: var(--tree-focus-ring
|
|
90
|
+
box-shadow: var(--tree-focus-ring);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/* :scope[selected] rules moved outside @scope — see tree-ui Safari note at end of file. */
|
|
94
94
|
|
|
95
95
|
/* ── Caret ── */
|
|
96
96
|
[slot="caret"] {
|
|
97
|
-
--a-icon-size: var(--tree-caret-size
|
|
97
|
+
--a-icon-size: var(--tree-caret-size);
|
|
98
98
|
flex-shrink: 0;
|
|
99
|
-
color: var(--tree-fg-muted
|
|
100
|
-
transition: transform var(--tree-duration
|
|
99
|
+
color: var(--tree-fg-muted);
|
|
100
|
+
transition: transform var(--tree-duration) var(--tree-easing);
|
|
101
101
|
transform: rotate(90deg);
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -112,8 +112,8 @@
|
|
|
112
112
|
|
|
113
113
|
/* ── Icon ── */
|
|
114
114
|
[slot="icon"] {
|
|
115
|
-
--a-icon-size: var(--tree-icon-size
|
|
116
|
-
color: var(--tree-fg-muted
|
|
115
|
+
--a-icon-size: var(--tree-icon-size);
|
|
116
|
+
color: var(--tree-fg-muted);
|
|
117
117
|
flex-shrink: 0;
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
[slot="badge"] {
|
|
135
135
|
flex-shrink: 0;
|
|
136
136
|
font-size: var(--tree-badge-size, var(--a-ui-xs));
|
|
137
|
-
color: var(--tree-badge-fg, var(--tree-fg-muted
|
|
137
|
+
color: var(--tree-badge-fg, var(--tree-fg-muted));
|
|
138
138
|
background: var(--tree-badge-bg, transparent);
|
|
139
139
|
padding: 0 var(--tree-badge-px, var(--a-space-1));
|
|
140
140
|
border-radius: var(--tree-badge-radius, var(--a-radius-sm));
|
|
@@ -149,10 +149,10 @@
|
|
|
149
149
|
[slot="actions"] {
|
|
150
150
|
display: flex;
|
|
151
151
|
align-items: center;
|
|
152
|
-
gap: var(--tree-actions-gap
|
|
152
|
+
gap: var(--tree-actions-gap);
|
|
153
153
|
margin-inline-start: auto;
|
|
154
154
|
opacity: 0;
|
|
155
|
-
transition: opacity var(--tree-duration
|
|
155
|
+
transition: opacity var(--tree-duration) var(--tree-easing);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
[slot="row"]:hover [slot="actions"] {
|
|
@@ -173,11 +173,11 @@
|
|
|
173
173
|
`:where(:scope)` still resolve via inheritance. See
|
|
174
174
|
docs/BROWSER-COMPAT.md §3a. */
|
|
175
175
|
tree-ui[selected] > [slot="row"] {
|
|
176
|
-
background: var(--tree-bg-selected
|
|
177
|
-
color: var(--tree-fg
|
|
176
|
+
background: var(--tree-bg-selected);
|
|
177
|
+
color: var(--tree-fg);
|
|
178
178
|
}
|
|
179
179
|
tree-ui[selected] > [slot="row"] [slot="icon"] {
|
|
180
|
-
color: var(--tree-fg
|
|
180
|
+
color: var(--tree-fg);
|
|
181
181
|
}
|
|
182
182
|
tree-ui[selected] > [slot="row"] [slot="actions"] {
|
|
183
183
|
opacity: 1;
|
|
@@ -11,6 +11,7 @@ import { html, stamp } from '../../core/template.js';
|
|
|
11
11
|
|
|
12
12
|
beforeAll(async () => {
|
|
13
13
|
await import('./tree.js');
|
|
14
|
+
await import('../button/button.js');
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
describe('<tree-ui> tree-select forwards modifier keys (FB-46)', () => {
|
|
@@ -261,3 +262,51 @@ describe('<tree-item-ui> ARIA tree containment (FEEDBACK-91)', () => {
|
|
|
261
262
|
expect(parent.querySelector(':scope > [slot="row"]').hasAttribute('aria-selected')).toBe(false);
|
|
262
263
|
});
|
|
263
264
|
});
|
|
265
|
+
|
|
266
|
+
describe('<tree-item-ui> adopts interpolated [slot="actions"] into the row (FEEDBACK-96)', () => {
|
|
267
|
+
let host;
|
|
268
|
+
const settle = () => new Promise((r) => setTimeout(r, 40));
|
|
269
|
+
beforeEach(() => { host = document.createElement('div'); document.body.appendChild(host); });
|
|
270
|
+
afterEach(() => host.remove());
|
|
271
|
+
|
|
272
|
+
it('moves a `.map()`-rendered actions button into the treeitem row (not a stray child of the group)', async () => {
|
|
273
|
+
const PALS = [{ id: 'n', name: 'Neutral' }, { id: 'b', name: 'Brand' }];
|
|
274
|
+
stamp(html`
|
|
275
|
+
<tree-ui>
|
|
276
|
+
<tree-item-ui text="Colors" value="colors" open>
|
|
277
|
+
${html`<button-ui slot="actions" icon="plus" title="Add"></button-ui>`}
|
|
278
|
+
${PALS.map((p) => html`<tree-item-ui text="${p.name}" value="${p.id}"></tree-item-ui>`)}
|
|
279
|
+
</tree-item-ui>
|
|
280
|
+
</tree-ui>
|
|
281
|
+
`, host);
|
|
282
|
+
await settle();
|
|
283
|
+
|
|
284
|
+
const colors = host.querySelector('tree-item-ui[value="colors"]');
|
|
285
|
+
const row = colors.querySelector(':scope > [slot="row"]');
|
|
286
|
+
const btn = colors.querySelector('button-ui[slot="actions"]');
|
|
287
|
+
expect(btn).not.toBeNull();
|
|
288
|
+
// The fix: the interpolated button (wrapped in a display:contents span) is
|
|
289
|
+
// adopted INTO the row. Pre-fix, #stamp's `:scope >` query missed it (the
|
|
290
|
+
// button arrives after #stamp, inside a wrapper span) and it stayed a bare
|
|
291
|
+
// child of the group/tree → axe aria-required-children.
|
|
292
|
+
expect(btn.parentElement).toBe(row);
|
|
293
|
+
// Auto-stamped empty placeholder dropped — exactly one actions slot in the row.
|
|
294
|
+
expect(row.querySelectorAll(':scope > [slot="actions"]').length).toBe(1);
|
|
295
|
+
// Nested items NOT mis-adopted as actions (the tree-item-ui boundary holds).
|
|
296
|
+
expect(host.querySelectorAll('tree-item-ui').length).toBe(3);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('is idempotent — no double-adopt across settles', async () => {
|
|
300
|
+
stamp(html`
|
|
301
|
+
<tree-ui>
|
|
302
|
+
<tree-item-ui text="Colors" value="colors" open>
|
|
303
|
+
${html`<button-ui slot="actions" icon="plus"></button-ui>`}
|
|
304
|
+
</tree-item-ui>
|
|
305
|
+
</tree-ui>
|
|
306
|
+
`, host);
|
|
307
|
+
await settle();
|
|
308
|
+
await settle();
|
|
309
|
+
const row = host.querySelector('tree-item-ui[value="colors"] > [slot="row"]');
|
|
310
|
+
expect(row.querySelectorAll(':scope > [slot="actions"]').length).toBe(1);
|
|
311
|
+
});
|
|
312
|
+
});
|