@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.
Files changed (271) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/color/index.js +1 -1
  3. package/components/accordion/accordion-item.yaml +2 -2
  4. package/components/accordion/accordion.js +1 -1
  5. package/components/action-list/action-item.yaml +2 -2
  6. package/components/action-list/action-list.js +1 -1
  7. package/components/agent-artifact/{class.js → agent-artifact.class.js} +1 -1
  8. package/components/agent-artifact/agent-artifact.js +1 -1
  9. package/components/agent-feedback-bar/agent-feedback-bar.js +1 -1
  10. package/components/agent-questions/agent-questions.js +1 -1
  11. package/components/agent-reasoning/agent-reasoning.js +1 -1
  12. package/components/agent-suggestions/agent-suggestions.js +1 -1
  13. package/components/alert/alert.a2ui.json +64 -1
  14. package/components/alert/{class.js → alert.class.js} +189 -2
  15. package/components/alert/alert.css +78 -0
  16. package/components/alert/alert.d.ts +14 -0
  17. package/components/alert/alert.js +1 -1
  18. package/components/alert/alert.test.js +184 -0
  19. package/components/alert/alert.yaml +114 -1
  20. package/components/avatar/avatar-group.yaml +2 -2
  21. package/components/avatar/avatar.js +1 -1
  22. package/components/badge/badge.js +1 -1
  23. package/components/block/block.js +1 -1
  24. package/components/breadcrumb/breadcrumb.js +1 -1
  25. package/components/button/button.js +1 -1
  26. package/components/calendar-grid/calendar-grid.a2ui.json +10 -0
  27. package/components/calendar-grid/{class.js → calendar-grid.class.js} +30 -4
  28. package/components/calendar-grid/calendar-grid.css +20 -0
  29. package/components/calendar-grid/calendar-grid.d.ts +4 -0
  30. package/components/calendar-grid/calendar-grid.js +1 -1
  31. package/components/calendar-grid/calendar-grid.yaml +20 -0
  32. package/components/calendar-picker/calendar-picker.js +1 -1
  33. package/components/card/card.js +1 -1
  34. package/components/chart/chart.js +1 -1
  35. package/components/chart-legend/chart-legend.js +1 -1
  36. package/components/chat-thread/chat-input.a2ui.json +1 -1
  37. package/components/chat-thread/chat-input.js +6 -1
  38. package/components/chat-thread/chat-input.yaml +4 -1
  39. package/components/chat-thread/chat-thread.js +1 -1
  40. package/components/check/check.js +1 -1
  41. package/components/code/code.js +1 -1
  42. package/components/col/col.js +1 -1
  43. package/components/color-input/color-input.js +1 -1
  44. package/components/color-picker/color-picker.js +1 -1
  45. package/components/combobox/combobox.js +1 -1
  46. package/components/command/command.js +1 -1
  47. package/components/date-range-picker/{class.js → date-range-picker.class.js} +18 -2
  48. package/components/date-range-picker/date-range-picker.css +51 -5
  49. package/components/date-range-picker/date-range-picker.js +1 -1
  50. package/components/datetime-picker/{class.js → datetime-picker.class.js} +1 -1
  51. package/components/datetime-picker/datetime-picker.js +1 -1
  52. package/components/demo-toggle/demo-toggle.js +1 -1
  53. package/components/description-list/description-list.js +1 -1
  54. package/components/divider/divider.js +1 -1
  55. package/components/drawer/drawer.js +1 -1
  56. package/components/embed/embed.js +1 -1
  57. package/components/empty-state/empty-state.js +1 -1
  58. package/components/feed/feed.js +1 -1
  59. package/components/field/field.js +1 -1
  60. package/components/field/field.test.js +1 -1
  61. package/components/fields/fields.js +1 -1
  62. package/components/grid/grid.js +1 -1
  63. package/components/heatmap/heatmap.js +1 -1
  64. package/components/icon/icon.js +1 -1
  65. package/components/image/image.js +1 -1
  66. package/components/index.js +3 -0
  67. package/components/inline-message/inline-message.a2ui.json +143 -0
  68. package/components/inline-message/inline-message.class.js +169 -0
  69. package/components/inline-message/inline-message.css +75 -0
  70. package/components/inline-message/inline-message.d.ts +31 -0
  71. package/components/inline-message/inline-message.examples.md +19 -0
  72. package/components/inline-message/inline-message.js +17 -0
  73. package/components/inline-message/inline-message.test.js +203 -0
  74. package/components/inline-message/inline-message.yaml +205 -0
  75. package/components/input/input.css +1 -1
  76. package/components/input/input.js +1 -1
  77. package/components/input/input.yaml +5 -4
  78. package/components/inspector/inspector.js +1 -1
  79. package/components/integration-card/integration-card.js +1 -1
  80. package/components/kbd/kbd.js +1 -1
  81. package/components/link/link.js +1 -1
  82. package/components/list/list-item.yaml +2 -2
  83. package/components/list/list.js +1 -1
  84. package/components/list-window/list-window.js +1 -1
  85. package/components/loading-overlay/loading-overlay.a2ui.json +176 -0
  86. package/components/loading-overlay/loading-overlay.class.js +203 -0
  87. package/components/loading-overlay/loading-overlay.css +81 -0
  88. package/components/loading-overlay/loading-overlay.d.ts +24 -0
  89. package/components/loading-overlay/loading-overlay.examples.md +50 -0
  90. package/components/loading-overlay/loading-overlay.js +17 -0
  91. package/components/loading-overlay/loading-overlay.test.js +257 -0
  92. package/components/loading-overlay/loading-overlay.yaml +260 -0
  93. package/components/menu/menu-divider.yaml +1 -1
  94. package/components/menu/menu-item.yaml +1 -1
  95. package/components/menu/menu.a2ui.json +3 -0
  96. package/components/menu/menu.js +1 -1
  97. package/components/menu/menu.yaml +7 -0
  98. package/components/modal/{class.js → modal.class.js} +12 -1
  99. package/components/modal/modal.css +11 -1
  100. package/components/modal/modal.js +1 -1
  101. package/components/nav/nav.js +1 -1
  102. package/components/nav-group/nav-group.js +1 -1
  103. package/components/nav-item/nav-item.js +1 -1
  104. package/components/noodles/noodles.js +1 -1
  105. package/components/option-card/option-card.js +1 -1
  106. package/components/otp-input/otp-input.js +1 -1
  107. package/components/page/page.js +1 -1
  108. package/components/pagination/pagination.js +1 -1
  109. package/components/pane/pane.js +1 -1
  110. package/components/pipeline-status/pipeline-status.js +1 -1
  111. package/components/popover/popover.a2ui.json +8 -1
  112. package/components/popover/popover.js +1 -1
  113. package/components/popover/popover.yaml +14 -1
  114. package/components/progress/progress.js +1 -1
  115. package/components/progress-row/progress-row.js +1 -1
  116. package/components/radio/radio.js +1 -1
  117. package/components/range/range.js +1 -1
  118. package/components/rating/rating.js +1 -1
  119. package/components/richtext/richtext.js +1 -1
  120. package/components/row/row.js +1 -1
  121. package/components/search/search.js +1 -1
  122. package/components/segment/segment.js +1 -1
  123. package/components/segmented/segmented.js +1 -1
  124. package/components/select/select.a2ui.json +58 -4
  125. package/components/select/{class.js → select.class.js} +415 -6
  126. package/components/select/select.css +158 -0
  127. package/components/select/select.d.ts +31 -1
  128. package/components/select/select.js +1 -1
  129. package/components/select/select.test.js +202 -0
  130. package/components/select/select.yaml +126 -5
  131. package/components/skeleton/skeleton.js +1 -1
  132. package/components/slider/slider.js +1 -1
  133. package/components/spinner/spinner.a2ui.json +3 -2
  134. package/components/spinner/{class.js → spinner.class.js} +33 -3
  135. package/components/spinner/spinner.css +91 -35
  136. package/components/spinner/spinner.d.ts +2 -2
  137. package/components/spinner/spinner.js +1 -1
  138. package/components/spinner/spinner.test.js +49 -11
  139. package/components/spinner/spinner.yaml +9 -1
  140. package/components/stack/stack.js +1 -1
  141. package/components/step-progress/step-progress.js +1 -1
  142. package/components/stepper/stepper-item.yaml +1 -1
  143. package/components/stepper/stepper.js +1 -1
  144. package/components/stream/stream.js +1 -1
  145. package/components/swatch/swatch.js +1 -1
  146. package/components/swiper/swiper.js +1 -1
  147. package/components/switch/switch.js +1 -1
  148. package/components/table/table.css +1 -1
  149. package/components/table/table.js +1 -1
  150. package/components/table-toolbar/{class.js → table-toolbar.class.js} +1 -1
  151. package/components/table-toolbar/table-toolbar.js +1 -1
  152. package/components/tabs/tab.yaml +2 -2
  153. package/components/tabs/tabs.js +1 -1
  154. package/components/tag/tag.js +1 -1
  155. package/components/tags-input/tags-input.a2ui.json +337 -0
  156. package/components/tags-input/tags-input.class.js +776 -0
  157. package/components/tags-input/tags-input.css +201 -0
  158. package/components/tags-input/tags-input.d.ts +120 -0
  159. package/components/tags-input/tags-input.examples.md +92 -0
  160. package/components/tags-input/tags-input.js +17 -0
  161. package/components/tags-input/tags-input.test.js +368 -0
  162. package/components/tags-input/tags-input.yaml +367 -0
  163. package/components/text/text.js +1 -1
  164. package/components/textarea/textarea.a2ui.json +1 -1
  165. package/components/textarea/textarea.js +1 -1
  166. package/components/textarea/textarea.yaml +11 -8
  167. package/components/time-picker/time-picker.js +1 -1
  168. package/components/timeline/timeline-item.yaml +2 -2
  169. package/components/timeline/{class.js → timeline.class.js} +1 -1
  170. package/components/timeline/timeline.js +1 -1
  171. package/components/toast/toast.js +1 -1
  172. package/components/toggle-group/toggle-group.js +1 -1
  173. package/components/toggle-group/toggle-option.yaml +1 -1
  174. package/components/toggle-scheme/toggle-scheme.js +1 -1
  175. package/components/toolbar/toolbar-group.yaml +1 -1
  176. package/components/toolbar/toolbar.js +1 -1
  177. package/components/tooltip/tooltip.js +1 -1
  178. package/components/tree/tree-item.yaml +1 -1
  179. package/components/tree/tree.js +1 -1
  180. package/components/upload/upload.js +1 -1
  181. package/dist/web-components.min.css +1 -1
  182. package/dist/web-components.min.js +111 -90
  183. package/package.json +3 -3
  184. package/styles/components.css +3 -0
  185. /package/components/accordion/{class.js → accordion.class.js} +0 -0
  186. /package/components/action-list/{class.js → action-list.class.js} +0 -0
  187. /package/components/agent-feedback-bar/{class.js → agent-feedback-bar.class.js} +0 -0
  188. /package/components/agent-questions/{class.js → agent-questions.class.js} +0 -0
  189. /package/components/agent-reasoning/{class.js → agent-reasoning.class.js} +0 -0
  190. /package/components/agent-suggestions/{class.js → agent-suggestions.class.js} +0 -0
  191. /package/components/avatar/{class.js → avatar.class.js} +0 -0
  192. /package/components/badge/{class.js → badge.class.js} +0 -0
  193. /package/components/block/{class.js → block.class.js} +0 -0
  194. /package/components/breadcrumb/{class.js → breadcrumb.class.js} +0 -0
  195. /package/components/button/{class.js → button.class.js} +0 -0
  196. /package/components/calendar-picker/{class.js → calendar-picker.class.js} +0 -0
  197. /package/components/card/{class.js → card.class.js} +0 -0
  198. /package/components/chart/{class.js → chart.class.js} +0 -0
  199. /package/components/chart-legend/{class.js → chart-legend.class.js} +0 -0
  200. /package/components/chat-thread/{class.js → chat-thread.class.js} +0 -0
  201. /package/components/check/{class.js → check.class.js} +0 -0
  202. /package/components/code/{class.js → code.class.js} +0 -0
  203. /package/components/col/{class.js → col.class.js} +0 -0
  204. /package/components/color-input/{class.js → color-input.class.js} +0 -0
  205. /package/components/color-picker/{class.js → color-picker.class.js} +0 -0
  206. /package/components/combobox/{class.js → combobox.class.js} +0 -0
  207. /package/components/command/{class.js → command.class.js} +0 -0
  208. /package/components/demo-toggle/{class.js → demo-toggle.class.js} +0 -0
  209. /package/components/description-list/{class.js → description-list.class.js} +0 -0
  210. /package/components/divider/{class.js → divider.class.js} +0 -0
  211. /package/components/drawer/{class.js → drawer.class.js} +0 -0
  212. /package/components/embed/{class.js → embed.class.js} +0 -0
  213. /package/components/empty-state/{class.js → empty-state.class.js} +0 -0
  214. /package/components/feed/{class.js → feed.class.js} +0 -0
  215. /package/components/field/{class.js → field.class.js} +0 -0
  216. /package/components/fields/{class.js → fields.class.js} +0 -0
  217. /package/components/grid/{class.js → grid.class.js} +0 -0
  218. /package/components/heatmap/{class.js → heatmap.class.js} +0 -0
  219. /package/components/icon/{class.js → icon.class.js} +0 -0
  220. /package/components/image/{class.js → image.class.js} +0 -0
  221. /package/components/input/{class.js → input.class.js} +0 -0
  222. /package/components/inspector/{class.js → inspector.class.js} +0 -0
  223. /package/components/integration-card/{class.js → integration-card.class.js} +0 -0
  224. /package/components/kbd/{class.js → kbd.class.js} +0 -0
  225. /package/components/link/{class.js → link.class.js} +0 -0
  226. /package/components/list/{class.js → list.class.js} +0 -0
  227. /package/components/list-window/{class.js → list-window.class.js} +0 -0
  228. /package/components/menu/{class.js → menu.class.js} +0 -0
  229. /package/components/nav/{class.js → nav.class.js} +0 -0
  230. /package/components/nav-group/{class.js → nav-group.class.js} +0 -0
  231. /package/components/nav-item/{class.js → nav-item.class.js} +0 -0
  232. /package/components/noodles/{class.js → noodles.class.js} +0 -0
  233. /package/components/option-card/{class.js → option-card.class.js} +0 -0
  234. /package/components/otp-input/{class.js → otp-input.class.js} +0 -0
  235. /package/components/page/{class.js → page.class.js} +0 -0
  236. /package/components/pagination/{class.js → pagination.class.js} +0 -0
  237. /package/components/pane/{class.js → pane.class.js} +0 -0
  238. /package/components/pipeline-status/{class.js → pipeline-status.class.js} +0 -0
  239. /package/components/popover/{class.js → popover.class.js} +0 -0
  240. /package/components/progress/{class.js → progress.class.js} +0 -0
  241. /package/components/progress-row/{class.js → progress-row.class.js} +0 -0
  242. /package/components/radio/{class.js → radio.class.js} +0 -0
  243. /package/components/range/{class.js → range.class.js} +0 -0
  244. /package/components/rating/{class.js → rating.class.js} +0 -0
  245. /package/components/richtext/{class.js → richtext.class.js} +0 -0
  246. /package/components/row/{class.js → row.class.js} +0 -0
  247. /package/components/search/{class.js → search.class.js} +0 -0
  248. /package/components/segment/{class.js → segment.class.js} +0 -0
  249. /package/components/segmented/{class.js → segmented.class.js} +0 -0
  250. /package/components/skeleton/{class.js → skeleton.class.js} +0 -0
  251. /package/components/slider/{class.js → slider.class.js} +0 -0
  252. /package/components/stack/{class.js → stack.class.js} +0 -0
  253. /package/components/step-progress/{class.js → step-progress.class.js} +0 -0
  254. /package/components/stepper/{class.js → stepper.class.js} +0 -0
  255. /package/components/stream/{class.js → stream.class.js} +0 -0
  256. /package/components/swatch/{class.js → swatch.class.js} +0 -0
  257. /package/components/swiper/{class.js → swiper.class.js} +0 -0
  258. /package/components/switch/{class.js → switch.class.js} +0 -0
  259. /package/components/table/{class.js → table.class.js} +0 -0
  260. /package/components/tabs/{class.js → tabs.class.js} +0 -0
  261. /package/components/tag/{class.js → tag.class.js} +0 -0
  262. /package/components/text/{class.js → text.class.js} +0 -0
  263. /package/components/textarea/{class.js → textarea.class.js} +0 -0
  264. /package/components/time-picker/{class.js → time-picker.class.js} +0 -0
  265. /package/components/toast/{class.js → toast.class.js} +0 -0
  266. /package/components/toggle-group/{class.js → toggle-group.class.js} +0 -0
  267. /package/components/toggle-scheme/{class.js → toggle-scheme.class.js} +0 -0
  268. /package/components/toolbar/{class.js → toolbar.class.js} +0 -0
  269. /package/components/tooltip/{class.js → tooltip.class.js} +0 -0
  270. /package/components/tree/{class.js → tree.class.js} +0 -0
  271. /package/components/upload/{class.js → upload.class.js} +0 -0
@@ -0,0 +1,260 @@
1
+ # Hand-authored per SPEC-034 (docs/specs/implementation-ready/SPEC-034-loading-overlay.md).
2
+ # Edit this file; run `npm run build:components` to regenerate loading-overlay.a2ui.json.
3
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
4
+ name: UILoadingOverlay
5
+ tag: loading-overlay-ui
6
+ status: stable
7
+ component: LoadingOverlay
8
+ category: feedback
9
+ version: 1
10
+ description: >-
11
+ Container-scoped busy overlay. Covers a positioned parent region with a
12
+ centered spinner (auto-stamped) or slotted indicator (skeleton-ui,
13
+ progress-ui, custom) while async work is in flight. Wires aria-busy
14
+ onto the parent on connect; applies a [delay] grace window to avoid
15
+ flash on fast loads. For viewport-scoped / route loaders use a
16
+ dedicated route-loader pattern; for submit-button busy use
17
+ <button-ui loading>.
18
+ props:
19
+ active:
20
+ description: When set, overlay is visible and the parent container is marked aria-busy. Toggle from consumer code; default hidden.
21
+ type: boolean
22
+ default: false
23
+ reflect: true
24
+ dynamic: true
25
+ delay:
26
+ description: Suppress the overlay until this many ms elapse. Prevents flash on fast loads. Default 200ms.
27
+ type: number
28
+ default: 200
29
+ reflect: true
30
+ dynamic: true
31
+ label:
32
+ description: Accessible operation name used by the host aria-label and forwarded to the auto-stamped spinner.
33
+ type: string
34
+ default: Loading…
35
+ reflect: true
36
+ dynamic: true
37
+ variant:
38
+ description: Backdrop treatment — default (muted scrim), transparent (no backdrop fill — useful with full-area skeleton indicators), blur (light scrim with backdrop-filter blur).
39
+ type: string
40
+ default: default
41
+ enum:
42
+ - default
43
+ - transparent
44
+ - blur
45
+ reflect: true
46
+ dynamic: true
47
+ events: {}
48
+ slots:
49
+ default:
50
+ description: Busy indicator content — <spinner-ui>, <skeleton-ui>, <progress-ui>, or custom. If empty, a centered <spinner-ui size="lg"> is auto-stamped.
51
+ states:
52
+ - name: idle
53
+ description: Default, hidden. Parent interactive.
54
+ - name: active
55
+ description: Overlay visible; parent has aria-busy="true".
56
+ attribute: active
57
+ traits: []
58
+ tokens:
59
+ --loading-overlay-bg:
60
+ description: Backdrop fill color. Default uses the generic neutral scrim token.
61
+ default: var(--a-scrim-default)
62
+ --loading-overlay-radius:
63
+ description: Backdrop corner radius. Matches the parent surface by default.
64
+ default: var(--a-radius-md)
65
+ --loading-overlay-z:
66
+ description: Stacking order. Sits above sibling content, below modal-ui (which uses ::backdrop on top-layer dialog).
67
+ default: '50'
68
+ --loading-overlay-duration:
69
+ description: Fade in / fade out duration.
70
+ default: var(--a-duration)
71
+ --loading-overlay-easing:
72
+ description: Fade easing curve.
73
+ default: var(--a-easing-out)
74
+ --loading-overlay-gap:
75
+ description: Vertical gap between the indicator and any sibling content (e.g. label, skeleton stack).
76
+ default: var(--a-space-3)
77
+ a2ui:
78
+ rules:
79
+ - >-
80
+ <LoadingOverlay> MUST be placed inside a sized container with
81
+ content (Card, Section, Table body, Chart). It absolutely positions
82
+ against the nearest positioned ancestor. The parent's CSS must
83
+ include `position: relative` (or any non-static positioning) — the
84
+ component does not mutate parent layout styles.
85
+ - >-
86
+ Toggle <LoadingOverlay active> from consumer code while async work
87
+ is in flight. The overlay applies aria-busy="true" to its parent
88
+ while active; on dismiss, both inert and aria-busy are released.
89
+ - >-
90
+ The [delay] grace window (default 200ms) suppresses paint on
91
+ fast-resolving loads. For server-rendered "definitely-slow" states
92
+ (>1s known wait) consider [delay="0"] for immediate feedback.
93
+ - >-
94
+ Do NOT use as a page-level / viewport loader — use a dedicated
95
+ route-loader pattern. <LoadingOverlay> is container-scoped.
96
+ - >-
97
+ Do NOT nest <LoadingOverlay> inside <Modal> or <Drawer> — those
98
+ primitives own their own busy state. When they support it, pass
99
+ [loading] to those directly.
100
+ - >-
101
+ Do NOT use <LoadingOverlay> to disable a form during submit — use
102
+ <Button type="submit" loading> for the submit affordance.
103
+ - >-
104
+ The default slot accepts any busy indicator. When empty, a
105
+ centered <Spinner size="lg"> is auto-stamped. Slot a <Skeleton>
106
+ stack for placeholder-shaped loading; slot <Progress value=…> when
107
+ the wait is determinate.
108
+ anti_patterns:
109
+ - wrong: |
110
+ {"component": "Page", "children": [
111
+ {"component": "LoadingOverlay", "active": true}
112
+ ]}
113
+ why: |
114
+ LoadingOverlay is container-scoped. Attaching it directly to Page
115
+ covers the entire viewport but lacks the route-loader's wiring
116
+ (skeleton routing, route-level animation). Use the route loader.
117
+ fix: |
118
+ {"component": "Card", "children": [
119
+ {"component": "LoadingOverlay", "active": true},
120
+ {"component": "Table", "data-stream-src": "..."}
121
+ ]}
122
+ - wrong: |
123
+ {"component": "Modal", "open": true, "children": [
124
+ {"component": "LoadingOverlay", "active": true}
125
+ ]}
126
+ why: |
127
+ Modal owns its own busy state and focus trap; nesting a
128
+ LoadingOverlay introduces two competing inert toggles.
129
+ fix: |
130
+ {"component": "Modal", "open": true, "loading": true}
131
+ - wrong: |
132
+ {"component": "Form", "children": [
133
+ {"component": "Button", "text": "Submit", "type": "submit"},
134
+ {"component": "LoadingOverlay", "active": true}
135
+ ]}
136
+ why: |
137
+ A form-submit affordance belongs on the button itself, not as an
138
+ overlay over the entire form region. Use Button[loading].
139
+ fix: |
140
+ {"component": "Form", "children": [
141
+ {"component": "Button", "text": "Submitting", "type": "submit", "loading": true, "disabled": true}
142
+ ]}
143
+ examples:
144
+ - name: card-with-loading-table
145
+ description: Card containing a table that loads on mount; the overlay covers the card's body while data streams.
146
+ a2ui: >-
147
+ [
148
+ {
149
+ "id": "card",
150
+ "component": "Card",
151
+ "children": ["sec"]
152
+ },
153
+ {
154
+ "id": "sec",
155
+ "component": "Section",
156
+ "children": ["overlay", "table"]
157
+ },
158
+ {
159
+ "id": "overlay",
160
+ "component": "LoadingOverlay",
161
+ "active": true,
162
+ "label": "Loading orders…"
163
+ },
164
+ {
165
+ "id": "table",
166
+ "component": "Table",
167
+ "data-stream-src": "/api/orders"
168
+ }
169
+ ]
170
+ - name: skeleton-overlay
171
+ description: Skeleton-shaped placeholder overlay using the transparent variant — slot a stack of <Skeleton> rows.
172
+ a2ui: >-
173
+ [
174
+ {
175
+ "id": "ov",
176
+ "component": "LoadingOverlay",
177
+ "active": true,
178
+ "variant": "transparent",
179
+ "label": "Loading content…",
180
+ "children": ["sk-stack"]
181
+ },
182
+ {
183
+ "id": "sk-stack",
184
+ "component": "Column",
185
+ "gap": "2",
186
+ "children": ["sk1", "sk2", "sk3"]
187
+ },
188
+ {
189
+ "id": "sk1",
190
+ "component": "Skeleton",
191
+ "width": "100%",
192
+ "height": "1rem"
193
+ },
194
+ {
195
+ "id": "sk2",
196
+ "component": "Skeleton",
197
+ "width": "80%",
198
+ "height": "1rem"
199
+ },
200
+ {
201
+ "id": "sk3",
202
+ "component": "Skeleton",
203
+ "width": "60%",
204
+ "height": "1rem"
205
+ }
206
+ ]
207
+ - name: fast-load-no-flash
208
+ description: Overlay with the default 200ms grace window. If the underlying load resolves in less than 200ms, the overlay never paints.
209
+ a2ui: >-
210
+ [
211
+ {
212
+ "id": "ov",
213
+ "component": "LoadingOverlay",
214
+ "active": true,
215
+ "delay": 200,
216
+ "label": "Loading"
217
+ }
218
+ ]
219
+ keywords:
220
+ - loading
221
+ - overlay
222
+ - busy
223
+ - spinner
224
+ - skeleton
225
+ - placeholder
226
+ - feedback
227
+ - progress
228
+ - indicator
229
+ - wait
230
+ synonyms:
231
+ loading:
232
+ - loading
233
+ - overlay
234
+ - busy
235
+ - spinner
236
+ - skeleton
237
+ overlay:
238
+ - loading
239
+ - overlay
240
+ - busy
241
+ busy:
242
+ - loading
243
+ - overlay
244
+ - busy
245
+ - spinner
246
+ spinner:
247
+ - loading
248
+ - overlay
249
+ - spinner
250
+ loader:
251
+ - loading
252
+ - overlay
253
+ - spinner
254
+ related:
255
+ - Spinner
256
+ - Skeleton
257
+ - Progress
258
+ - Card
259
+ - Table
260
+ - Modal
@@ -1,7 +1,7 @@
1
1
  # Edit this file; run `npm run build:components` to regenerate a2ui.json.
2
2
  #
3
3
  # §228 (v0.5.9): authored to close the §229 baseline class-export-undeclared
4
- # drift for UIMenuDivider. Ships as a sibling class in menu/class.js +
4
+ # drift for UIMenuDivider. Ships as a sibling class in menu/menu.class.js +
5
5
  # is registered alongside UIMenu + UIMenuItem.
6
6
 
7
7
  # Child component of <menu-ui>. Surface only inside that parent.
@@ -1,7 +1,7 @@
1
1
  # Edit this file; run `npm run build:components` to regenerate a2ui.json.
2
2
  #
3
3
  # §228 (v0.5.9): authored to close the §229 baseline class-export-undeclared
4
- # drift for UIMenuItem. The item ships as a sibling class in menu/class.js
4
+ # drift for UIMenuItem. The item ships as a sibling class in menu/menu.class.js
5
5
  # + is registered alongside UIMenu + UIMenuDivider.
6
6
 
7
7
  # Child component of <menu-ui>. Surface only inside that parent.
@@ -91,6 +91,9 @@
91
91
  "slots": {
92
92
  "default": {
93
93
  "description": "Menu items with role=\"menuitem\" and optional <hr> dividers"
94
+ },
95
+ "trigger": {
96
+ "description": "Required. Focusable element that opens the menu when activated. Exactly one child must have slot=\"trigger\" — typically <button-ui>, but any focusable element works. Without it the menu cannot open via keyboard or pointer. Lives in light DOM; the items are hoisted to a top-layer popover on open."
94
97
  }
95
98
  },
96
99
  "states": [
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIMenu, UIMenuItem, UIMenuDivider } from './class.js';
13
+ import { UIMenu, UIMenuItem, UIMenuDivider } from './menu.class.js';
14
14
 
15
15
  defineIfFree('menu-ui', UIMenu);
16
16
  defineIfFree('menu-item-ui', UIMenuItem);
@@ -42,6 +42,13 @@ events:
42
42
  type: string
43
43
  description: Menu item text.
44
44
  slots:
45
+ trigger:
46
+ description: >-
47
+ Required. Focusable element that opens the menu when activated.
48
+ Exactly one child must have slot="trigger" — typically <button-ui>,
49
+ but any focusable element works. Without it the menu cannot open
50
+ via keyboard or pointer. Lives in light DOM; the items are
51
+ hoisted to a top-layer popover on open.
45
52
  default:
46
53
  description: Menu items with role="menuitem" and optional <hr> dividers
47
54
  states:
@@ -142,7 +142,18 @@ export class UIModal extends UIElement {
142
142
 
143
143
  const header = this.ensure('header');
144
144
  if (header.parentElement !== panel) panel.prepend(header);
145
- header.setAttribute('text', this.text);
145
+ // Only set `text=` when actually present — the CSS rule
146
+ // `:scope [slot="header"][text]:not([text=""])::before { content: attr(text); flex: 1 }`
147
+ // generates a flex:1 pseudo-element. Setting `text=""` unconditionally
148
+ // creates a phantom flex slot that pushes slotted title content
149
+ // (e.g., confirm-dialog-ui's stamped <text-ui slot="heading">) to the
150
+ // trailing edge of the header row. Defense-in-depth alongside the
151
+ // CSS gate.
152
+ if (this.text) {
153
+ header.setAttribute('text', this.text);
154
+ } else {
155
+ header.removeAttribute('text');
156
+ }
146
157
 
147
158
  if (!this.permanent) {
148
159
  const close = this.ensure('close');
@@ -116,7 +116,17 @@
116
116
  color: var(--modal-header-fg, var(--modal-header-fg-default));
117
117
  flex-shrink: 0;
118
118
  }
119
- :scope [slot="header"]::before {
119
+ /* `[text]` gate — same drift class as button-ui / tag-ui / badge-ui /
120
+ segment-ui (Apr-May 2026 phantom-gap arc). Without the `[text]`
121
+ attribute selector, an empty `attr(text)` still generates a
122
+ pseudo-element with `flex: 1` — it claims the row's free space and
123
+ pushes any slotted title text-ui / icon-ui to the trailing edge,
124
+ leaving only the close button on the right looking like the title.
125
+ Gated on `[text]:not([text=""])` because modal/modal.class.js sets
126
+ `header.setAttribute('text', this.text)` unconditionally; the
127
+ defensive selector + class skip (see modal/modal.class.js render())
128
+ close the same trap from both directions. */
129
+ :scope [slot="header"][text]:not([text=""])::before {
120
130
  content: attr(text);
121
131
  flex: 1;
122
132
  }
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIModal } from './class.js';
13
+ import { UIModal } from './modal.class.js';
14
14
 
15
15
  defineIfFree('modal-ui', UIModal);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UINav } from './class.js';
13
+ import { UINav } from './nav.class.js';
14
14
 
15
15
  defineIfFree('nav-ui', UINav);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UINavGroup } from './class.js';
13
+ import { UINavGroup } from './nav-group.class.js';
14
14
 
15
15
  defineIfFree('nav-group-ui', UINavGroup);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UINavItem } from './class.js';
13
+ import { UINavItem } from './nav-item.class.js';
14
14
 
15
15
  defineIfFree('nav-item-ui', UINavItem);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UINoodles } from './class.js';
13
+ import { UINoodles } from './noodles.class.js';
14
14
 
15
15
  defineIfFree('noodles-ui', UINoodles);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIOptionCard } from './class.js';
13
+ import { UIOptionCard } from './option-card.class.js';
14
14
 
15
15
  defineIfFree('option-card-ui', UIOptionCard);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIOtpInput } from './class.js';
13
+ import { UIOtpInput } from './otp-input.class.js';
14
14
 
15
15
  defineIfFree('otp-input-ui', UIOtpInput);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIPage } from './class.js';
13
+ import { UIPage } from './page.class.js';
14
14
 
15
15
  defineIfFree('page-ui', UIPage);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIPagination } from './class.js';
13
+ import { UIPagination } from './pagination.class.js';
14
14
 
15
15
  defineIfFree('pagination-ui', UIPagination);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIPane } from './class.js';
13
+ import { UIPane } from './pane.class.js';
14
14
 
15
15
  defineIfFree('pane-ui', UIPane);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIPipelineStatus } from './class.js';
13
+ import { UIPipelineStatus } from './pipeline-status.class.js';
14
14
 
15
15
  defineIfFree('pipeline-status-ui', UIPipelineStatus);
16
16
 
@@ -91,7 +91,14 @@
91
91
  "button",
92
92
  "divider"
93
93
  ],
94
- "slots": {},
94
+ "slots": {
95
+ "content": {
96
+ "description": "Popover body — any interactive content. Hoisted to the top-layer via :popover-open when shown. Positioned via the Popover API + CSS Anchor Positioning per [placement] / [gap]; no manual positioning required."
97
+ },
98
+ "trigger": {
99
+ "description": "Focusable element that opens the popover when activated. Typically <button-ui>, but any focusable element works (button, a link with href). MUST be focusable for keyboard accessibility — bare <span> or <div> children will not respond to keyboard activation. Positioned at the anchor point per [placement]."
100
+ }
101
+ },
95
102
  "states": [
96
103
  {
97
104
  "description": "Default, ready for interaction.",
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIPopover } from './class.js';
13
+ import { UIPopover } from './popover.class.js';
14
14
 
15
15
  defineIfFree('popover-ui', UIPopover);
16
16
 
@@ -40,7 +40,20 @@ props:
40
40
  - hover
41
41
  - manual
42
42
  events: {}
43
- slots: {}
43
+ slots:
44
+ trigger:
45
+ description: >-
46
+ Focusable element that opens the popover when activated.
47
+ Typically <button-ui>, but any focusable element works (button,
48
+ a link with href). MUST be focusable for keyboard accessibility —
49
+ bare <span> or <div> children will not respond to keyboard
50
+ activation. Positioned at the anchor point per [placement].
51
+ content:
52
+ description: >-
53
+ Popover body — any interactive content. Hoisted to the top-layer
54
+ via :popover-open when shown. Positioned via the Popover API +
55
+ CSS Anchor Positioning per [placement] / [gap]; no manual
56
+ positioning required.
44
57
  states:
45
58
  - name: idle
46
59
  description: Default, ready for interaction.
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIProgress } from './class.js';
13
+ import { UIProgress } from './progress.class.js';
14
14
 
15
15
  defineIfFree('progress-ui', UIProgress);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIProgressRow } from './class.js';
13
+ import { UIProgressRow } from './progress-row.class.js';
14
14
 
15
15
  defineIfFree('progress-row-ui', UIProgressRow);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIRadio } from './class.js';
13
+ import { UIRadio } from './radio.class.js';
14
14
 
15
15
  defineIfFree('radio-ui', UIRadio);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIRange } from './class.js';
13
+ import { UIRange } from './range.class.js';
14
14
 
15
15
  defineIfFree('range-ui', UIRange);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIRating } from './class.js';
13
+ import { UIRating } from './rating.class.js';
14
14
 
15
15
  defineIfFree('rating-ui', UIRating);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIRichText } from './class.js';
13
+ import { UIRichText } from './richtext.class.js';
14
14
 
15
15
  defineIfFree('richtext-ui', UIRichText);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UIRow } from './class.js';
13
+ import { UIRow } from './row.class.js';
14
14
 
15
15
  defineIfFree('row-ui', UIRow);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UISearch } from './class.js';
13
+ import { UISearch } from './search.class.js';
14
14
 
15
15
  defineIfFree('search-ui', UISearch);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UISegment } from './class.js';
13
+ import { UISegment } from './segment.class.js';
14
14
 
15
15
  defineIfFree('segment-ui', UISegment);
16
16
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { defineIfFree } from '../../core/register.js';
13
- import { UISegmented } from './class.js';
13
+ import { UISegmented } from './segmented.class.js';
14
14
 
15
15
  defineIfFree('segmented-ui', UISegmented);
16
16