@adia-ai/web-components 0.6.34 → 0.6.36
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 +71 -0
- package/color/index.js +1 -1
- package/components/accordion/accordion-item.yaml +2 -2
- package/components/accordion/accordion.js +1 -1
- package/components/action-list/action-item.yaml +2 -2
- package/components/action-list/action-list.js +1 -1
- package/components/agent-artifact/{class.js → agent-artifact.class.js} +1 -1
- package/components/agent-artifact/agent-artifact.js +1 -1
- package/components/agent-feedback-bar/agent-feedback-bar.js +1 -1
- package/components/agent-questions/agent-questions.js +1 -1
- package/components/agent-reasoning/agent-reasoning.js +1 -1
- package/components/agent-suggestions/agent-suggestions.js +1 -1
- package/components/alert/alert.a2ui.json +64 -1
- package/components/alert/{class.js → alert.class.js} +189 -2
- package/components/alert/alert.css +78 -0
- package/components/alert/alert.d.ts +14 -0
- package/components/alert/alert.js +1 -1
- package/components/alert/alert.test.js +184 -0
- package/components/alert/alert.yaml +114 -1
- package/components/avatar/avatar-group.yaml +2 -2
- package/components/avatar/avatar.js +1 -1
- package/components/badge/badge.js +1 -1
- package/components/block/block.js +1 -1
- package/components/breadcrumb/breadcrumb.js +1 -1
- package/components/button/button.js +1 -1
- package/components/calendar-grid/calendar-grid.a2ui.json +10 -0
- package/components/calendar-grid/{class.js → calendar-grid.class.js} +30 -4
- package/components/calendar-grid/calendar-grid.css +20 -0
- package/components/calendar-grid/calendar-grid.d.ts +4 -0
- package/components/calendar-grid/calendar-grid.js +1 -1
- package/components/calendar-grid/calendar-grid.yaml +20 -0
- package/components/calendar-picker/calendar-picker.js +1 -1
- package/components/card/card.js +1 -1
- package/components/chart/chart.js +1 -1
- package/components/chart-legend/chart-legend.js +1 -1
- package/components/chat-thread/chat-input.a2ui.json +1 -1
- package/components/chat-thread/chat-input.js +6 -1
- package/components/chat-thread/chat-input.yaml +4 -1
- package/components/chat-thread/chat-thread.js +1 -1
- package/components/check/check.js +1 -1
- package/components/code/code.js +1 -1
- package/components/col/col.js +1 -1
- package/components/color-input/color-input.js +1 -1
- package/components/color-picker/color-picker.js +1 -1
- package/components/combobox/combobox.css +12 -0
- package/components/combobox/combobox.js +1 -1
- package/components/command/command.js +1 -1
- package/components/date-range-picker/{class.js → date-range-picker.class.js} +19 -3
- package/components/date-range-picker/date-range-picker.css +55 -6
- package/components/date-range-picker/date-range-picker.js +1 -1
- package/components/datetime-picker/{class.js → datetime-picker.class.js} +1 -1
- package/components/datetime-picker/datetime-picker.css +7 -1
- package/components/datetime-picker/datetime-picker.js +1 -1
- package/components/demo-toggle/demo-toggle.js +1 -1
- package/components/description-list/description-list.js +1 -1
- package/components/divider/divider.js +1 -1
- package/components/drawer/drawer.js +1 -1
- package/components/embed/embed.js +1 -1
- package/components/empty-state/empty-state.js +1 -1
- package/components/feed/feed.js +1 -1
- package/components/field/field.js +1 -1
- package/components/field/field.test.js +1 -1
- package/components/fields/fields.js +1 -1
- package/components/grid/grid.js +1 -1
- package/components/heatmap/heatmap.js +1 -1
- package/components/icon/icon.js +1 -1
- package/components/image/image.js +1 -1
- package/components/index.js +3 -0
- package/components/inline-message/inline-message.a2ui.json +143 -0
- package/components/inline-message/inline-message.class.js +169 -0
- package/components/inline-message/inline-message.css +75 -0
- package/components/inline-message/inline-message.d.ts +31 -0
- package/components/inline-message/inline-message.examples.md +19 -0
- package/components/inline-message/inline-message.js +17 -0
- package/components/inline-message/inline-message.test.js +203 -0
- package/components/inline-message/inline-message.yaml +205 -0
- package/components/input/input.css +16 -2
- package/components/input/input.js +1 -1
- package/components/input/input.test.js +40 -0
- package/components/input/input.yaml +5 -4
- package/components/inspector/inspector.js +1 -1
- package/components/integration-card/integration-card.js +1 -1
- package/components/kbd/kbd.js +1 -1
- package/components/link/link.js +1 -1
- package/components/list/list-item.yaml +2 -2
- package/components/list/list.js +1 -1
- package/components/list-window/list-window.js +1 -1
- package/components/loading-overlay/loading-overlay.a2ui.json +176 -0
- package/components/loading-overlay/loading-overlay.class.js +203 -0
- package/components/loading-overlay/loading-overlay.css +81 -0
- package/components/loading-overlay/loading-overlay.d.ts +24 -0
- package/components/loading-overlay/loading-overlay.examples.md +50 -0
- package/components/loading-overlay/loading-overlay.js +17 -0
- package/components/loading-overlay/loading-overlay.test.js +257 -0
- package/components/loading-overlay/loading-overlay.yaml +260 -0
- package/components/menu/menu-divider.yaml +1 -1
- package/components/menu/menu-item.yaml +1 -1
- package/components/menu/menu.a2ui.json +3 -0
- package/components/menu/menu.js +1 -1
- package/components/menu/menu.yaml +7 -0
- package/components/modal/{class.js → modal.class.js} +12 -1
- package/components/modal/modal.css +11 -1
- package/components/modal/modal.js +1 -1
- package/components/nav/nav.js +1 -1
- package/components/nav-group/nav-group.js +1 -1
- package/components/nav-item/nav-item.js +1 -1
- package/components/noodles/noodles.js +1 -1
- package/components/option-card/option-card.js +1 -1
- package/components/otp-input/otp-input.js +1 -1
- package/components/page/page.js +1 -1
- package/components/pagination/pagination.js +1 -1
- package/components/pane/pane.js +1 -1
- package/components/pipeline-status/pipeline-status.js +1 -1
- package/components/popover/popover.a2ui.json +8 -1
- package/components/popover/popover.js +1 -1
- package/components/popover/popover.yaml +14 -1
- package/components/progress/progress.js +1 -1
- package/components/progress-row/progress-row.js +1 -1
- package/components/radio/radio.js +1 -1
- package/components/range/range.js +1 -1
- package/components/rating/rating.js +1 -1
- package/components/richtext/richtext.js +1 -1
- package/components/row/row.js +1 -1
- package/components/search/{class.js → search.class.js} +2 -0
- package/components/search/search.js +1 -1
- package/components/segment/segment.js +1 -1
- package/components/segmented/segmented.js +1 -1
- package/components/select/select.a2ui.json +58 -4
- package/components/select/{class.js → select.class.js} +415 -6
- package/components/select/select.css +158 -0
- package/components/select/select.d.ts +31 -1
- package/components/select/select.js +1 -1
- package/components/select/select.test.js +202 -0
- package/components/select/select.yaml +126 -5
- package/components/skeleton/skeleton.js +1 -1
- package/components/slider/slider.js +1 -1
- package/components/spinner/spinner.a2ui.json +3 -2
- package/components/spinner/{class.js → spinner.class.js} +33 -3
- package/components/spinner/spinner.css +91 -35
- package/components/spinner/spinner.d.ts +2 -2
- package/components/spinner/spinner.js +1 -1
- package/components/spinner/spinner.test.js +49 -11
- package/components/spinner/spinner.yaml +9 -1
- package/components/stack/stack.js +1 -1
- package/components/step-progress/step-progress.js +1 -1
- package/components/stepper/stepper-item.yaml +1 -1
- package/components/stepper/stepper.js +1 -1
- package/components/stream/stream.js +1 -1
- package/components/swatch/swatch.js +1 -1
- package/components/swiper/swiper.js +1 -1
- package/components/switch/switch.js +1 -1
- package/components/table/table.css +1 -1
- package/components/table/table.js +1 -1
- package/components/table-toolbar/{class.js → table-toolbar.class.js} +2 -1
- package/components/table-toolbar/table-toolbar.js +1 -1
- package/components/tabs/tab.yaml +2 -2
- package/components/tabs/tabs.js +1 -1
- package/components/tag/tag.a2ui.json +9 -0
- package/components/tag/{class.js → tag.class.js} +8 -1
- package/components/tag/tag.css +84 -20
- package/components/tag/tag.js +1 -1
- package/components/tag/tag.test.js +75 -1
- package/components/tag/tag.yaml +14 -0
- package/components/tags-input/tags-input.a2ui.json +337 -0
- package/components/tags-input/tags-input.class.js +783 -0
- package/components/tags-input/tags-input.css +210 -0
- package/components/tags-input/tags-input.d.ts +120 -0
- package/components/tags-input/tags-input.examples.md +92 -0
- package/components/tags-input/tags-input.js +17 -0
- package/components/tags-input/tags-input.test.js +368 -0
- package/components/tags-input/tags-input.yaml +367 -0
- package/components/text/text.js +1 -1
- package/components/textarea/textarea.a2ui.json +1 -1
- package/components/textarea/textarea.css +10 -1
- package/components/textarea/textarea.js +1 -1
- package/components/textarea/textarea.yaml +11 -8
- package/components/time-picker/time-picker.js +1 -1
- package/components/timeline/timeline-item.yaml +2 -2
- package/components/timeline/{class.js → timeline.class.js} +1 -1
- package/components/timeline/timeline.js +1 -1
- package/components/toast/toast.js +1 -1
- package/components/toggle-group/toggle-group.js +1 -1
- package/components/toggle-group/toggle-option.yaml +1 -1
- package/components/toggle-scheme/toggle-scheme.js +1 -1
- package/components/toolbar/toolbar-group.yaml +1 -1
- package/components/toolbar/toolbar.js +1 -1
- package/components/tooltip/tooltip.js +1 -1
- package/components/tree/tree-item.yaml +1 -1
- package/components/tree/tree.js +1 -1
- package/components/upload/upload.js +1 -1
- package/core/provider.js +19 -2
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +112 -90
- package/package.json +3 -3
- package/styles/components.css +3 -0
- /package/components/accordion/{class.js → accordion.class.js} +0 -0
- /package/components/action-list/{class.js → action-list.class.js} +0 -0
- /package/components/agent-feedback-bar/{class.js → agent-feedback-bar.class.js} +0 -0
- /package/components/agent-questions/{class.js → agent-questions.class.js} +0 -0
- /package/components/agent-reasoning/{class.js → agent-reasoning.class.js} +0 -0
- /package/components/agent-suggestions/{class.js → agent-suggestions.class.js} +0 -0
- /package/components/avatar/{class.js → avatar.class.js} +0 -0
- /package/components/badge/{class.js → badge.class.js} +0 -0
- /package/components/block/{class.js → block.class.js} +0 -0
- /package/components/breadcrumb/{class.js → breadcrumb.class.js} +0 -0
- /package/components/button/{class.js → button.class.js} +0 -0
- /package/components/calendar-picker/{class.js → calendar-picker.class.js} +0 -0
- /package/components/card/{class.js → card.class.js} +0 -0
- /package/components/chart/{class.js → chart.class.js} +0 -0
- /package/components/chart-legend/{class.js → chart-legend.class.js} +0 -0
- /package/components/chat-thread/{class.js → chat-thread.class.js} +0 -0
- /package/components/check/{class.js → check.class.js} +0 -0
- /package/components/code/{class.js → code.class.js} +0 -0
- /package/components/col/{class.js → col.class.js} +0 -0
- /package/components/color-input/{class.js → color-input.class.js} +0 -0
- /package/components/color-picker/{class.js → color-picker.class.js} +0 -0
- /package/components/combobox/{class.js → combobox.class.js} +0 -0
- /package/components/command/{class.js → command.class.js} +0 -0
- /package/components/demo-toggle/{class.js → demo-toggle.class.js} +0 -0
- /package/components/description-list/{class.js → description-list.class.js} +0 -0
- /package/components/divider/{class.js → divider.class.js} +0 -0
- /package/components/drawer/{class.js → drawer.class.js} +0 -0
- /package/components/embed/{class.js → embed.class.js} +0 -0
- /package/components/empty-state/{class.js → empty-state.class.js} +0 -0
- /package/components/feed/{class.js → feed.class.js} +0 -0
- /package/components/field/{class.js → field.class.js} +0 -0
- /package/components/fields/{class.js → fields.class.js} +0 -0
- /package/components/grid/{class.js → grid.class.js} +0 -0
- /package/components/heatmap/{class.js → heatmap.class.js} +0 -0
- /package/components/icon/{class.js → icon.class.js} +0 -0
- /package/components/image/{class.js → image.class.js} +0 -0
- /package/components/input/{class.js → input.class.js} +0 -0
- /package/components/inspector/{class.js → inspector.class.js} +0 -0
- /package/components/integration-card/{class.js → integration-card.class.js} +0 -0
- /package/components/kbd/{class.js → kbd.class.js} +0 -0
- /package/components/link/{class.js → link.class.js} +0 -0
- /package/components/list/{class.js → list.class.js} +0 -0
- /package/components/list-window/{class.js → list-window.class.js} +0 -0
- /package/components/menu/{class.js → menu.class.js} +0 -0
- /package/components/nav/{class.js → nav.class.js} +0 -0
- /package/components/nav-group/{class.js → nav-group.class.js} +0 -0
- /package/components/nav-item/{class.js → nav-item.class.js} +0 -0
- /package/components/noodles/{class.js → noodles.class.js} +0 -0
- /package/components/option-card/{class.js → option-card.class.js} +0 -0
- /package/components/otp-input/{class.js → otp-input.class.js} +0 -0
- /package/components/page/{class.js → page.class.js} +0 -0
- /package/components/pagination/{class.js → pagination.class.js} +0 -0
- /package/components/pane/{class.js → pane.class.js} +0 -0
- /package/components/pipeline-status/{class.js → pipeline-status.class.js} +0 -0
- /package/components/popover/{class.js → popover.class.js} +0 -0
- /package/components/progress/{class.js → progress.class.js} +0 -0
- /package/components/progress-row/{class.js → progress-row.class.js} +0 -0
- /package/components/radio/{class.js → radio.class.js} +0 -0
- /package/components/range/{class.js → range.class.js} +0 -0
- /package/components/rating/{class.js → rating.class.js} +0 -0
- /package/components/richtext/{class.js → richtext.class.js} +0 -0
- /package/components/row/{class.js → row.class.js} +0 -0
- /package/components/segment/{class.js → segment.class.js} +0 -0
- /package/components/segmented/{class.js → segmented.class.js} +0 -0
- /package/components/skeleton/{class.js → skeleton.class.js} +0 -0
- /package/components/slider/{class.js → slider.class.js} +0 -0
- /package/components/stack/{class.js → stack.class.js} +0 -0
- /package/components/step-progress/{class.js → step-progress.class.js} +0 -0
- /package/components/stepper/{class.js → stepper.class.js} +0 -0
- /package/components/stream/{class.js → stream.class.js} +0 -0
- /package/components/swatch/{class.js → swatch.class.js} +0 -0
- /package/components/swiper/{class.js → swiper.class.js} +0 -0
- /package/components/switch/{class.js → switch.class.js} +0 -0
- /package/components/table/{class.js → table.class.js} +0 -0
- /package/components/tabs/{class.js → tabs.class.js} +0 -0
- /package/components/text/{class.js → text.class.js} +0 -0
- /package/components/textarea/{class.js → textarea.class.js} +0 -0
- /package/components/time-picker/{class.js → time-picker.class.js} +0 -0
- /package/components/toast/{class.js → toast.class.js} +0 -0
- /package/components/toggle-group/{class.js → toggle-group.class.js} +0 -0
- /package/components/toggle-scheme/{class.js → toggle-scheme.class.js} +0 -0
- /package/components/toolbar/{class.js → toolbar.class.js} +0 -0
- /package/components/tooltip/{class.js → tooltip.class.js} +0 -0
- /package/components/tree/{class.js → tree.class.js} +0 -0
- /package/components/upload/{class.js → upload.class.js} +0 -0
|
@@ -50,9 +50,16 @@ export class UISpinner extends UIElement {
|
|
|
50
50
|
label: { type: String, default: 'Loading', reflect: false },
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
53
|
+
// Arc / ring / knight variants are pure ::before paint — no children.
|
|
54
|
+
// Dots variant stamps three <span data-spinner-dot=N> children in
|
|
55
|
+
// #syncDots() so each dot can carry an independent animation-delay.
|
|
56
|
+
// Pre-fix: ::before painted dot1, ::after painted dot3, and a
|
|
57
|
+
// box-shadow on ::before painted the middle dot. The pseudo-element
|
|
58
|
+
// approach broke spacing (the box-shadow dot doesn't participate in
|
|
59
|
+
// flex-gap math; the middle dot can't animate; the outer dots picked
|
|
60
|
+
// up scale from keyframes but the middle stayed static). Three real
|
|
61
|
+
// children let flex-gap distribute the row evenly AND give each dot
|
|
62
|
+
// its own animation phase.
|
|
56
63
|
static template = () => null;
|
|
57
64
|
|
|
58
65
|
connected() {
|
|
@@ -60,10 +67,33 @@ export class UISpinner extends UIElement {
|
|
|
60
67
|
if (!this.hasAttribute('role')) this.setAttribute('role', 'progressbar');
|
|
61
68
|
if (!this.hasAttribute('aria-busy')) this.setAttribute('aria-busy', 'true');
|
|
62
69
|
this.setAttribute('aria-valuetext', this.label || 'Loading');
|
|
70
|
+
this.#syncDots();
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
render() {
|
|
66
74
|
// Keep aria-valuetext in sync if `label` changes after connect.
|
|
67
75
|
this.setAttribute('aria-valuetext', this.label || 'Loading');
|
|
76
|
+
this.#syncDots();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#syncDots() {
|
|
80
|
+
const isDots = this.variant === 'dots';
|
|
81
|
+
const existing = this.querySelectorAll(':scope > [data-spinner-dot]');
|
|
82
|
+
if (isDots) {
|
|
83
|
+
if (existing.length === 3) return; // already stamped
|
|
84
|
+
// Wipe any stale dots from a previous variant + stamp fresh.
|
|
85
|
+
existing.forEach((n) => n.remove());
|
|
86
|
+
const frag = document.createDocumentFragment();
|
|
87
|
+
for (let i = 1; i <= 3; i++) {
|
|
88
|
+
const span = document.createElement('span');
|
|
89
|
+
span.setAttribute('data-spinner-dot', String(i));
|
|
90
|
+
span.setAttribute('aria-hidden', 'true');
|
|
91
|
+
frag.appendChild(span);
|
|
92
|
+
}
|
|
93
|
+
this.appendChild(frag);
|
|
94
|
+
} else if (existing.length) {
|
|
95
|
+
// Variant changed away from dots — drop the stamped children.
|
|
96
|
+
existing.forEach((n) => n.remove());
|
|
97
|
+
}
|
|
68
98
|
}
|
|
69
99
|
}
|
|
@@ -8,10 +8,23 @@
|
|
|
8
8
|
--spinner-size-default: 1rem; /* icon-ui md */
|
|
9
9
|
--spinner-color-default: currentColor;
|
|
10
10
|
--spinner-stroke-default: 2px;
|
|
11
|
-
|
|
11
|
+
/* Rotational cadence — interaction-duration tokens (`--a-duration-*`,
|
|
12
|
+
120-300 ms) are tuned for hover/focus transitions; a full spinner
|
|
13
|
+
revolution at 300 ms reads as a frantic blur. Canonical loader
|
|
14
|
+
cadence is ~0.8 s per revolution (smooth, perceptible motion). */
|
|
15
|
+
--spinner-duration-default: 0.8s;
|
|
12
16
|
--spinner-track-opacity-default: 0.25;
|
|
13
17
|
--spinner-dot-size-default: calc(var(--spinner-size, var(--spinner-size-default)) / 4);
|
|
14
18
|
--spinner-dot-gap-default: calc(var(--spinner-size, var(--spinner-size-default)) / 8);
|
|
19
|
+
/* Knight-rider variant — horizontal track with a sliding thumb.
|
|
20
|
+
Track width is a separate scale from the round-spinner --spinner-size
|
|
21
|
+
(Knight reads as a bar, not a glyph). Track height defaults to the
|
|
22
|
+
spinner-stroke for visual continuity with arc/ring. Thumb width
|
|
23
|
+
expressed as a 0-1 ratio of the track so the keyframe math is
|
|
24
|
+
single-variable. */
|
|
25
|
+
--spinner-bar-track-width-default: 4rem;
|
|
26
|
+
--spinner-bar-track-height-default: var(--spinner-stroke, var(--spinner-stroke-default));
|
|
27
|
+
--spinner-bar-thumb-ratio-default: 0.3;
|
|
15
28
|
}
|
|
16
29
|
|
|
17
30
|
/* ── Block 2 — BASE ────────────────────────────────────────────── */
|
|
@@ -65,20 +78,17 @@
|
|
|
65
78
|
}
|
|
66
79
|
|
|
67
80
|
/* ── Variant: DOTS — three bouncing dots ─────────────────────────
|
|
68
|
-
|
|
69
|
-
children
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
shape is to overlay three identical dot pseudos via a flexbox
|
|
73
|
-
container of pseudo + two child pseudos isn't possible without
|
|
74
|
-
a stamped child. So we use a single ::before that paints all
|
|
75
|
-
three dots via background gradients + an animation on the
|
|
76
|
-
`--dot-bounce` custom property (animated via @property).
|
|
81
|
+
Layout: inline-flex with three real <span data-spinner-dot=N>
|
|
82
|
+
children stamped by spinner.class.js #syncDots(). flex-gap distributes
|
|
83
|
+
the row evenly; each child carries its own animation-delay so
|
|
84
|
+
the bounce reads as a left-to-right wave.
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
Why three real children (instead of ::before / ::after + a
|
|
87
|
+
middle dot painted via box-shadow): box-shadow paints the
|
|
88
|
+
middle dot but does NOT participate in flex-gap, so the box-
|
|
89
|
+
shadow dot and the right pseudo had asymmetric spacing. The
|
|
90
|
+
middle dot also couldn't carry its own @keyframes animation
|
|
91
|
+
(box-shadow can't animate per-stop). Stamped children fix both. */
|
|
82
92
|
:scope[variant="dots"] {
|
|
83
93
|
display: inline-flex;
|
|
84
94
|
align-items: center;
|
|
@@ -88,35 +98,61 @@
|
|
|
88
98
|
gap: var(--spinner-dot-gap, var(--spinner-dot-gap-default));
|
|
89
99
|
}
|
|
90
100
|
|
|
91
|
-
:scope[variant="dots"]
|
|
92
|
-
:scope[variant="dots"]::after {
|
|
93
|
-
content: "";
|
|
94
|
-
display: block;
|
|
101
|
+
:scope[variant="dots"] > [data-spinner-dot] {
|
|
95
102
|
width: var(--spinner-dot-size, var(--spinner-dot-size-default));
|
|
96
103
|
height: var(--spinner-dot-size, var(--spinner-dot-size-default));
|
|
97
104
|
border-radius: 50%;
|
|
98
105
|
background: currentColor;
|
|
99
106
|
animation: spinner-ui-bounce var(--spinner-duration, var(--spinner-duration-default)) ease-in-out infinite;
|
|
100
107
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
animation-delay: 0s;
|
|
108
|
+
/* Stagger each dot so the row reads as a wave left → right.
|
|
109
|
+
Three equal slices of one revolution (0, T/3, 2T/3) give the
|
|
110
|
+
classic three-dot loading rhythm. */
|
|
111
|
+
:scope[variant="dots"] > [data-spinner-dot="1"] { animation-delay: 0s; }
|
|
112
|
+
:scope[variant="dots"] > [data-spinner-dot="2"] {
|
|
113
|
+
animation-delay: calc(var(--spinner-duration, var(--spinner-duration-default)) / 3);
|
|
114
|
+
}
|
|
115
|
+
:scope[variant="dots"] > [data-spinner-dot="3"] {
|
|
116
|
+
animation-delay: calc(var(--spinner-duration, var(--spinner-duration-default)) * 2 / 3);
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
:
|
|
114
|
-
|
|
119
|
+
/* ── Variant: KNIGHT — knight-rider sliding bar ──────────────────
|
|
120
|
+
Horizontal track with a thumb sliding back-and-forth via
|
|
121
|
+
`animation-direction: alternate`. Thumb width is a 0–1 ratio of
|
|
122
|
+
the track so the keyframe math reduces to translateX(((1/ratio) - 1) * 100%)
|
|
123
|
+
of the THUMB's own width — i.e. travel = (track - thumb) px,
|
|
124
|
+
expressed in thumb-relative percentages so it scales with any
|
|
125
|
+
track width without a calc that touches both axes. Default
|
|
126
|
+
ratio 0.3 → translate end = 233.33% (of thumb width). */
|
|
127
|
+
:scope[variant="knight"] {
|
|
128
|
+
display: inline-block;
|
|
129
|
+
width: var(--spinner-bar-track-width, var(--spinner-bar-track-width-default));
|
|
130
|
+
height: var(--spinner-bar-track-height, var(--spinner-bar-track-height-default));
|
|
131
|
+
background: color-mix(
|
|
132
|
+
in oklch,
|
|
133
|
+
currentColor calc(var(--spinner-track-opacity, var(--spinner-track-opacity-default)) * 100%),
|
|
134
|
+
transparent
|
|
135
|
+
);
|
|
136
|
+
border-radius: 9999px;
|
|
137
|
+
position: relative;
|
|
138
|
+
overflow: hidden;
|
|
139
|
+
}
|
|
140
|
+
:scope[variant="knight"]::before {
|
|
141
|
+
content: "";
|
|
142
|
+
position: absolute;
|
|
143
|
+
inset: 0 auto 0 0; /* top:0; right:auto; bottom:0; left:0 */
|
|
144
|
+
width: calc(var(--spinner-bar-thumb-ratio, var(--spinner-bar-thumb-ratio-default)) * 100%);
|
|
145
|
+
background: currentColor;
|
|
146
|
+
border-radius: inherit;
|
|
147
|
+
animation: spinner-ui-knight
|
|
148
|
+
var(--spinner-duration, var(--spinner-duration-default))
|
|
149
|
+
ease-in-out infinite alternate;
|
|
115
150
|
}
|
|
116
151
|
|
|
117
152
|
/* ── Paused state — freeze in place ────────────────────────────── */
|
|
118
153
|
:scope[paused]::before,
|
|
119
|
-
:scope[paused]::after
|
|
154
|
+
:scope[paused]::after,
|
|
155
|
+
:scope[paused] > [data-spinner-dot] {
|
|
120
156
|
animation-play-state: paused;
|
|
121
157
|
}
|
|
122
158
|
|
|
@@ -126,7 +162,8 @@
|
|
|
126
162
|
JS lifecycle. */
|
|
127
163
|
@media (prefers-reduced-motion: reduce) {
|
|
128
164
|
:scope::before,
|
|
129
|
-
:scope::after
|
|
165
|
+
:scope::after,
|
|
166
|
+
:scope > [data-spinner-dot] {
|
|
130
167
|
animation: none !important;
|
|
131
168
|
}
|
|
132
169
|
:scope::before {
|
|
@@ -145,12 +182,18 @@
|
|
|
145
182
|
text-align: center;
|
|
146
183
|
color: currentColor;
|
|
147
184
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
185
|
+
/* Dots variant — hide all three stamped dots and let the host's
|
|
186
|
+
::before paint the ellipsis fallback. */
|
|
187
|
+
:scope[variant="dots"] > [data-spinner-dot] { display: none; }
|
|
151
188
|
:scope[variant="dots"] {
|
|
152
189
|
width: var(--spinner-size, var(--spinner-size-default)); /* shrink back to a square in reduced mode */
|
|
153
190
|
}
|
|
191
|
+
/* Knight-rider — hide the sliding thumb; the host's ::before
|
|
192
|
+
above repaints as the ellipsis fallback. */
|
|
193
|
+
:scope[variant="knight"] {
|
|
194
|
+
width: var(--spinner-size, var(--spinner-size-default));
|
|
195
|
+
background: transparent;
|
|
196
|
+
}
|
|
154
197
|
}
|
|
155
198
|
|
|
156
199
|
/* ── Keyframes ─────────────────────────────────────────────────── */
|
|
@@ -162,4 +205,17 @@
|
|
|
162
205
|
0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }
|
|
163
206
|
40% { transform: scale(1); opacity: 1; }
|
|
164
207
|
}
|
|
208
|
+
|
|
209
|
+
/* Knight-rider — thumb slides from left edge to (track - thumb)
|
|
210
|
+
and bounces back via `animation-direction: alternate`. The
|
|
211
|
+
translate distance is expressed in thumb-relative percentages:
|
|
212
|
+
translateX(((1 / ratio) - 1) * 100%) of the thumb's own width
|
|
213
|
+
equals (track - thumb) px. At default ratio 0.3 this resolves
|
|
214
|
+
to translateX(233.33%). */
|
|
215
|
+
@keyframes spinner-ui-knight {
|
|
216
|
+
from { transform: translateX(0); }
|
|
217
|
+
to { transform: translateX(
|
|
218
|
+
calc((1 / var(--spinner-bar-thumb-ratio, var(--spinner-bar-thumb-ratio-default)) - 1) * 100%)
|
|
219
|
+
); }
|
|
220
|
+
}
|
|
165
221
|
}
|
|
@@ -21,6 +21,6 @@ export class UISpinner extends UIElement {
|
|
|
21
21
|
size: 'sm' | 'md' | 'lg';
|
|
22
22
|
/** Color tone — `current` inherits parent text color (matches button label), `accent` uses brand accent, `subtle` is muted, `inverse` flips for on-accent surfaces. */
|
|
23
23
|
tone: 'current' | 'accent' | 'subtle' | 'inverse';
|
|
24
|
-
/** Visual flavor — arc (rotating quarter-circle), ring (full ring with one colored segment), dots (three bouncing dots). */
|
|
25
|
-
variant: 'arc' | 'ring' | 'dots';
|
|
24
|
+
/** Visual flavor — `arc` (rotating quarter-circle, the default glyph spinner), `ring` (full ring with one colored segment rotating around it), `dots` (three bouncing dots — animated in a left-to-right wave), `knight` (horizontal "knight-rider" bar — a sliding thumb that bounces back-and-forth across a track; widest variant, reads as a determinate-looking bar but is indeterminate by intent). */
|
|
25
|
+
variant: 'arc' | 'ring' | 'dots' | 'knight';
|
|
26
26
|
}
|
|
@@ -182,16 +182,20 @@ describe('spinner-ui — CSS source contract', () => {
|
|
|
182
182
|
}
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
it('size="sm" / "md" / "lg" all override --spinner-size', () => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
it('size="sm" / "md" / "lg" all override --spinner-size-default', () => {
|
|
186
|
+
// The two-token convention (--{prop}-default for defaults +
|
|
187
|
+
// var(--{prop}, var(--{prop}-default)) at use sites) means size
|
|
188
|
+
// variants flip the -default token; consumer overrides write to
|
|
189
|
+
// the bare --{prop} which wins via the var() fallback chain.
|
|
190
|
+
expect(SPINNER_CSS).toMatch(/:scope\[size="sm"\][^}]*--spinner-size-default:\s*0\.875rem/);
|
|
191
|
+
expect(SPINNER_CSS).toMatch(/:scope\[size="md"\][^}]*--spinner-size-default:\s*1rem/);
|
|
192
|
+
expect(SPINNER_CSS).toMatch(/:scope\[size="lg"\][^}]*--spinner-size-default:\s*1\.25rem/);
|
|
189
193
|
});
|
|
190
194
|
|
|
191
|
-
it('tone="subtle" / "accent" / "inverse" override --spinner-color via semantic tokens', () => {
|
|
192
|
-
expect(SPINNER_CSS).toMatch(/:scope\[tone="subtle"\][^}]*--spinner-color:\s*var\(--a-fg-subtle\)/);
|
|
193
|
-
expect(SPINNER_CSS).toMatch(/:scope\[tone="accent"\][^}]*--spinner-color:\s*var\(--a-accent-strong\)/);
|
|
194
|
-
expect(SPINNER_CSS).toMatch(/:scope\[tone="inverse"\][^}]*--spinner-color:\s*var\(--a-chrome-light\)/);
|
|
195
|
+
it('tone="subtle" / "accent" / "inverse" override --spinner-color-default via semantic tokens', () => {
|
|
196
|
+
expect(SPINNER_CSS).toMatch(/:scope\[tone="subtle"\][^}]*--spinner-color-default:\s*var\(--a-fg-subtle\)/);
|
|
197
|
+
expect(SPINNER_CSS).toMatch(/:scope\[tone="accent"\][^}]*--spinner-color-default:\s*var\(--a-accent-strong\)/);
|
|
198
|
+
expect(SPINNER_CSS).toMatch(/:scope\[tone="inverse"\][^}]*--spinner-color-default:\s*var\(--a-chrome-light\)/);
|
|
195
199
|
});
|
|
196
200
|
|
|
197
201
|
it('arc variant uses a rotating quarter-circle border on ::before', () => {
|
|
@@ -206,12 +210,46 @@ describe('spinner-ui — CSS source contract', () => {
|
|
|
206
210
|
expect(SPINNER_CSS).toMatch(/border-top-color:\s*currentColor/);
|
|
207
211
|
});
|
|
208
212
|
|
|
209
|
-
it('dots variant uses
|
|
210
|
-
|
|
211
|
-
|
|
213
|
+
it('dots variant uses 3 stamped [data-spinner-dot] children with bounce keyframes', () => {
|
|
214
|
+
// Pre-fix: ::before painted dot1 + a box-shadow middle dot, ::after
|
|
215
|
+
// painted dot3. Spacing was uneven (box-shadow doesn't participate
|
|
216
|
+
// in flex-gap math) and the middle dot couldn't animate. Post-fix
|
|
217
|
+
// (spinner.class.js #syncDots): three real <span data-spinner-dot=N>
|
|
218
|
+
// children stamped on connect; flex-gap distributes the row evenly
|
|
219
|
+
// and each child carries an independent animation-delay so the
|
|
220
|
+
// bounce reads as a left-to-right wave.
|
|
221
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="dots"\]\s*>\s*\[data-spinner-dot\]/);
|
|
222
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="dots"\]\s*>\s*\[data-spinner-dot="1"\]/);
|
|
223
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="dots"\]\s*>\s*\[data-spinner-dot="2"\]/);
|
|
224
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="dots"\]\s*>\s*\[data-spinner-dot="3"\]/);
|
|
212
225
|
expect(SPINNER_CSS).toMatch(/animation:\s*spinner-ui-bounce/);
|
|
213
226
|
});
|
|
214
227
|
|
|
228
|
+
it('knight variant uses a sliding ::before thumb with knight keyframes', () => {
|
|
229
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="knight"\]\s*\{/);
|
|
230
|
+
expect(SPINNER_CSS).toMatch(/:scope\[variant="knight"\]::before/);
|
|
231
|
+
expect(SPINNER_CSS).toMatch(/animation:\s*spinner-ui-knight/);
|
|
232
|
+
// Keyframe math: translateX((1/ratio - 1) * 100%) sweeps the thumb
|
|
233
|
+
// from x=0 to x=(track - thumb) px, expressed in thumb-relative %.
|
|
234
|
+
expect(SPINNER_CSS).toMatch(/@keyframes\s+spinner-ui-knight/);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('knight stamps NO data-spinner-dot children (pseudo-element paint only)', async () => {
|
|
238
|
+
const k = mount('<spinner-ui variant="knight"></spinner-ui>');
|
|
239
|
+
await tick();
|
|
240
|
+
expect(k.querySelectorAll(':scope > [data-spinner-dot]').length).toBe(0);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('dots stamps exactly 3 data-spinner-dot children on connect', async () => {
|
|
244
|
+
const d = mount('<spinner-ui variant="dots"></spinner-ui>');
|
|
245
|
+
await tick();
|
|
246
|
+
const dots = d.querySelectorAll(':scope > [data-spinner-dot]');
|
|
247
|
+
expect(dots.length).toBe(3);
|
|
248
|
+
expect(dots[0].getAttribute('data-spinner-dot')).toBe('1');
|
|
249
|
+
expect(dots[1].getAttribute('data-spinner-dot')).toBe('2');
|
|
250
|
+
expect(dots[2].getAttribute('data-spinner-dot')).toBe('3');
|
|
251
|
+
});
|
|
252
|
+
|
|
215
253
|
it('paused state freezes the animation via animation-play-state', () => {
|
|
216
254
|
expect(SPINNER_CSS).toMatch(/:scope\[paused\][^}]*animation-play-state:\s*paused/);
|
|
217
255
|
});
|
|
@@ -26,13 +26,21 @@ props:
|
|
|
26
26
|
- lg
|
|
27
27
|
reflect: true
|
|
28
28
|
variant:
|
|
29
|
-
description:
|
|
29
|
+
description: >-
|
|
30
|
+
Visual flavor —
|
|
31
|
+
`arc` (rotating quarter-circle, the default glyph spinner),
|
|
32
|
+
`ring` (full ring with one colored segment rotating around it),
|
|
33
|
+
`dots` (three bouncing dots — animated in a left-to-right wave),
|
|
34
|
+
`knight` (horizontal "knight-rider" bar — a sliding thumb that
|
|
35
|
+
bounces back-and-forth across a track; widest variant, reads as
|
|
36
|
+
a determinate-looking bar but is indeterminate by intent).
|
|
30
37
|
type: string
|
|
31
38
|
default: arc
|
|
32
39
|
enum:
|
|
33
40
|
- arc
|
|
34
41
|
- ring
|
|
35
42
|
- dots
|
|
43
|
+
- knight
|
|
36
44
|
reflect: true
|
|
37
45
|
tone:
|
|
38
46
|
description: Color tone — `current` inherits parent text color (matches button label), `accent` uses brand accent, `subtle` is muted, `inverse` flips for on-accent surfaces.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
2
|
#
|
|
3
3
|
# §228 (v0.5.9): authored to close the §229 baseline class-export-undeclared
|
|
4
|
-
# drift for UIStepperItem. Ships as a sibling class in stepper/class.js
|
|
4
|
+
# drift for UIStepperItem. Ships as a sibling class in stepper/stepper.class.js
|
|
5
5
|
# + is registered alongside UIStepper.
|
|
6
6
|
|
|
7
7
|
# Child component of <stepper-ui>. Surface only inside that parent.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { defineIfFree } from '../../core/register.js';
|
|
13
|
-
import { UIStepper, UIStepperItem } from './class.js';
|
|
13
|
+
import { UIStepper, UIStepperItem } from './stepper.class.js';
|
|
14
14
|
|
|
15
15
|
defineIfFree('stepper-ui', UIStepper);
|
|
16
16
|
defineIfFree('stepper-item-ui', UIStepperItem);
|
|
@@ -433,7 +433,7 @@
|
|
|
433
433
|
|
|
434
434
|
/* ═══════ Loading (skeleton rows) ═══════
|
|
435
435
|
Skeleton rows replace real rows while [loading] is set on the host
|
|
436
|
-
(see class.js #renderOverlays). Each row is a [data-skeleton-row]
|
|
436
|
+
(see table.class.js #renderOverlays). Each row is a [data-skeleton-row]
|
|
437
437
|
containing <skeleton-ui> cells. Inherit body-row layout so column
|
|
438
438
|
widths track the header, then suppress hover/striping/click states
|
|
439
439
|
(no real data to interact with). */
|
|
@@ -124,7 +124,7 @@ export class UITableToolbar extends UIElement {
|
|
|
124
124
|
variant: { type: String, default: 'default', reflect: true },
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
// §205 (v0.5.7): dynamic sort-indicator icons (class.js:576 — nested ternary
|
|
127
|
+
// §205 (v0.5.7): dynamic sort-indicator icons (table-toolbar.class.js:576 — nested ternary
|
|
128
128
|
// `dir === 'asc' ? 'arrow-up' : dir === 'desc' ? 'arrow-down' : 'caret-up-down'`).
|
|
129
129
|
// Per FEEDBACK-16 §1 + §209 slot-11 ternary-walker discovery.
|
|
130
130
|
static requiredIcons = ['arrow-up', 'arrow-down', 'caret-up-down'];
|
|
@@ -290,6 +290,7 @@ export class UITableToolbar extends UIElement {
|
|
|
290
290
|
// name renders as literal text before the icon registry resolves.
|
|
291
291
|
const search = document.createElement('search-ui');
|
|
292
292
|
search.setAttribute('data-search', '');
|
|
293
|
+
search.setAttribute('size', 'sm'); // match toolbar buttons + badge + filter chips
|
|
293
294
|
search.setAttribute('placeholder', this.placeholder);
|
|
294
295
|
search.setAttribute('debounce', String(SEARCH_DEBOUNCE));
|
|
295
296
|
search.addEventListener('search', this.#onSearch);
|
package/components/tabs/tab.yaml
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
2
|
#
|
|
3
3
|
# §176 (v0.5.5): authored to close the §175 baseline-orphan class. The
|
|
4
|
-
# component already existed as a sibling class in the parent's class.js
|
|
4
|
+
# component already existed as a sibling class in the parent's tabs.class.js
|
|
5
5
|
# + was registered alongside the parent (e.g. UIList + UIListItem both
|
|
6
|
-
# from list/class.js). The catalog just lacked its own entry. With the
|
|
6
|
+
# from list/list.class.js). The catalog just lacked its own entry. With the
|
|
7
7
|
# §172 sibling-yaml scanner, this file gets picked up next to the parent
|
|
8
8
|
# yaml.
|
|
9
9
|
|
package/components/tabs/tabs.js
CHANGED
|
@@ -44,6 +44,15 @@
|
|
|
44
44
|
"description": "Tag label. Renderer routes this to the `text` attribute, rendered via CSS attr(text) on ::after.",
|
|
45
45
|
"$ref": "common_types.json#/$defs/DynamicString"
|
|
46
46
|
},
|
|
47
|
+
"tone": {
|
|
48
|
+
"description": "Fill style — orthogonal to [variant]. Default (`solid`) for family\nvariants is a saturated bg with on-strong (near-white) text — the\nchip IS the state. Opt-out via `tone=\"muted\"` for a tinted bg with\nscheme-paired text (matches <badge-ui>'s default look) when the\nchip is metadata in a dense list rather than a status stamp. The\n`default` variant stays quiet chrome regardless of tone unless\n`tone=\"solid\"` is set explicitly (high-contrast neutral inverse).\n",
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": [
|
|
51
|
+
"solid",
|
|
52
|
+
"muted"
|
|
53
|
+
],
|
|
54
|
+
"default": "solid"
|
|
55
|
+
},
|
|
47
56
|
"variant": {
|
|
48
57
|
"description": "Semantic variant — `default | info | success | warning | danger`.",
|
|
49
58
|
"type": "string",
|
|
@@ -42,13 +42,20 @@ export class UITag extends UIElement {
|
|
|
42
42
|
// `tag.textContent = …` working natively; the prop declaration
|
|
43
43
|
// broke that path. v0.5.x §327.
|
|
44
44
|
variant: { type: String, default: 'default', reflect: true },
|
|
45
|
+
// `tone` is read-only via attribute selectors (CSS), not by the
|
|
46
|
+
// class — declared in yaml for documentation + a2ui hint but NOT
|
|
47
|
+
// in `static properties` so the runtime doesn't reflect an
|
|
48
|
+
// ever-present `tone="solid"` attribute onto every <tag-ui>
|
|
49
|
+
// (which would defeat the variant-default cascade and force CSS
|
|
50
|
+
// selectors to compete with reflected defaults). Author sets
|
|
51
|
+
// `[tone]` directly when opting in.
|
|
45
52
|
size: { type: String, default: 'md', reflect: true },
|
|
46
53
|
removable: { type: Boolean, default: false, reflect: true },
|
|
47
54
|
disabled: { type: Boolean, default: false, reflect: true },
|
|
48
55
|
};
|
|
49
56
|
|
|
50
57
|
static parts = {
|
|
51
|
-
dismiss: '<button slot="dismiss" type="button" aria-label="Remove"><icon-ui name="x"></icon-ui></button>',
|
|
58
|
+
dismiss: '<button slot="dismiss" type="button" aria-label="Remove"><icon-ui name="x" weight="bold"></icon-ui></button>',
|
|
52
59
|
};
|
|
53
60
|
|
|
54
61
|
static template = () => null;
|