@adia-ai/web-components 0.6.33 → 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 +64 -0
- package/color/index.js +1 -1
- package/components/accordion/accordion-item.yaml +2 -2
- package/components/accordion/accordion.css +2 -2
- package/components/accordion/accordion.js +1 -1
- package/components/action-list/action-item.yaml +2 -2
- package/components/action-list/action-list.css +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.css +31 -31
- package/components/agent-artifact/agent-artifact.js +1 -1
- package/components/agent-feedback-bar/agent-feedback-bar.css +10 -10
- package/components/agent-feedback-bar/agent-feedback-bar.js +1 -1
- package/components/agent-questions/agent-questions.css +57 -57
- package/components/agent-questions/agent-questions.js +1 -1
- package/components/agent-reasoning/agent-reasoning.css +62 -62
- package/components/agent-reasoning/agent-reasoning.js +1 -1
- package/components/agent-suggestions/agent-suggestions.css +4 -4
- package/components/agent-suggestions/agent-suggestions.js +1 -1
- package/components/agent-trace/agent-trace.css +53 -53
- package/components/alert/alert.a2ui.json +64 -1
- package/components/alert/{class.js → alert.class.js} +189 -2
- package/components/alert/alert.css +119 -41
- 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.css +27 -27
- package/components/avatar/avatar.js +1 -1
- package/components/badge/badge.css +27 -27
- package/components/badge/badge.js +1 -1
- package/components/block/block.css +16 -16
- package/components/block/block.js +1 -1
- package/components/breadcrumb/breadcrumb.css +23 -23
- package/components/breadcrumb/breadcrumb.js +1 -1
- package/components/button/button.css +101 -91
- package/components/button/button.js +1 -1
- package/components/calendar-grid/calendar-grid.a2ui.json +146 -0
- package/components/calendar-grid/calendar-grid.class.js +326 -0
- package/components/calendar-grid/calendar-grid.css +246 -0
- package/components/calendar-grid/calendar-grid.d.ts +41 -0
- package/components/calendar-grid/calendar-grid.js +17 -0
- package/components/calendar-grid/calendar-grid.yaml +136 -0
- package/components/calendar-picker/calendar-picker.css +139 -139
- package/components/calendar-picker/calendar-picker.js +1 -1
- package/components/canvas/canvas.css +12 -12
- package/components/card/card.css +83 -83
- package/components/card/card.js +1 -1
- package/components/chart/chart.css +224 -224
- package/components/chart/chart.js +1 -1
- package/components/chart-legend/chart-legend.css +26 -26
- 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.css +40 -40
- package/components/check/check.js +1 -1
- package/components/code/code.css +125 -125
- package/components/code/code.js +1 -1
- package/components/col/col.css +15 -15
- package/components/col/col.js +1 -1
- package/components/color-input/color-input.js +1 -1
- package/components/color-picker/color-picker.css +55 -55
- package/components/color-picker/color-picker.js +1 -1
- package/components/combobox/combobox.a2ui.json +363 -0
- package/components/combobox/combobox.class.js +861 -0
- package/components/combobox/combobox.css +244 -0
- package/components/combobox/combobox.d.ts +113 -0
- package/components/combobox/combobox.examples.md +59 -0
- package/components/combobox/combobox.js +17 -0
- package/components/combobox/combobox.test.js +181 -0
- package/components/combobox/combobox.yaml +369 -0
- package/components/command/command.css +90 -90
- package/components/command/command.js +1 -1
- package/components/date-range-picker/date-range-picker.a2ui.json +300 -0
- package/components/date-range-picker/date-range-picker.class.js +791 -0
- package/components/date-range-picker/date-range-picker.css +224 -0
- package/components/date-range-picker/date-range-picker.d.ts +82 -0
- package/components/date-range-picker/date-range-picker.examples.md +37 -0
- package/components/date-range-picker/date-range-picker.js +17 -0
- package/components/date-range-picker/date-range-picker.test.js +387 -0
- package/components/date-range-picker/date-range-picker.yaml +285 -0
- package/components/datetime-picker/datetime-picker.a2ui.json +334 -0
- package/components/datetime-picker/datetime-picker.class.js +706 -0
- package/components/datetime-picker/datetime-picker.css +150 -0
- package/components/datetime-picker/datetime-picker.d.ts +86 -0
- package/components/datetime-picker/datetime-picker.examples.md +46 -0
- package/components/datetime-picker/datetime-picker.js +17 -0
- package/components/datetime-picker/datetime-picker.test.js +454 -0
- package/components/datetime-picker/datetime-picker.yaml +332 -0
- package/components/demo-toggle/demo-toggle.css +27 -27
- package/components/demo-toggle/demo-toggle.js +1 -1
- package/components/description-list/description-list.css +18 -18
- package/components/description-list/description-list.js +1 -1
- package/components/divider/divider.css +24 -24
- package/components/divider/divider.js +1 -1
- package/components/drawer/drawer.js +1 -1
- package/components/embed/embed.css +6 -6
- package/components/embed/embed.js +1 -1
- package/components/empty-state/empty-state.css +27 -27
- package/components/empty-state/empty-state.js +1 -1
- package/components/feed/feed.css +12 -12
- package/components/feed/feed.js +1 -1
- package/components/field/field.css +28 -28
- package/components/field/field.js +1 -1
- package/components/field/field.test.js +1 -1
- package/components/fields/fields.css +5 -5
- package/components/fields/fields.js +1 -1
- package/components/grid/grid.css +5 -5
- package/components/grid/grid.js +1 -1
- package/components/heatmap/heatmap.css +63 -63
- package/components/heatmap/heatmap.js +1 -1
- package/components/icon/icon.css +12 -12
- package/components/icon/icon.js +1 -1
- package/components/image/image.css +14 -14
- package/components/image/image.js +1 -1
- package/components/index.js +11 -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 +67 -67
- package/components/input/input.js +1 -1
- package/components/input/input.yaml +5 -4
- package/components/inspector/inspector.css +6 -6
- package/components/inspector/inspector.js +1 -1
- package/components/integration-card/integration-card.a2ui.json +268 -0
- package/components/integration-card/integration-card.class.js +410 -0
- package/components/integration-card/integration-card.css +169 -0
- package/components/integration-card/integration-card.d.ts +63 -0
- package/components/integration-card/integration-card.examples.md +41 -0
- package/components/integration-card/integration-card.js +17 -0
- package/components/integration-card/integration-card.test.js +306 -0
- package/components/integration-card/integration-card.yaml +280 -0
- package/components/kbd/kbd.css +32 -32
- package/components/kbd/kbd.js +1 -1
- package/components/link/link.css +12 -12
- package/components/link/link.js +1 -1
- package/components/list/list-item.yaml +2 -2
- package/components/list/list.css +8 -8
- package/components/list/list.js +1 -1
- package/components/list-window/list-window.a2ui.json +277 -0
- package/components/list-window/list-window.class.js +688 -0
- package/components/list-window/list-window.css +124 -0
- package/components/list-window/list-window.d.ts +84 -0
- package/components/list-window/list-window.examples.md +73 -0
- package/components/list-window/list-window.js +17 -0
- package/components/list-window/list-window.test.js +303 -0
- package/components/list-window/list-window.yaml +270 -0
- 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.css +8 -8
- 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 +54 -44
- package/components/modal/modal.js +1 -1
- package/components/nav/nav.css +40 -40
- package/components/nav/nav.js +1 -1
- package/components/nav-group/nav-group.css +52 -52
- package/components/nav-group/nav-group.js +1 -1
- package/components/nav-item/nav-item.css +44 -44
- package/components/nav-item/nav-item.js +1 -1
- package/components/noodles/noodles.css +31 -31
- package/components/noodles/noodles.js +1 -1
- package/components/option-card/option-card.css +69 -69
- package/components/option-card/option-card.js +1 -1
- package/components/otp-input/otp-input.css +30 -30
- package/components/otp-input/otp-input.js +1 -1
- package/components/page/page.css +18 -18
- package/components/page/page.js +1 -1
- package/components/pagination/pagination.css +61 -61
- package/components/pagination/pagination.js +1 -1
- package/components/pane/pane.css +57 -57
- package/components/pane/pane.js +1 -1
- package/components/pipeline-status/pipeline-status.css +65 -65
- package/components/pipeline-status/pipeline-status.js +1 -1
- package/components/popover/popover.a2ui.json +8 -1
- package/components/popover/popover.css +17 -17
- package/components/popover/popover.js +1 -1
- package/components/popover/popover.yaml +14 -1
- package/components/progress/progress.css +23 -23
- package/components/progress/progress.js +1 -1
- package/components/progress-row/progress-row.css +17 -17
- package/components/progress-row/progress-row.js +1 -1
- package/components/radio/radio.css +39 -39
- package/components/radio/radio.js +1 -1
- package/components/range/range.css +55 -55
- package/components/range/range.js +1 -1
- package/components/rating/rating.css +28 -28
- package/components/rating/rating.js +1 -1
- package/components/richtext/richtext.css +133 -133
- package/components/richtext/richtext.js +1 -1
- package/components/row/row.css +19 -19
- package/components/row/row.js +1 -1
- package/components/search/search.css +5 -5
- package/components/search/search.js +1 -1
- package/components/segment/segment.css +24 -24
- package/components/segment/segment.js +1 -1
- package/components/segmented/segmented.css +25 -25
- 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 +242 -84
- 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.css +14 -14
- package/components/skeleton/skeleton.js +1 -1
- package/components/slider/slider.css +46 -46
- package/components/slider/slider.js +1 -1
- package/components/spinner/spinner.a2ui.json +198 -0
- package/components/spinner/spinner.class.js +99 -0
- package/components/spinner/spinner.css +221 -0
- package/components/spinner/spinner.d.ts +26 -0
- package/components/spinner/spinner.examples.md +26 -0
- package/components/spinner/spinner.js +17 -0
- package/components/spinner/spinner.test.js +272 -0
- package/components/spinner/spinner.yaml +238 -0
- package/components/stack/stack.css +11 -11
- package/components/stack/stack.js +1 -1
- package/components/stat/stat.css +25 -25
- package/components/step-progress/step-progress.css +20 -20
- package/components/step-progress/step-progress.js +1 -1
- package/components/stepper/stepper-item.yaml +1 -1
- package/components/stepper/stepper.css +29 -29
- package/components/stepper/stepper.js +1 -1
- package/components/stream/stream.css +12 -12
- package/components/stream/stream.js +1 -1
- package/components/swatch/swatch.css +68 -68
- package/components/swatch/swatch.js +1 -1
- package/components/swiper/swiper.css +57 -57
- package/components/swiper/swiper.js +1 -1
- package/components/switch/switch.css +52 -52
- package/components/switch/switch.js +1 -1
- package/components/table/table.css +163 -163
- 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.css +32 -32
- package/components/table-toolbar/table-toolbar.js +1 -1
- package/components/tabs/tab.yaml +2 -2
- package/components/tabs/tabs.css +51 -51
- package/components/tabs/tabs.js +1 -1
- package/components/tag/tag.css +48 -48
- 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.css +44 -44
- package/components/text/text.js +1 -1
- package/components/textarea/textarea.a2ui.json +1 -1
- package/components/textarea/textarea.css +46 -46
- package/components/textarea/textarea.js +1 -1
- package/components/textarea/textarea.yaml +11 -8
- package/components/time-picker/time-picker.a2ui.json +267 -0
- package/components/time-picker/time-picker.class.js +693 -0
- package/components/time-picker/time-picker.css +122 -0
- package/components/time-picker/time-picker.d.ts +75 -0
- package/components/time-picker/time-picker.examples.md +35 -0
- package/components/time-picker/time-picker.js +17 -0
- package/components/time-picker/time-picker.test.js +287 -0
- package/components/time-picker/time-picker.yaml +256 -0
- package/components/timeline/timeline-item.yaml +2 -2
- package/components/timeline/{class.js → timeline.class.js} +1 -1
- package/components/timeline/timeline.css +50 -50
- package/components/timeline/timeline.js +1 -1
- package/components/toast/toast.css +58 -58
- package/components/toast/toast.js +1 -1
- package/components/toggle-group/toggle-group.css +6 -6
- package/components/toggle-group/toggle-group.js +1 -1
- package/components/toggle-group/toggle-option.yaml +1 -1
- package/components/toggle-scheme/toggle-scheme.css +2 -2
- package/components/toggle-scheme/toggle-scheme.js +1 -1
- package/components/toolbar/toolbar-group.yaml +1 -1
- package/components/toolbar/toolbar.css +17 -17
- package/components/toolbar/toolbar.js +1 -1
- package/components/tooltip/tooltip.css +2 -2
- package/components/tooltip/tooltip.js +1 -1
- package/components/tree/tree-item.yaml +1 -1
- package/components/tree/tree.css +37 -37
- package/components/tree/tree.js +1 -1
- package/components/upload/upload.css +49 -49
- package/components/upload/upload.js +1 -1
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +146 -87
- package/package.json +3 -3
- package/styles/components.css +11 -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/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/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/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/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
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/Spinner.json",
|
|
4
|
+
"title": "Spinner",
|
|
5
|
+
"description": "Circular animated indicator for indeterminate loading. Renders a rotating arc, full ring, or three bouncing dots inside a sized box; the animation runs while the element is in the DOM and `[paused]` is unset. Fills the circular-spinner gap left by <skeleton-ui> (rectangular placeholder) and <progress-ui> (linear determinate bar) — use <spinner-ui> when the wait duration is unknown and the shape of the eventual content is irregular or the region is too small for a placeholder block.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "Spinner"
|
|
18
|
+
},
|
|
19
|
+
"label": {
|
|
20
|
+
"description": "Accessible operation name surfaced via `aria-valuetext`. Override for context-specific labels (\"Saving\", \"Uploading\").",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"default": "Loading"
|
|
23
|
+
},
|
|
24
|
+
"paused": {
|
|
25
|
+
"description": "Pause the animation in-place. Useful for screenshot tests and explicit-control flows.",
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": false
|
|
28
|
+
},
|
|
29
|
+
"size": {
|
|
30
|
+
"description": "Diameter — matches icon-ui's ladder (sm 14px, md 16px, lg 20px).",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"enum": [
|
|
33
|
+
"sm",
|
|
34
|
+
"md",
|
|
35
|
+
"lg"
|
|
36
|
+
],
|
|
37
|
+
"default": "md"
|
|
38
|
+
},
|
|
39
|
+
"tone": {
|
|
40
|
+
"description": "Color tone — `current` inherits parent text color (matches button label), `accent` uses brand accent, `subtle` is muted, `inverse` flips for on-accent surfaces.",
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": [
|
|
43
|
+
"current",
|
|
44
|
+
"accent",
|
|
45
|
+
"subtle",
|
|
46
|
+
"inverse"
|
|
47
|
+
],
|
|
48
|
+
"default": "current"
|
|
49
|
+
},
|
|
50
|
+
"variant": {
|
|
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
|
+
"type": "string",
|
|
53
|
+
"enum": [
|
|
54
|
+
"arc",
|
|
55
|
+
"ring",
|
|
56
|
+
"dots",
|
|
57
|
+
"knight"
|
|
58
|
+
],
|
|
59
|
+
"default": "arc"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"required": [
|
|
63
|
+
"component"
|
|
64
|
+
],
|
|
65
|
+
"unevaluatedProperties": false,
|
|
66
|
+
"x-adiaui": {
|
|
67
|
+
"anti_patterns": [
|
|
68
|
+
{
|
|
69
|
+
"fix": "{\"component\": \"Progress\", \"value\": 42, \"max\": 100}\n",
|
|
70
|
+
"why": "Spinner is INDETERMINATE only. `value` and any quantitative\nprogress field belongs on Progress, not Spinner. Also \"Spin\" is\nnot a valid operation label.\n",
|
|
71
|
+
"wrong": "{\"component\": \"Spinner\", \"label\": \"Spin\", \"value\": 0.42}\n"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"fix": "{\"component\": \"Spinner\", \"size\": \"md\"}\n",
|
|
75
|
+
"why": "Skeleton is a placeholder; rotation is not part of its contract.\nA rotating circle is a Spinner.\n",
|
|
76
|
+
"wrong": "{\"component\": \"Skeleton\", \"variant\": \"circle\", \"animation\": \"rotate\"}\n"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"fix": "{\"component\": \"Card\", \"children\": [\n {\"component\": \"Spinner\", \"size\": \"lg\"}\n]}\n",
|
|
80
|
+
"why": "Multiple sibling spinners in one region produce visual noise\nwithout extra information. Use one parent-level Spinner.\n",
|
|
81
|
+
"wrong": "{\"component\": \"Card\", \"children\": [\n {\"component\": \"Spinner\"},\n {\"component\": \"Spinner\"},\n {\"component\": \"Spinner\"}\n]}\n"
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"category": "feedback",
|
|
85
|
+
"composes": [],
|
|
86
|
+
"events": {},
|
|
87
|
+
"examples": [
|
|
88
|
+
{
|
|
89
|
+
"description": "Loading button — primary action with a saving spinner. The button is disabled while the operation is in progress; the spinner matches the button label color via tone=\"current\".",
|
|
90
|
+
"a2ui": "[\n {\n \"id\": \"btn-save\",\n \"component\": \"Button\",\n \"text\": \"Saving\",\n \"variant\": \"primary\",\n \"disabled\": true,\n \"children\": [\"sp-1\"]\n },\n {\n \"id\": \"sp-1\",\n \"component\": \"Spinner\",\n \"size\": \"sm\",\n \"tone\": \"current\",\n \"label\": \"Saving\"\n }\n]",
|
|
91
|
+
"name": "button-saving"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"description": "Standalone centered spinner inside a card while body content fetches.",
|
|
95
|
+
"a2ui": "[\n {\n \"id\": \"card\",\n \"component\": \"Card\",\n \"children\": [\"row\"]\n },\n {\n \"id\": \"row\",\n \"component\": \"Row\",\n \"justify\": \"center\",\n \"align\": \"center\",\n \"children\": [\"sp\"]\n },\n {\n \"id\": \"sp\",\n \"component\": \"Spinner\",\n \"size\": \"lg\",\n \"tone\": \"subtle\",\n \"label\": \"Loading dashboard\"\n }\n]",
|
|
96
|
+
"name": "centered-card-loading"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"description": "Three bouncing dots — good for chat / typing indicators.",
|
|
100
|
+
"a2ui": "[\n {\n \"id\": \"sp\",\n \"component\": \"Spinner\",\n \"variant\": \"dots\",\n \"tone\": \"subtle\",\n \"label\": \"Assistant is typing\"\n }\n]",
|
|
101
|
+
"name": "typing-indicator"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"keywords": [
|
|
105
|
+
"spinner",
|
|
106
|
+
"loader",
|
|
107
|
+
"loading",
|
|
108
|
+
"indeterminate",
|
|
109
|
+
"progress",
|
|
110
|
+
"busy",
|
|
111
|
+
"feedback",
|
|
112
|
+
"circular"
|
|
113
|
+
],
|
|
114
|
+
"name": "UISpinner",
|
|
115
|
+
"related": [
|
|
116
|
+
"Progress",
|
|
117
|
+
"Skeleton",
|
|
118
|
+
"Button",
|
|
119
|
+
"EmptyState"
|
|
120
|
+
],
|
|
121
|
+
"slots": {},
|
|
122
|
+
"states": [
|
|
123
|
+
{
|
|
124
|
+
"description": "Default; animation active.",
|
|
125
|
+
"name": "running"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"description": "Animation frozen at the current frame.",
|
|
129
|
+
"attribute": "paused",
|
|
130
|
+
"name": "paused"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"description": "Triggered by prefers-reduced-motion. Animation replaced with a static ellipsis. Detected via CSS, not JS.",
|
|
134
|
+
"name": "reduced"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"status": "stable",
|
|
138
|
+
"synonyms": {
|
|
139
|
+
"busy": [
|
|
140
|
+
"spinner",
|
|
141
|
+
"loading"
|
|
142
|
+
],
|
|
143
|
+
"indeterminate": [
|
|
144
|
+
"spinner",
|
|
145
|
+
"progress"
|
|
146
|
+
],
|
|
147
|
+
"loader": [
|
|
148
|
+
"spinner",
|
|
149
|
+
"loading",
|
|
150
|
+
"progress"
|
|
151
|
+
],
|
|
152
|
+
"loading": [
|
|
153
|
+
"spinner",
|
|
154
|
+
"loading",
|
|
155
|
+
"progress",
|
|
156
|
+
"skeleton"
|
|
157
|
+
],
|
|
158
|
+
"saving": [
|
|
159
|
+
"spinner",
|
|
160
|
+
"loading"
|
|
161
|
+
],
|
|
162
|
+
"spinner": [
|
|
163
|
+
"spinner",
|
|
164
|
+
"loader",
|
|
165
|
+
"progress"
|
|
166
|
+
],
|
|
167
|
+
"uploading": [
|
|
168
|
+
"spinner",
|
|
169
|
+
"loading"
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
"tag": "spinner-ui",
|
|
173
|
+
"tokens": {
|
|
174
|
+
"--spinner-color": {
|
|
175
|
+
"description": "Color of the active arc / ring / dots. Defaults to currentColor so a tone-driven cascade resolves naturally.",
|
|
176
|
+
"default": "currentColor"
|
|
177
|
+
},
|
|
178
|
+
"--spinner-duration": {
|
|
179
|
+
"description": "One full rotation duration.",
|
|
180
|
+
"default": "var(--a-duration-slow)"
|
|
181
|
+
},
|
|
182
|
+
"--spinner-size": {
|
|
183
|
+
"description": "Diameter of the spinner box.",
|
|
184
|
+
"default": "1rem"
|
|
185
|
+
},
|
|
186
|
+
"--spinner-stroke": {
|
|
187
|
+
"description": "Border thickness for the arc / ring variants.",
|
|
188
|
+
"default": "2px"
|
|
189
|
+
},
|
|
190
|
+
"--spinner-track-opacity": {
|
|
191
|
+
"description": "Opacity for the non-rotating ring track (variant=ring only).",
|
|
192
|
+
"default": "0.25"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"traits": [],
|
|
196
|
+
"version": 1
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-side-effect class export for `<spinner-ui>`.
|
|
3
|
+
*
|
|
4
|
+
* Importing this file gives you the class without auto-registering the
|
|
5
|
+
* tag. Useful for test isolation, subclassing with tag-name override, or
|
|
6
|
+
* selective composition.
|
|
7
|
+
*
|
|
8
|
+
* The auto-register path stays at `@adia-ai/web-components/components/spinner`
|
|
9
|
+
* (which imports this file + calls `defineIfFree()`).
|
|
10
|
+
*
|
|
11
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* <spinner-ui size="md" variant="arc" tone="current" label="Loading"></spinner-ui>
|
|
16
|
+
* <spinner-ui variant="dots" tone="subtle" label="Assistant is typing"></spinner-ui>
|
|
17
|
+
* <spinner-ui paused size="lg"></spinner-ui>
|
|
18
|
+
*
|
|
19
|
+
* Circular animated indicator for INDETERMINATE loading. The visual is
|
|
20
|
+
* rendered entirely via `::before` (and per-variant peers) on the host;
|
|
21
|
+
* the component stamps no internal DOM (`static template = () => null`).
|
|
22
|
+
*
|
|
23
|
+
* Props (attributes):
|
|
24
|
+
* size — sm | md (default) | lg
|
|
25
|
+
* variant — arc (default) | ring | dots
|
|
26
|
+
* tone — current (default) | subtle | accent | inverse
|
|
27
|
+
* paused — freeze the animation in place (default: false)
|
|
28
|
+
* label — accessible operation name (default: "Loading")
|
|
29
|
+
*
|
|
30
|
+
* ARIA: role="progressbar" + aria-busy="true" + aria-valuetext=<label>.
|
|
31
|
+
* Reduced motion: when prefers-reduced-motion: reduce is active, the
|
|
32
|
+
* spinning animation is replaced with a static "…" ellipsis via CSS
|
|
33
|
+
* only — no JS observer required. WCAG 2.3.3.
|
|
34
|
+
*
|
|
35
|
+
* Lifecycle: pure-CSS animation. No timers, no observers. connected()
|
|
36
|
+
* sets the three ARIA attributes once; render() keeps aria-valuetext in
|
|
37
|
+
* sync with the [label] prop.
|
|
38
|
+
*
|
|
39
|
+
* @see SPEC-001 (docs/specs/implementation-ready/SPEC-001-spinner-loader.md)
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
import { UIElement } from '../../core/element.js';
|
|
43
|
+
|
|
44
|
+
export class UISpinner extends UIElement {
|
|
45
|
+
static properties = {
|
|
46
|
+
size: { type: String, default: 'md', reflect: true },
|
|
47
|
+
variant: { type: String, default: 'arc', reflect: true },
|
|
48
|
+
tone: { type: String, default: 'current', reflect: true },
|
|
49
|
+
paused: { type: Boolean, default: false, reflect: true },
|
|
50
|
+
label: { type: String, default: 'Loading', reflect: false },
|
|
51
|
+
};
|
|
52
|
+
|
|
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.
|
|
63
|
+
static template = () => null;
|
|
64
|
+
|
|
65
|
+
connected() {
|
|
66
|
+
// ARIA wiring — fixed for the lifetime of the element.
|
|
67
|
+
if (!this.hasAttribute('role')) this.setAttribute('role', 'progressbar');
|
|
68
|
+
if (!this.hasAttribute('aria-busy')) this.setAttribute('aria-busy', 'true');
|
|
69
|
+
this.setAttribute('aria-valuetext', this.label || 'Loading');
|
|
70
|
+
this.#syncDots();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
render() {
|
|
74
|
+
// Keep aria-valuetext in sync if `label` changes after connect.
|
|
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
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
@scope (spinner-ui) {
|
|
2
|
+
/* ── Block 1 — TOKENS ─────────────────────────────────────────────
|
|
3
|
+
Spinner inherits the icon ladder for sizing (matches icon-ui's
|
|
4
|
+
`:scope[size="..."]` rems). The semantic colors come via `tone=…`
|
|
5
|
+
re-assigning --spinner-color. Stroke is 2px (raw px allowed for
|
|
6
|
+
borders 1-2px per component-token-contract §"Forbidden patterns"). */
|
|
7
|
+
:where(:scope) {
|
|
8
|
+
--spinner-size-default: 1rem; /* icon-ui md */
|
|
9
|
+
--spinner-color-default: currentColor;
|
|
10
|
+
--spinner-stroke-default: 2px;
|
|
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;
|
|
16
|
+
--spinner-track-opacity-default: 0.25;
|
|
17
|
+
--spinner-dot-size-default: calc(var(--spinner-size, var(--spinner-size-default)) / 4);
|
|
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;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ── Block 2 — BASE ────────────────────────────────────────────── */
|
|
31
|
+
:scope {
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
display: inline-block;
|
|
34
|
+
width: var(--spinner-size, var(--spinner-size-default));
|
|
35
|
+
height: var(--spinner-size, var(--spinner-size-default));
|
|
36
|
+
color: var(--spinner-color, var(--spinner-color-default));
|
|
37
|
+
vertical-align: middle;
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* ── Size ladder (mirrors icon-ui's local rem declarations) ─────── */
|
|
42
|
+
:scope[size="sm"] { --spinner-size-default: 0.875rem; } /* 14px */
|
|
43
|
+
:scope[size="md"] { --spinner-size-default: 1rem; } /* 16px */
|
|
44
|
+
:scope[size="lg"] { --spinner-size-default: 1.25rem; } /* 20px */
|
|
45
|
+
|
|
46
|
+
/* ── Tones (override --spinner-color token) ────────────────────── */
|
|
47
|
+
:scope[tone="current"] { --spinner-color-default: currentColor; }
|
|
48
|
+
:scope[tone="subtle"] { --spinner-color-default: var(--a-fg-subtle); }
|
|
49
|
+
:scope[tone="accent"] { --spinner-color-default: var(--a-accent-strong); }
|
|
50
|
+
:scope[tone="inverse"] { --spinner-color-default: var(--a-chrome-light); }
|
|
51
|
+
|
|
52
|
+
/* ── Variant: ARC (default) — rotating quarter-circle border ───── */
|
|
53
|
+
:scope[variant="arc"]::before,
|
|
54
|
+
:scope:not([variant])::before {
|
|
55
|
+
content: "";
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
display: block;
|
|
58
|
+
width: 100%;
|
|
59
|
+
height: 100%;
|
|
60
|
+
border-radius: 50%;
|
|
61
|
+
border: var(--spinner-stroke, var(--spinner-stroke-default)) solid;
|
|
62
|
+
border-color: currentColor transparent transparent transparent;
|
|
63
|
+
animation: spinner-ui-rotate var(--spinner-duration, var(--spinner-duration-default)) linear infinite;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* ── Variant: RING — full ring with one rotating colored segment ── */
|
|
67
|
+
:scope[variant="ring"]::before {
|
|
68
|
+
content: "";
|
|
69
|
+
box-sizing: border-box;
|
|
70
|
+
display: block;
|
|
71
|
+
width: 100%;
|
|
72
|
+
height: 100%;
|
|
73
|
+
border-radius: 50%;
|
|
74
|
+
border: var(--spinner-stroke, var(--spinner-stroke-default)) solid;
|
|
75
|
+
border-color: color-mix(in oklch, currentColor calc(var(--spinner-track-opacity, var(--spinner-track-opacity-default)) * 100%), transparent);
|
|
76
|
+
border-top-color: currentColor;
|
|
77
|
+
animation: spinner-ui-rotate var(--spinner-duration, var(--spinner-duration-default)) linear infinite;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* ── Variant: DOTS — three bouncing dots ─────────────────────────
|
|
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.
|
|
85
|
+
|
|
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. */
|
|
92
|
+
:scope[variant="dots"] {
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
width: auto; /* dots row is wider than tall */
|
|
97
|
+
min-width: var(--spinner-size, var(--spinner-size-default));
|
|
98
|
+
gap: var(--spinner-dot-gap, var(--spinner-dot-gap-default));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
:scope[variant="dots"] > [data-spinner-dot] {
|
|
102
|
+
width: var(--spinner-dot-size, var(--spinner-dot-size-default));
|
|
103
|
+
height: var(--spinner-dot-size, var(--spinner-dot-size-default));
|
|
104
|
+
border-radius: 50%;
|
|
105
|
+
background: currentColor;
|
|
106
|
+
animation: spinner-ui-bounce var(--spinner-duration, var(--spinner-duration-default)) ease-in-out infinite;
|
|
107
|
+
}
|
|
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);
|
|
117
|
+
}
|
|
118
|
+
|
|
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;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* ── Paused state — freeze in place ────────────────────────────── */
|
|
153
|
+
:scope[paused]::before,
|
|
154
|
+
:scope[paused]::after,
|
|
155
|
+
:scope[paused] > [data-spinner-dot] {
|
|
156
|
+
animation-play-state: paused;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ── Reduced-motion replacement: static "…" ellipsis ────────────
|
|
160
|
+
WCAG 2.3.3 — animations of any duration are a vestibular risk.
|
|
161
|
+
The static replacement still announces aria-busy="true" via the
|
|
162
|
+
JS lifecycle. */
|
|
163
|
+
@media (prefers-reduced-motion: reduce) {
|
|
164
|
+
:scope::before,
|
|
165
|
+
:scope::after,
|
|
166
|
+
:scope > [data-spinner-dot] {
|
|
167
|
+
animation: none !important;
|
|
168
|
+
}
|
|
169
|
+
:scope::before {
|
|
170
|
+
content: "…";
|
|
171
|
+
border: none;
|
|
172
|
+
background: transparent;
|
|
173
|
+
box-shadow: none;
|
|
174
|
+
margin: 0;
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: 100%;
|
|
177
|
+
display: flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
justify-content: center;
|
|
180
|
+
font: inherit;
|
|
181
|
+
line-height: 1;
|
|
182
|
+
text-align: center;
|
|
183
|
+
color: currentColor;
|
|
184
|
+
}
|
|
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; }
|
|
188
|
+
:scope[variant="dots"] {
|
|
189
|
+
width: var(--spinner-size, var(--spinner-size-default)); /* shrink back to a square in reduced mode */
|
|
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
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* ── Keyframes ─────────────────────────────────────────────────── */
|
|
200
|
+
@keyframes spinner-ui-rotate {
|
|
201
|
+
to { transform: rotate(360deg); }
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@keyframes spinner-ui-bounce {
|
|
205
|
+
0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }
|
|
206
|
+
40% { transform: scale(1); opacity: 1; }
|
|
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
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<spinner-ui>` — Circular animated indicator for indeterminate loading. Renders a rotating arc, full ring, or three bouncing dots inside a sized box; the animation runs while the element is in the DOM and `[paused]` is unset. Fills the circular-spinner gap left by <skeleton-ui> (rectangular placeholder) and <progress-ui> (linear determinate bar) — use <spinner-ui> when the wait duration is unknown and the shape of the eventual content is irregular or the region is too small for a placeholder block.
|
|
3
|
+
*
|
|
4
|
+
* @see https://ui-kit.exe.xyz/site/components/spinner
|
|
5
|
+
*
|
|
6
|
+
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
|
+
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
|
+
* regenerate; or hand-author this file fully if rich event types are
|
|
10
|
+
* needed beyond what the yaml `events:` block can express.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { UIElement } from '../../core/element.js';
|
|
14
|
+
|
|
15
|
+
export class UISpinner extends UIElement {
|
|
16
|
+
/** Accessible operation name surfaced via `aria-valuetext`. Override for context-specific labels ("Saving", "Uploading"). */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Pause the animation in-place. Useful for screenshot tests and explicit-control flows. */
|
|
19
|
+
paused: boolean;
|
|
20
|
+
/** Diameter — matches icon-ui's ladder (sm 14px, md 16px, lg 20px). */
|
|
21
|
+
size: 'sm' | 'md' | 'lg';
|
|
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
|
+
tone: 'current' | 'accent' | 'subtle' | 'inverse';
|
|
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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# spinner — Examples
|
|
2
|
+
|
|
3
|
+
## Default
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<spinner-ui></spinner-ui>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Loading button
|
|
10
|
+
|
|
11
|
+
Canonical composition. Disable the button while the operation is in
|
|
12
|
+
progress; `tone="current"` keeps the spinner matched to the button's
|
|
13
|
+
label color.
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<button-ui variant="primary" disabled>
|
|
17
|
+
<spinner-ui size="sm" tone="current" label="Saving"></spinner-ui>
|
|
18
|
+
Saving
|
|
19
|
+
</button-ui>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Typing indicator
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<spinner-ui variant="dots" tone="subtle" label="Assistant is typing"></spinner-ui>
|
|
26
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<spinner-ui>` — auto-registers the tag on import.
|
|
3
|
+
*
|
|
4
|
+
* For non-side-effect class import (test isolation, tag override), use
|
|
5
|
+
* the `class` subpath:
|
|
6
|
+
*
|
|
7
|
+
* import { UISpinner } from '@adia-ai/web-components/components/spinner/class';
|
|
8
|
+
*
|
|
9
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { defineIfFree } from '../../core/register.js';
|
|
13
|
+
import { UISpinner } from './spinner.class.js';
|
|
14
|
+
|
|
15
|
+
defineIfFree('spinner-ui', UISpinner);
|
|
16
|
+
|
|
17
|
+
export { UISpinner };
|