@adia-ai/web-components 0.6.34 → 0.6.35
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/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.js +1 -1
- package/components/command/command.js +1 -1
- package/components/date-range-picker/{class.js → date-range-picker.class.js} +18 -2
- package/components/date-range-picker/date-range-picker.css +51 -5
- 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.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 +1 -1
- package/components/input/input.js +1 -1
- 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/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} +1 -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.js +1 -1
- package/components/tags-input/tags-input.a2ui.json +337 -0
- package/components/tags-input/tags-input.class.js +776 -0
- package/components/tags-input/tags-input.css +201 -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.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/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +111 -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/search/{class.js → search.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/tag/{class.js → tag.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
|
@@ -182,6 +182,74 @@
|
|
|
182
182
|
:scope[variant="ghost"] > [slot="trigger"]:hover > [slot="caret"] {
|
|
183
183
|
color: var(--select-fg-subtle, var(--select-fg-subtle-default));
|
|
184
184
|
}
|
|
185
|
+
|
|
186
|
+
/* ── SPEC-040 — Multi-select chip trigger ──
|
|
187
|
+
[data-multi-chips] is set on the host by render() when [multiple] is
|
|
188
|
+
active. Layout switches from inline-text trigger to wrap-flex chip row.
|
|
189
|
+
Tag-ui chips inside [data-chips] inherit the host's tag-ui token set;
|
|
190
|
+
the +more pill is a CSS-only button styled to match. */
|
|
191
|
+
:scope[data-multi-chips] > [slot="trigger"] {
|
|
192
|
+
flex-wrap: wrap;
|
|
193
|
+
align-items: center;
|
|
194
|
+
gap: var(--a-space-1);
|
|
195
|
+
/* min-height tracks single-row height when empty; flex-wrap allows
|
|
196
|
+
it to grow as chips overflow. */
|
|
197
|
+
padding-block: calc(var(--select-py, var(--a-space-1)));
|
|
198
|
+
}
|
|
199
|
+
:scope[data-multi-chips] [data-chips] {
|
|
200
|
+
display: contents; /* let chips participate in the trigger's flex line */
|
|
201
|
+
}
|
|
202
|
+
:scope[data-multi-chips] [data-chips] tag-ui {
|
|
203
|
+
/* Chip styling tracks the active variant via tag-ui's own tokens. */
|
|
204
|
+
--tag-size-default: var(--a-ui-tiny);
|
|
205
|
+
}
|
|
206
|
+
:scope[data-multi-chips] [data-chips] [data-more] {
|
|
207
|
+
appearance: none;
|
|
208
|
+
border: 1px solid var(--select-border, var(--select-border-default));
|
|
209
|
+
background: var(--select-bg-hover, var(--select-bg-hover-default));
|
|
210
|
+
color: var(--select-fg-muted, var(--select-fg-muted-default));
|
|
211
|
+
border-radius: var(--a-radius-full);
|
|
212
|
+
padding: 0 var(--a-space-2);
|
|
213
|
+
font: inherit;
|
|
214
|
+
font-size: var(--a-ui-tiny);
|
|
215
|
+
line-height: calc(var(--a-size) - var(--a-space-3));
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
}
|
|
218
|
+
:scope[data-multi-chips] [data-chips] [data-more]:hover {
|
|
219
|
+
background: var(--a-bg-hover);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* Clear-all `x` affordance. Visible only when [clearable] AND chips. */
|
|
223
|
+
:scope[data-multi-chips] [data-clear-all] {
|
|
224
|
+
appearance: none;
|
|
225
|
+
background: transparent;
|
|
226
|
+
border: none;
|
|
227
|
+
padding: var(--a-space-0);
|
|
228
|
+
margin-inline-start: var(--a-space-1);
|
|
229
|
+
color: var(--select-fg-muted, var(--select-fg-muted-default));
|
|
230
|
+
cursor: pointer;
|
|
231
|
+
border-radius: var(--a-radius-full);
|
|
232
|
+
--a-icon-size: var(--a-ui-sm);
|
|
233
|
+
display: inline-flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
}
|
|
236
|
+
:scope[data-multi-chips] [data-clear-all][hidden] { display: none; }
|
|
237
|
+
:scope[data-multi-chips] [data-clear-all]:hover {
|
|
238
|
+
color: var(--select-fg, var(--select-fg-default));
|
|
239
|
+
background: var(--a-bg-hover);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* In multi-select with chips present, the trigger display element is
|
|
243
|
+
the rest-of-row slot — make it flex-grow but not push chips off. */
|
|
244
|
+
:scope[data-multi-chips] [slot="display"] {
|
|
245
|
+
flex: 1;
|
|
246
|
+
min-width: 4ch;
|
|
247
|
+
}
|
|
248
|
+
/* Hide the display when empty in multi-mode (chips fill the slot). */
|
|
249
|
+
:scope[data-multi-chips] [slot="display"]:empty {
|
|
250
|
+
flex: 0 0 0;
|
|
251
|
+
padding: 0;
|
|
252
|
+
}
|
|
185
253
|
}
|
|
186
254
|
|
|
187
255
|
/* ── Top-layer: cannot inherit component tokens ── */
|
|
@@ -320,3 +388,93 @@ select-ui > [slot="hint"] {
|
|
|
320
388
|
color: var(--select-hint-fg, var(--select-fg-muted, var(--select-fg-muted-default)));
|
|
321
389
|
line-height: var(--select-hint-lh, 1.4);
|
|
322
390
|
}
|
|
391
|
+
|
|
392
|
+
/* ── SPEC-040 — Multi-select popover affordances ──
|
|
393
|
+
Top-layer: popover lives outside @scope so reference --a-* directly. */
|
|
394
|
+
|
|
395
|
+
/* Select-all / Clear control row above the option list. */
|
|
396
|
+
select-ui [slot="listbox"] [data-select-all] {
|
|
397
|
+
display: flex;
|
|
398
|
+
align-items: center;
|
|
399
|
+
justify-content: flex-end;
|
|
400
|
+
padding: var(--a-space-1);
|
|
401
|
+
border-bottom: 1px solid var(--a-border-subtle);
|
|
402
|
+
margin-bottom: var(--a-space-1);
|
|
403
|
+
}
|
|
404
|
+
select-ui [slot="listbox"] [data-select-all-btn] {
|
|
405
|
+
appearance: none;
|
|
406
|
+
background: transparent;
|
|
407
|
+
border: none;
|
|
408
|
+
font: inherit;
|
|
409
|
+
font-size: var(--a-ui-xs);
|
|
410
|
+
color: var(--a-accent);
|
|
411
|
+
cursor: pointer;
|
|
412
|
+
padding: var(--a-space-1) var(--a-space-2);
|
|
413
|
+
border-radius: var(--a-radius-sm);
|
|
414
|
+
}
|
|
415
|
+
select-ui [slot="listbox"] [data-select-all-btn]:hover {
|
|
416
|
+
background: var(--a-bg-hover);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/* Multi-select option rows — leading checkbox indicator + label.
|
|
420
|
+
The check icon is hidden by default and revealed at aria-selected. */
|
|
421
|
+
select-ui [role="option"][data-multi-option] {
|
|
422
|
+
display: flex;
|
|
423
|
+
align-items: center;
|
|
424
|
+
gap: var(--a-space-2);
|
|
425
|
+
}
|
|
426
|
+
select-ui [role="option"][data-multi-option] [data-checkbox] {
|
|
427
|
+
flex-shrink: 0;
|
|
428
|
+
display: inline-flex;
|
|
429
|
+
align-items: center;
|
|
430
|
+
justify-content: center;
|
|
431
|
+
width: 1rem;
|
|
432
|
+
height: 1rem;
|
|
433
|
+
border: 1px solid var(--a-ui-border);
|
|
434
|
+
border-radius: var(--a-radius-sm);
|
|
435
|
+
background: var(--a-canvas-bright);
|
|
436
|
+
margin-inline-end: 0; /* row gap already provides spacing */
|
|
437
|
+
transition:
|
|
438
|
+
background var(--a-duration-fast) var(--a-easing),
|
|
439
|
+
border-color var(--a-duration-fast) var(--a-easing);
|
|
440
|
+
}
|
|
441
|
+
/* Hide the check icon when unselected — overrides the option-row icon-ui
|
|
442
|
+
rule above. */
|
|
443
|
+
select-ui [role="option"][data-multi-option] [data-checkbox] icon-ui {
|
|
444
|
+
--a-icon-size: 0.75rem;
|
|
445
|
+
color: transparent;
|
|
446
|
+
margin: 0;
|
|
447
|
+
vertical-align: 0;
|
|
448
|
+
transition: color var(--a-duration-fast) var(--a-easing);
|
|
449
|
+
}
|
|
450
|
+
select-ui [role="option"][data-multi-option][aria-selected="true"] [data-checkbox] {
|
|
451
|
+
background: var(--a-accent);
|
|
452
|
+
border-color: var(--a-accent);
|
|
453
|
+
}
|
|
454
|
+
select-ui [role="option"][data-multi-option][aria-selected="true"] [data-checkbox] icon-ui {
|
|
455
|
+
color: var(--a-chrome-light);
|
|
456
|
+
}
|
|
457
|
+
select-ui [role="option"][data-multi-option] [data-option-label] {
|
|
458
|
+
flex: 1;
|
|
459
|
+
min-width: 0;
|
|
460
|
+
}
|
|
461
|
+
/* Multi-option selected state — override the single-select "bold +
|
|
462
|
+
accent bg" treatment so the row stays light + the checkbox carries
|
|
463
|
+
the selected signal. */
|
|
464
|
+
select-ui [role="option"][data-multi-option][aria-selected="true"] {
|
|
465
|
+
background: transparent;
|
|
466
|
+
font-weight: inherit;
|
|
467
|
+
color: var(--select-fg, var(--select-fg-default));
|
|
468
|
+
}
|
|
469
|
+
select-ui [role="option"][data-multi-option][aria-selected="true"]:hover,
|
|
470
|
+
select-ui [role="option"][data-multi-option][aria-selected="true"][data-focused] {
|
|
471
|
+
background: var(--select-option-bg-hover, var(--select-option-bg-hover-default));
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/* Empty state when there are no options. */
|
|
475
|
+
select-ui [slot="listbox"] [data-empty] {
|
|
476
|
+
padding: var(--a-space-3) var(--a-ui-px);
|
|
477
|
+
color: var(--a-fg-muted);
|
|
478
|
+
text-align: center;
|
|
479
|
+
font-size: var(--a-ui-xs);
|
|
480
|
+
}
|
|
@@ -17,7 +17,12 @@ export interface SelectOption {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface SelectChangeEventDetail<V extends string = string> {
|
|
20
|
-
value:
|
|
20
|
+
/** Single-select: the new value. Multi-select: array of selected ids. */
|
|
21
|
+
value: V | V[];
|
|
22
|
+
/** Multi-select only: ids added in this change. */
|
|
23
|
+
added?: V[];
|
|
24
|
+
/** Multi-select only: ids removed in this change. */
|
|
25
|
+
removed?: V[];
|
|
21
26
|
}
|
|
22
27
|
export type SelectChangeEvent<V extends string = string> = CustomEvent<SelectChangeEventDetail<V>>;
|
|
23
28
|
|
|
@@ -26,6 +31,13 @@ export interface SelectActionEventDetail {
|
|
|
26
31
|
}
|
|
27
32
|
export type SelectActionEvent = CustomEvent<SelectActionEventDetail>;
|
|
28
33
|
|
|
34
|
+
/** SPEC-040 — fired when [multiple] toggle suppressed by min/max constraints. */
|
|
35
|
+
export interface SelectInvalidEventDetail {
|
|
36
|
+
value: string[];
|
|
37
|
+
reason: 'min' | 'max';
|
|
38
|
+
}
|
|
39
|
+
export type SelectInvalidEvent = CustomEvent<SelectInvalidEventDetail>;
|
|
40
|
+
|
|
29
41
|
export class UISelect extends UIFormElement {
|
|
30
42
|
placeholder: string;
|
|
31
43
|
/** Open/closed reflected attribute — toggled by trigger click / keyboard. */
|
|
@@ -40,6 +52,16 @@ export class UISelect extends UIFormElement {
|
|
|
40
52
|
/** Allow values not in the option list (combobox mode). */
|
|
41
53
|
freeText: boolean;
|
|
42
54
|
divider: boolean;
|
|
55
|
+
/** SPEC-040 — cap visible chips in multi-select trigger. 0 = unlimited. */
|
|
56
|
+
maxChips: number;
|
|
57
|
+
/** SPEC-040 — minimum required selections in multi-select mode. */
|
|
58
|
+
min: number;
|
|
59
|
+
/** SPEC-040 — maximum allowed selections in multi-select mode. 0 = unlimited. */
|
|
60
|
+
max: number;
|
|
61
|
+
/** SPEC-040 — render Select-all / Clear control above the option list. */
|
|
62
|
+
selectAll: boolean;
|
|
63
|
+
/** SPEC-040 — render a clear-all `x` affordance in the trigger. */
|
|
64
|
+
clearable: boolean;
|
|
43
65
|
/** §207 (v0.5.7): hint text below the field, wired to aria-describedby. */
|
|
44
66
|
hint: string;
|
|
45
67
|
/**
|
|
@@ -63,6 +85,13 @@ export class UISelect extends UIFormElement {
|
|
|
63
85
|
*/
|
|
64
86
|
options: readonly SelectOption[];
|
|
65
87
|
|
|
88
|
+
/** SPEC-040 — toggle one option's selection in multi-select mode. */
|
|
89
|
+
toggle(id: string): void;
|
|
90
|
+
/** SPEC-040 — select every non-disabled option in multi-select mode. */
|
|
91
|
+
selectAllOptions(): void;
|
|
92
|
+
/** SPEC-040 — clear all selections. */
|
|
93
|
+
clear(): void;
|
|
94
|
+
|
|
66
95
|
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
67
96
|
type: K,
|
|
68
97
|
listener: (this: UISelect, ev: HTMLElementEventMap[K]) => unknown,
|
|
@@ -70,4 +99,5 @@ export class UISelect extends UIFormElement {
|
|
|
70
99
|
): void;
|
|
71
100
|
addEventListener(type: 'change', listener: (ev: SelectChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
72
101
|
addEventListener(type: 'action', listener: (ev: SelectActionEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
102
|
+
addEventListener(type: 'invalid', listener: (ev: SelectInvalidEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
73
103
|
}
|
|
@@ -86,4 +86,206 @@ describe('select-ui', () => {
|
|
|
86
86
|
|
|
87
87
|
expect(selected).toEqual(['b']);
|
|
88
88
|
});
|
|
89
|
+
|
|
90
|
+
// ── SPEC-040 (multi-select) ──
|
|
91
|
+
|
|
92
|
+
it('multi-select: [multiple] sets data-multi-chips and renders tag-ui chips per selected value', async () => {
|
|
93
|
+
const s = mount(`
|
|
94
|
+
<select-ui multiple value="a,c">
|
|
95
|
+
<option value="a">Alpha</option>
|
|
96
|
+
<option value="b">Beta</option>
|
|
97
|
+
<option value="c">Gamma</option>
|
|
98
|
+
</select-ui>
|
|
99
|
+
`);
|
|
100
|
+
await tick();
|
|
101
|
+
expect(s.hasAttribute('data-multi-chips')).toBe(true);
|
|
102
|
+
const chips = s.querySelectorAll('[slot="trigger"] [data-chips] tag-ui');
|
|
103
|
+
expect(chips.length).toBe(2);
|
|
104
|
+
const chipValues = Array.from(chips).map((c) => c.dataset.chipValue);
|
|
105
|
+
expect(chipValues).toContain('a');
|
|
106
|
+
expect(chipValues).toContain('c');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('multi-select: aria-multiselectable=true is set on the listbox', async () => {
|
|
110
|
+
const s = mount(`
|
|
111
|
+
<select-ui multiple open>
|
|
112
|
+
<option value="a">Alpha</option>
|
|
113
|
+
<option value="b">Beta</option>
|
|
114
|
+
</select-ui>
|
|
115
|
+
`);
|
|
116
|
+
await tick();
|
|
117
|
+
const lb = s.querySelector('[slot="listbox"]');
|
|
118
|
+
expect(lb).toBeTruthy();
|
|
119
|
+
expect(lb.getAttribute('aria-multiselectable')).toBe('true');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('multi-select: clicking an option toggles selection without closing the popover', async () => {
|
|
123
|
+
const s = mount(`
|
|
124
|
+
<select-ui multiple open>
|
|
125
|
+
<option value="a">Alpha</option>
|
|
126
|
+
<option value="b">Beta</option>
|
|
127
|
+
<option value="c">Gamma</option>
|
|
128
|
+
</select-ui>
|
|
129
|
+
`);
|
|
130
|
+
await tick();
|
|
131
|
+
const opts = s.querySelectorAll('[role="option"]');
|
|
132
|
+
const optA = Array.from(opts).find((o) => o.getAttribute('data-value') === 'a');
|
|
133
|
+
optA.click();
|
|
134
|
+
await tick();
|
|
135
|
+
expect(s.open).toBe(true); // still open
|
|
136
|
+
expect(s.value).toBe('a');
|
|
137
|
+
|
|
138
|
+
const optC = Array.from(s.querySelectorAll('[role="option"]')).find((o) => o.getAttribute('data-value') === 'c');
|
|
139
|
+
optC.click();
|
|
140
|
+
await tick();
|
|
141
|
+
expect(s.open).toBe(true);
|
|
142
|
+
const parts = new Set(s.value.split(','));
|
|
143
|
+
expect(parts.has('a')).toBe(true);
|
|
144
|
+
expect(parts.has('c')).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('multi-select: Backspace from the trigger removes the last chip', async () => {
|
|
148
|
+
const s = mount(`
|
|
149
|
+
<select-ui multiple value="a,b">
|
|
150
|
+
<option value="a">Alpha</option>
|
|
151
|
+
<option value="b">Beta</option>
|
|
152
|
+
</select-ui>
|
|
153
|
+
`);
|
|
154
|
+
await tick();
|
|
155
|
+
const ev = new KeyboardEvent('keydown', { key: 'Backspace', bubbles: true });
|
|
156
|
+
s.dispatchEvent(ev);
|
|
157
|
+
await tick();
|
|
158
|
+
expect(s.value).toBe('a');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('multi-select: toggle(id) is a public API', async () => {
|
|
162
|
+
const s = mount(`
|
|
163
|
+
<select-ui multiple>
|
|
164
|
+
<option value="a">Alpha</option>
|
|
165
|
+
<option value="b">Beta</option>
|
|
166
|
+
</select-ui>
|
|
167
|
+
`);
|
|
168
|
+
await tick();
|
|
169
|
+
s.toggle('a');
|
|
170
|
+
await tick();
|
|
171
|
+
expect(s.value).toBe('a');
|
|
172
|
+
s.toggle('a');
|
|
173
|
+
await tick();
|
|
174
|
+
expect(s.value).toBe('');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('multi-select: [max] suppresses further selection and fires invalid', async () => {
|
|
178
|
+
const s = mount(`
|
|
179
|
+
<select-ui multiple max="2" value="a,b">
|
|
180
|
+
<option value="a">Alpha</option>
|
|
181
|
+
<option value="b">Beta</option>
|
|
182
|
+
<option value="c">Gamma</option>
|
|
183
|
+
</select-ui>
|
|
184
|
+
`);
|
|
185
|
+
await tick();
|
|
186
|
+
let invalidFired = null;
|
|
187
|
+
s.addEventListener('invalid', (e) => { invalidFired = e.detail; });
|
|
188
|
+
s.toggle('c');
|
|
189
|
+
await tick();
|
|
190
|
+
expect(invalidFired).toBeTruthy();
|
|
191
|
+
expect(invalidFired.reason).toBe('max');
|
|
192
|
+
expect(s.value).toBe('a,b'); // unchanged
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('multi-select: clear() empties value and fires change with removed array', async () => {
|
|
196
|
+
const s = mount(`
|
|
197
|
+
<select-ui multiple value="a,b">
|
|
198
|
+
<option value="a">Alpha</option>
|
|
199
|
+
<option value="b">Beta</option>
|
|
200
|
+
</select-ui>
|
|
201
|
+
`);
|
|
202
|
+
await tick();
|
|
203
|
+
let changed = null;
|
|
204
|
+
s.addEventListener('change', (e) => { changed = e.detail; });
|
|
205
|
+
s.clear();
|
|
206
|
+
await tick();
|
|
207
|
+
expect(s.value).toBe('');
|
|
208
|
+
expect(changed.removed).toEqual(['a', 'b']);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('multi-select: selectAllOptions() selects every non-disabled option', async () => {
|
|
212
|
+
const s = mount(`
|
|
213
|
+
<select-ui multiple>
|
|
214
|
+
<option value="a">Alpha</option>
|
|
215
|
+
<option value="b">Beta</option>
|
|
216
|
+
<option value="c" disabled>Gamma</option>
|
|
217
|
+
</select-ui>
|
|
218
|
+
`);
|
|
219
|
+
await tick();
|
|
220
|
+
s.selectAllOptions();
|
|
221
|
+
await tick();
|
|
222
|
+
const parts = new Set(s.value.split(','));
|
|
223
|
+
expect(parts.has('a')).toBe(true);
|
|
224
|
+
expect(parts.has('b')).toBe(true);
|
|
225
|
+
expect(parts.has('c')).toBe(false); // disabled
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('multi-select: [max-chips] shows "+N more" pill when exceeded', async () => {
|
|
229
|
+
const s = mount(`
|
|
230
|
+
<select-ui multiple max-chips="2" value="a,b,c,d">
|
|
231
|
+
<option value="a">Alpha</option>
|
|
232
|
+
<option value="b">Beta</option>
|
|
233
|
+
<option value="c">Gamma</option>
|
|
234
|
+
<option value="d">Delta</option>
|
|
235
|
+
</select-ui>
|
|
236
|
+
`);
|
|
237
|
+
await tick();
|
|
238
|
+
const chips = s.querySelectorAll('[slot="trigger"] [data-chips] tag-ui');
|
|
239
|
+
expect(chips.length).toBe(2);
|
|
240
|
+
const more = s.querySelector('[slot="trigger"] [data-more]');
|
|
241
|
+
expect(more).toBeTruthy();
|
|
242
|
+
expect(more.textContent).toBe('+2 more');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('multi-select: [clearable] reveals the clear-all button when chips present', async () => {
|
|
246
|
+
const s = mount(`
|
|
247
|
+
<select-ui multiple clearable value="a">
|
|
248
|
+
<option value="a">Alpha</option>
|
|
249
|
+
<option value="b">Beta</option>
|
|
250
|
+
</select-ui>
|
|
251
|
+
`);
|
|
252
|
+
await tick();
|
|
253
|
+
const clearBtn = s.querySelector('[data-clear-all]');
|
|
254
|
+
expect(clearBtn).toBeTruthy();
|
|
255
|
+
expect(clearBtn.hasAttribute('hidden')).toBe(false);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('multi-select: [select-all] renders the bulk-action header', async () => {
|
|
259
|
+
const s = mount(`
|
|
260
|
+
<select-ui multiple select-all open>
|
|
261
|
+
<option value="a">Alpha</option>
|
|
262
|
+
<option value="b">Beta</option>
|
|
263
|
+
</select-ui>
|
|
264
|
+
`);
|
|
265
|
+
await tick();
|
|
266
|
+
const header = s.querySelector('[slot="listbox"] [data-select-all]');
|
|
267
|
+
expect(header).toBeTruthy();
|
|
268
|
+
const btn = header.querySelector('[data-select-all-btn]');
|
|
269
|
+
expect(btn).toBeTruthy();
|
|
270
|
+
expect(btn.textContent).toBe('Select all');
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('multi-select: chip remove event empties that selection from value', async () => {
|
|
274
|
+
const s = mount(`
|
|
275
|
+
<select-ui multiple value="a,b">
|
|
276
|
+
<option value="a">Alpha</option>
|
|
277
|
+
<option value="b">Beta</option>
|
|
278
|
+
</select-ui>
|
|
279
|
+
`);
|
|
280
|
+
await tick();
|
|
281
|
+
const chipA = s.querySelector('tag-ui[data-chip-value="a"]');
|
|
282
|
+
expect(chipA).toBeTruthy();
|
|
283
|
+
// Simulate tag-ui's remove event (bubbles, with detail.text)
|
|
284
|
+
chipA.dispatchEvent(new CustomEvent('remove', {
|
|
285
|
+
bubbles: true,
|
|
286
|
+
detail: { text: 'Alpha', value: 'Alpha' },
|
|
287
|
+
}));
|
|
288
|
+
await tick();
|
|
289
|
+
expect(s.value).toBe('b');
|
|
290
|
+
});
|
|
89
291
|
});
|
|
@@ -8,17 +8,23 @@ component: Select
|
|
|
8
8
|
category: input
|
|
9
9
|
version: 1
|
|
10
10
|
description: |
|
|
11
|
-
Single-select dropdown primitive — the canonical AdiaUI
|
|
12
|
-
control. Form-bearing via UIFormElement: [name], [value],
|
|
11
|
+
Single- and multi-select dropdown primitive — the canonical AdiaUI
|
|
12
|
+
select control. Form-bearing via UIFormElement: [name], [value],
|
|
13
13
|
[required], [disabled], fires `change`. Options via native
|
|
14
14
|
<option> / <optgroup> children, programmatic `.options` array, or
|
|
15
15
|
JSON [data-options] (hydrated by <editor-shell>'s wireSelects).
|
|
16
16
|
Use for single-select with > 4 options; for ≤ 4 options use
|
|
17
|
-
<segmented-ui> or <radio-ui>. Multi-select via [multiple
|
|
17
|
+
<segmented-ui> or <radio-ui>. Multi-select via [multiple]: trigger
|
|
18
|
+
renders <tag-ui> chips per selection, popover shows checkbox-style
|
|
19
|
+
option list, Backspace removes the last chip, [select-all] adds
|
|
20
|
+
bulk controls, [max-chips] caps the visible chip count with a
|
|
21
|
+
"+N more" pill. Form value stays a comma-separated string under
|
|
22
|
+
[name] for native <form> compatibility (parse with .split(',')).
|
|
18
23
|
# Per ADR-0027 — primitives that programmatically create other primitives
|
|
19
24
|
# do NOT auto-import them. Consumer (or demo shell) must explicitly import.
|
|
20
25
|
composes:
|
|
21
|
-
- icon-ui
|
|
26
|
+
- icon-ui # chevron + option-row affixes (created in render)
|
|
27
|
+
- tag-ui # multi-select chip per selected option in the trigger
|
|
22
28
|
props:
|
|
23
29
|
name:
|
|
24
30
|
description: Form control name for form data submission
|
|
@@ -89,9 +95,56 @@ props:
|
|
|
89
95
|
type: number
|
|
90
96
|
default: null
|
|
91
97
|
multiple:
|
|
92
|
-
description:
|
|
98
|
+
description: |
|
|
99
|
+
Enables multi-select. Trigger renders <tag-ui> chips per selection
|
|
100
|
+
(not comma-separated text); popover renders checkbox-style option
|
|
101
|
+
rows where clicks toggle without closing; Backspace from the
|
|
102
|
+
trigger removes the last chip. Form value remains comma-separated
|
|
103
|
+
under [name] for native <form> compatibility.
|
|
93
104
|
type: boolean
|
|
94
105
|
default: false
|
|
106
|
+
reflect: true
|
|
107
|
+
max-chips:
|
|
108
|
+
description: |
|
|
109
|
+
Multi-select only. Caps the number of chips visible in the
|
|
110
|
+
trigger. When `value.length > max-chips`, the first N chips
|
|
111
|
+
render plus a "+M more" pill that opens the popover on click.
|
|
112
|
+
`0` (default) = unlimited.
|
|
113
|
+
type: number
|
|
114
|
+
default: 0
|
|
115
|
+
reflect: true
|
|
116
|
+
min:
|
|
117
|
+
description: |
|
|
118
|
+
Multi-select only. Minimum required selections. Below this floor
|
|
119
|
+
the host's form validity goes invalid (valueMissing) and the
|
|
120
|
+
`invalid` event fires.
|
|
121
|
+
type: number
|
|
122
|
+
default: 0
|
|
123
|
+
reflect: true
|
|
124
|
+
max:
|
|
125
|
+
description: |
|
|
126
|
+
Multi-select only. Maximum allowed selections. Toggling past the
|
|
127
|
+
cap is suppressed; the `invalid` event fires with reason="max".
|
|
128
|
+
`0` (default) = unlimited.
|
|
129
|
+
type: number
|
|
130
|
+
default: 0
|
|
131
|
+
reflect: true
|
|
132
|
+
select-all:
|
|
133
|
+
description: |
|
|
134
|
+
Multi-select only. Renders a "Select all" / "Clear" control row
|
|
135
|
+
above the option list. Click selects every non-disabled option;
|
|
136
|
+
when already all selected, click clears.
|
|
137
|
+
type: boolean
|
|
138
|
+
default: false
|
|
139
|
+
reflect: true
|
|
140
|
+
clearable:
|
|
141
|
+
description: |
|
|
142
|
+
Multi-select only. Adds a clear-all `x` affordance to the trigger
|
|
143
|
+
when at least one chip is present. Click empties value and fires
|
|
144
|
+
`change`.
|
|
145
|
+
type: boolean
|
|
146
|
+
default: false
|
|
147
|
+
reflect: true
|
|
95
148
|
open:
|
|
96
149
|
description: Whether the listbox is open
|
|
97
150
|
type: boolean
|
|
@@ -128,6 +181,10 @@ props:
|
|
|
128
181
|
events:
|
|
129
182
|
change:
|
|
130
183
|
description: Fired when selected value changes
|
|
184
|
+
invalid:
|
|
185
|
+
description: |
|
|
186
|
+
Multi-select only. Fired when a toggle is suppressed by [min] or
|
|
187
|
+
[max] constraints. detail = { value, reason: 'min' | 'max' }.
|
|
131
188
|
usage: |-
|
|
132
189
|
§225 (v0.5.9) — Consumer-authored children must be native `<option>` or
|
|
133
190
|
`<optgroup>`. The `#parseOptions()` walker reads only those two tag names;
|
|
@@ -173,6 +230,9 @@ traits: []
|
|
|
173
230
|
tokens: {}
|
|
174
231
|
requiredIcons:
|
|
175
232
|
- caret-up-down
|
|
233
|
+
- check # checkbox indicator on each option in [multiple] mode
|
|
234
|
+
- x # chip dismiss + clear-all affordance ([multiple] + [clearable])
|
|
235
|
+
- magnifying-glass # search-input prefix ([searchable])
|
|
176
236
|
a2ui:
|
|
177
237
|
rules:
|
|
178
238
|
- >-
|
|
@@ -200,6 +260,18 @@ a2ui:
|
|
|
200
260
|
unmatched values are valid (tag entry, email-with-suggestion).
|
|
201
261
|
Use [multiple searchable] for multi-select rather than
|
|
202
262
|
authoring a separate multi-select primitive.
|
|
263
|
+
- >-
|
|
264
|
+
For multi-select, set [multiple] — the trigger automatically
|
|
265
|
+
renders <tag-ui> chips per selected option; the popover renders
|
|
266
|
+
checkbox-style option rows where clicks toggle membership
|
|
267
|
+
without closing. Form value is comma-separated under [name].
|
|
268
|
+
There is NO `<multi-select-ui>` tag — that name does not exist.
|
|
269
|
+
- >-
|
|
270
|
+
Multi-select bulk controls: [select-all] renders a "Select all" /
|
|
271
|
+
"Clear" control above the option list; [clearable] adds a
|
|
272
|
+
clear-all `x` affordance to the trigger. [max-chips] caps the
|
|
273
|
+
visible chip count and renders "+N more". [min] / [max] gate
|
|
274
|
+
form validity.
|
|
203
275
|
anti_patterns: []
|
|
204
276
|
examples:
|
|
205
277
|
- name: bleed-design-settings
|
|
@@ -341,6 +413,37 @@ examples:
|
|
|
341
413
|
"variant": "primary"
|
|
342
414
|
}
|
|
343
415
|
]
|
|
416
|
+
- name: multi-select-tags
|
|
417
|
+
description: Multi-select with chip trigger + checkbox option list (SPEC-040).
|
|
418
|
+
a2ui: >-
|
|
419
|
+
[
|
|
420
|
+
{
|
|
421
|
+
"id": "root",
|
|
422
|
+
"component": "Card",
|
|
423
|
+
"children": ["sec"]
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"id": "sec",
|
|
427
|
+
"component": "Section",
|
|
428
|
+
"children": ["col"]
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"id": "col",
|
|
432
|
+
"component": "Column",
|
|
433
|
+
"children": ["tags"],
|
|
434
|
+
"gap": "3"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"id": "tags",
|
|
438
|
+
"component": "Select",
|
|
439
|
+
"multiple": true,
|
|
440
|
+
"selectAll": true,
|
|
441
|
+
"label": "Tags",
|
|
442
|
+
"name": "tags",
|
|
443
|
+
"placeholder": "Pick tags...",
|
|
444
|
+
"value": "urgent,backend"
|
|
445
|
+
}
|
|
446
|
+
]
|
|
344
447
|
- name: create-form
|
|
345
448
|
description: Simple account creation form with text fields, select, and action buttons.
|
|
346
449
|
a2ui: >-
|
|
@@ -443,6 +546,12 @@ keywords:
|
|
|
443
546
|
- dropdown
|
|
444
547
|
- combobox
|
|
445
548
|
- autocomplete
|
|
549
|
+
- multi-select
|
|
550
|
+
- multiple
|
|
551
|
+
- chips
|
|
552
|
+
- tokens
|
|
553
|
+
- tags
|
|
554
|
+
- picker
|
|
446
555
|
synonyms:
|
|
447
556
|
autocomplete:
|
|
448
557
|
- combobox
|
|
@@ -461,6 +570,18 @@ synonyms:
|
|
|
461
570
|
- menu
|
|
462
571
|
- select
|
|
463
572
|
- form
|
|
573
|
+
multi-select:
|
|
574
|
+
- multiselect
|
|
575
|
+
- multi-pick
|
|
576
|
+
- chips
|
|
577
|
+
- tokens
|
|
578
|
+
- tags
|
|
579
|
+
- multiple
|
|
580
|
+
multiple:
|
|
581
|
+
- multi-select
|
|
582
|
+
- multiselect
|
|
583
|
+
- chips
|
|
584
|
+
- select-many
|
|
464
585
|
related:
|
|
465
586
|
- image
|
|
466
587
|
- button
|
|
@@ -48,12 +48,13 @@
|
|
|
48
48
|
"default": "current"
|
|
49
49
|
},
|
|
50
50
|
"variant": {
|
|
51
|
-
"description": "Visual flavor — arc (rotating quarter-circle), ring (full ring with one colored segment), dots (three bouncing dots).",
|
|
51
|
+
"description": "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).",
|
|
52
52
|
"type": "string",
|
|
53
53
|
"enum": [
|
|
54
54
|
"arc",
|
|
55
55
|
"ring",
|
|
56
|
-
"dots"
|
|
56
|
+
"dots",
|
|
57
|
+
"knight"
|
|
57
58
|
],
|
|
58
59
|
"default": "arc"
|
|
59
60
|
}
|