@adia-ai/web-components 0.0.29 → 0.0.34

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 (295) hide show
  1. package/components/accordion/accordion.a2ui.json +1 -1
  2. package/components/accordion/accordion.js +6 -6
  3. package/components/accordion/accordion.yaml +1 -1
  4. package/components/action-list/action-list.a2ui.json +1 -1
  5. package/components/action-list/action-list.js +6 -6
  6. package/components/action-list/action-list.yaml +1 -1
  7. package/components/agent-artifact/agent-artifact.a2ui.json +1 -1
  8. package/components/agent-artifact/agent-artifact.js +4 -4
  9. package/components/agent-artifact/agent-artifact.yaml +1 -1
  10. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +1 -1
  11. package/components/agent-feedback-bar/agent-feedback-bar.js +4 -4
  12. package/components/agent-feedback-bar/agent-feedback-bar.yaml +1 -1
  13. package/components/agent-questions/agent-questions.a2ui.json +1 -1
  14. package/components/agent-questions/agent-questions.js +4 -4
  15. package/components/agent-questions/agent-questions.yaml +1 -1
  16. package/components/agent-reasoning/agent-reasoning.a2ui.json +3 -3
  17. package/components/agent-reasoning/agent-reasoning.js +4 -4
  18. package/components/agent-reasoning/agent-reasoning.yaml +3 -3
  19. package/components/agent-suggestions/agent-suggestions.a2ui.json +1 -1
  20. package/components/agent-suggestions/agent-suggestions.js +4 -4
  21. package/components/agent-suggestions/agent-suggestions.yaml +1 -1
  22. package/components/agent-trace/agent-trace.a2ui.json +1 -1
  23. package/components/agent-trace/agent-trace.js +4 -4
  24. package/components/agent-trace/agent-trace.yaml +1 -1
  25. package/components/alert/alert.a2ui.json +1 -1
  26. package/components/alert/alert.js +4 -4
  27. package/components/alert/alert.yaml +1 -1
  28. package/components/aside/aside.a2ui.json +1 -1
  29. package/components/aside/aside.yaml +1 -1
  30. package/components/avatar/avatar.a2ui.json +1 -1
  31. package/components/avatar/avatar.js +8 -8
  32. package/components/avatar/avatar.yaml +1 -1
  33. package/components/badge/badge.a2ui.json +1 -1
  34. package/components/badge/badge.js +4 -4
  35. package/components/badge/badge.yaml +1 -1
  36. package/components/block/block.a2ui.json +1 -1
  37. package/components/block/block.js +4 -4
  38. package/components/block/block.yaml +1 -1
  39. package/components/breadcrumb/breadcrumb.a2ui.json +1 -1
  40. package/components/breadcrumb/breadcrumb.js +4 -4
  41. package/components/breadcrumb/breadcrumb.yaml +1 -1
  42. package/components/button/button.a2ui.json +1 -1
  43. package/components/button/button.js +4 -4
  44. package/components/button/button.yaml +1 -1
  45. package/components/calendar-picker/calendar-picker.a2ui.json +1 -1
  46. package/components/calendar-picker/calendar-picker.js +6 -6
  47. package/components/calendar-picker/calendar-picker.yaml +1 -1
  48. package/components/canvas/canvas.a2ui.json +1 -1
  49. package/components/canvas/canvas.js +4 -4
  50. package/components/canvas/canvas.yaml +1 -1
  51. package/components/card/card.a2ui.json +1 -1
  52. package/components/card/card.js +4 -4
  53. package/components/card/card.yaml +1 -1
  54. package/components/chart/chart.a2ui.json +1 -1
  55. package/components/chart/chart.js +5 -5
  56. package/components/chart/chart.yaml +1 -1
  57. package/components/chart-legend/chart-legend.a2ui.json +1 -1
  58. package/components/chart-legend/chart-legend.js +7 -7
  59. package/components/chart-legend/chart-legend.yaml +1 -1
  60. package/components/{chat → chat-thread}/chat-input.js +5 -5
  61. package/components/{chat/chat.a2ui.json → chat-thread/chat-thread.a2ui.json} +6 -6
  62. package/components/{chat/chat.css → chat-thread/chat-thread.css} +2 -2
  63. package/components/{chat/chat.js → chat-thread/chat-thread.js} +7 -7
  64. package/components/{chat/chat.yaml → chat-thread/chat-thread.yaml} +4 -4
  65. package/components/check/check.a2ui.json +1 -1
  66. package/components/check/check.js +5 -5
  67. package/components/check/check.yaml +1 -1
  68. package/components/code/code.a2ui.json +1 -1
  69. package/components/code/code.js +4 -4
  70. package/components/code/code.yaml +1 -1
  71. package/components/col/col.a2ui.json +1 -1
  72. package/components/col/col.js +4 -4
  73. package/components/col/col.yaml +1 -1
  74. package/components/color-picker/color-picker.a2ui.json +1 -1
  75. package/components/color-picker/color-picker.js +6 -6
  76. package/components/color-picker/color-picker.yaml +1 -1
  77. package/components/command/command.a2ui.json +1 -1
  78. package/components/command/command.js +5 -5
  79. package/components/command/command.yaml +1 -1
  80. package/components/description-list/description-list.a2ui.json +1 -1
  81. package/components/description-list/description-list.js +4 -4
  82. package/components/description-list/description-list.yaml +1 -1
  83. package/components/divider/divider.a2ui.json +1 -1
  84. package/components/divider/divider.js +4 -4
  85. package/components/divider/divider.yaml +1 -1
  86. package/components/drawer/drawer.a2ui.json +1 -1
  87. package/components/drawer/drawer.js +4 -4
  88. package/components/drawer/drawer.yaml +1 -1
  89. package/components/embed/embed.a2ui.json +1 -1
  90. package/components/embed/embed.js +4 -4
  91. package/components/embed/embed.yaml +1 -1
  92. package/components/empty-state/empty-state.a2ui.json +1 -1
  93. package/components/empty-state/empty-state.js +4 -4
  94. package/components/empty-state/empty-state.yaml +1 -1
  95. package/components/feed/feed-item.yaml +2 -2
  96. package/components/feed/feed.a2ui.json +2 -2
  97. package/components/feed/feed.css +12 -3
  98. package/components/feed/feed.js +22 -22
  99. package/components/feed/feed.yaml +2 -2
  100. package/components/field/field.a2ui.json +1 -1
  101. package/components/field/field.js +10 -10
  102. package/components/field/field.yaml +2 -2
  103. package/components/footer/footer.a2ui.json +1 -1
  104. package/components/footer/footer.yaml +1 -1
  105. package/components/grid/grid.a2ui.json +1 -1
  106. package/components/grid/grid.js +4 -4
  107. package/components/grid/grid.yaml +1 -1
  108. package/components/header/header.a2ui.json +1 -1
  109. package/components/header/header.yaml +1 -1
  110. package/components/heatmap/heatmap.a2ui.json +1 -1
  111. package/components/heatmap/heatmap.js +4 -4
  112. package/components/heatmap/heatmap.yaml +1 -1
  113. package/components/icon/icon.a2ui.json +1 -1
  114. package/components/icon/icon.js +4 -4
  115. package/components/icon/icon.yaml +1 -1
  116. package/components/image/image.a2ui.json +1 -1
  117. package/components/image/image.js +4 -4
  118. package/components/image/image.yaml +1 -1
  119. package/components/index.js +89 -85
  120. package/components/input/input.a2ui.json +1 -1
  121. package/components/input/input.js +7 -7
  122. package/components/input/input.yaml +1 -1
  123. package/components/inspector/inspector.a2ui.json +1 -1
  124. package/components/inspector/inspector.js +4 -4
  125. package/components/inspector/inspector.yaml +1 -1
  126. package/components/kbd/kbd.a2ui.json +1 -1
  127. package/components/kbd/kbd.js +4 -4
  128. package/components/kbd/kbd.yaml +1 -1
  129. package/components/list/list.a2ui.json +1 -1
  130. package/components/list/list.js +6 -6
  131. package/components/list/list.yaml +1 -1
  132. package/components/menu/menu.a2ui.json +1 -1
  133. package/components/menu/menu.js +8 -8
  134. package/components/menu/menu.yaml +1 -1
  135. package/components/modal/modal.a2ui.json +1 -1
  136. package/components/modal/modal.js +4 -4
  137. package/components/modal/modal.yaml +1 -1
  138. package/components/nav/nav.a2ui.json +98 -0
  139. package/components/nav/nav.css +133 -0
  140. package/components/nav/nav.js +140 -0
  141. package/components/nav/nav.test.js +428 -0
  142. package/components/nav/nav.yaml +114 -0
  143. package/components/nav-group/nav-group.a2ui.json +100 -0
  144. package/components/nav-group/nav-group.css +317 -0
  145. package/components/nav-group/nav-group.js +142 -0
  146. package/components/nav-group/nav-group.yaml +69 -0
  147. package/components/nav-item/nav-item.a2ui.json +106 -0
  148. package/components/nav-item/nav-item.css +194 -0
  149. package/components/nav-item/nav-item.js +76 -0
  150. package/components/nav-item/nav-item.yaml +73 -0
  151. package/components/noodles/noodles.a2ui.json +1 -1
  152. package/components/noodles/noodles.js +4 -4
  153. package/components/noodles/noodles.yaml +1 -1
  154. package/components/option-card/option-card.a2ui.json +1 -1
  155. package/components/option-card/option-card.js +6 -6
  156. package/components/option-card/option-card.yaml +1 -1
  157. package/components/otp-input/otp-input.a2ui.json +1 -1
  158. package/components/otp-input/otp-input.js +5 -5
  159. package/components/otp-input/otp-input.yaml +1 -1
  160. package/components/page/page.a2ui.json +3 -3
  161. package/components/page/page.js +4 -4
  162. package/components/page/page.yaml +3 -3
  163. package/components/pagination/pagination.a2ui.json +1 -1
  164. package/components/pagination/pagination.js +4 -4
  165. package/components/pagination/pagination.yaml +1 -1
  166. package/components/pane/pane.a2ui.json +1 -1
  167. package/components/pane/pane.js +4 -4
  168. package/components/pane/pane.yaml +1 -1
  169. package/components/pipeline-status/pipeline-status.a2ui.json +1 -1
  170. package/components/pipeline-status/pipeline-status.js +4 -4
  171. package/components/pipeline-status/pipeline-status.yaml +1 -1
  172. package/components/popover/popover.a2ui.json +1 -1
  173. package/components/popover/popover.js +4 -4
  174. package/components/popover/popover.yaml +1 -1
  175. package/components/progress/progress.a2ui.json +1 -1
  176. package/components/progress/progress.js +4 -4
  177. package/components/progress/progress.yaml +1 -1
  178. package/components/progress-row/progress-row.a2ui.json +1 -1
  179. package/components/progress-row/progress-row.js +4 -4
  180. package/components/progress-row/progress-row.yaml +1 -1
  181. package/components/radio/radio.a2ui.json +1 -1
  182. package/components/radio/radio.js +5 -5
  183. package/components/radio/radio.yaml +1 -1
  184. package/components/range/range.a2ui.json +1 -1
  185. package/components/range/range.js +7 -7
  186. package/components/range/range.yaml +1 -1
  187. package/components/rating/rating.a2ui.json +1 -1
  188. package/components/rating/rating.js +6 -6
  189. package/components/rating/rating.yaml +1 -1
  190. package/components/richtext/richtext.a2ui.json +1 -1
  191. package/components/richtext/richtext.js +4 -4
  192. package/components/richtext/richtext.yaml +1 -1
  193. package/components/row/row.a2ui.json +1 -1
  194. package/components/row/row.js +4 -4
  195. package/components/row/row.yaml +1 -1
  196. package/components/search/search.a2ui.json +1 -1
  197. package/components/search/search.js +5 -5
  198. package/components/search/search.yaml +1 -1
  199. package/components/section/section.a2ui.json +1 -1
  200. package/components/section/section.yaml +1 -1
  201. package/components/segment/segment.a2ui.json +1 -1
  202. package/components/segment/segment.js +4 -4
  203. package/components/segment/segment.yaml +1 -1
  204. package/components/segmented/segmented.a2ui.json +1 -1
  205. package/components/segmented/segmented.css +6 -0
  206. package/components/segmented/segmented.js +7 -7
  207. package/components/segmented/segmented.yaml +1 -1
  208. package/components/select/select.a2ui.json +1 -1
  209. package/components/select/select.js +5 -5
  210. package/components/select/select.yaml +1 -1
  211. package/components/skeleton/skeleton.a2ui.json +1 -1
  212. package/components/skeleton/skeleton.js +4 -4
  213. package/components/skeleton/skeleton.yaml +1 -1
  214. package/components/slider/slider.a2ui.json +1 -1
  215. package/components/slider/slider.js +7 -7
  216. package/components/slider/slider.yaml +1 -1
  217. package/components/stack/stack.a2ui.json +1 -1
  218. package/components/stack/stack.js +4 -4
  219. package/components/stack/stack.yaml +1 -1
  220. package/components/stat/stat.a2ui.json +1 -1
  221. package/components/stat/stat.js +4 -4
  222. package/components/stat/stat.yaml +1 -1
  223. package/components/step-progress/step-progress.a2ui.json +111 -0
  224. package/components/step-progress/step-progress.css +61 -0
  225. package/components/step-progress/step-progress.js +88 -0
  226. package/components/step-progress/step-progress.test.js +118 -0
  227. package/components/step-progress/step-progress.yaml +93 -0
  228. package/components/stepper/stepper.a2ui.json +1 -1
  229. package/components/stepper/stepper.js +6 -6
  230. package/components/stepper/stepper.yaml +1 -1
  231. package/components/stream/stream.a2ui.json +1 -1
  232. package/components/stream/stream.js +4 -4
  233. package/components/stream/stream.yaml +1 -1
  234. package/components/swatch/swatch.a2ui.json +1 -1
  235. package/components/swatch/swatch.js +4 -4
  236. package/components/swatch/swatch.yaml +1 -1
  237. package/components/swiper/swiper.a2ui.json +1 -1
  238. package/components/swiper/swiper.js +4 -4
  239. package/components/swiper/swiper.yaml +1 -1
  240. package/components/switch/switch.a2ui.json +1 -1
  241. package/components/switch/switch.js +5 -5
  242. package/components/switch/switch.yaml +1 -1
  243. package/components/table/table.a2ui.json +1 -1
  244. package/components/table/table.js +4 -4
  245. package/components/table/table.yaml +1 -1
  246. package/components/table-toolbar/table-toolbar.a2ui.json +1 -1
  247. package/components/table-toolbar/table-toolbar.js +4 -4
  248. package/components/table-toolbar/table-toolbar.yaml +1 -1
  249. package/components/tabs/tab.js +4 -4
  250. package/components/tabs/tabs.a2ui.json +1 -1
  251. package/components/tabs/tabs.js +5 -5
  252. package/components/tabs/tabs.yaml +1 -1
  253. package/components/tag/tag.a2ui.json +1 -1
  254. package/components/tag/tag.js +4 -4
  255. package/components/tag/tag.yaml +1 -1
  256. package/components/text/text.a2ui.json +1 -1
  257. package/components/text/text.js +4 -4
  258. package/components/text/text.yaml +1 -1
  259. package/components/textarea/textarea.a2ui.json +1 -1
  260. package/components/textarea/textarea.js +5 -5
  261. package/components/textarea/textarea.yaml +1 -1
  262. package/components/timeline/timeline.a2ui.json +1 -1
  263. package/components/timeline/timeline.js +6 -6
  264. package/components/timeline/timeline.yaml +1 -1
  265. package/components/toast/toast.a2ui.json +1 -1
  266. package/components/toast/toast.js +18 -18
  267. package/components/toast/toast.yaml +1 -1
  268. package/components/toggle-group/toggle-group.a2ui.json +1 -1
  269. package/components/toggle-group/toggle-group.js +6 -6
  270. package/components/toggle-group/toggle-group.yaml +1 -1
  271. package/components/toolbar/toolbar.a2ui.json +1 -1
  272. package/components/toolbar/toolbar.js +6 -6
  273. package/components/toolbar/toolbar.yaml +1 -1
  274. package/components/tooltip/tooltip.a2ui.json +1 -1
  275. package/components/tooltip/tooltip.js +7 -7
  276. package/components/tooltip/tooltip.yaml +1 -1
  277. package/components/tree/tree.a2ui.json +1 -1
  278. package/components/tree/tree.js +6 -6
  279. package/components/tree/tree.yaml +1 -1
  280. package/components/upload/upload.a2ui.json +1 -1
  281. package/components/upload/upload.js +6 -6
  282. package/components/upload/upload.yaml +1 -1
  283. package/core/element.js +4 -4
  284. package/core/element.test.js +18 -18
  285. package/core/form.js +9 -9
  286. package/core/index.js +2 -2
  287. package/core/provider.js +7 -7
  288. package/core/template.js +1 -1
  289. package/index.css +1 -1
  290. package/index.js +10 -8
  291. package/package.json +1 -1
  292. package/styles/components.css +11 -6
  293. package/styles/resets.css +1 -1
  294. package/traits/define.js +2 -2
  295. /package/components/{chat → chat-thread}/chat-input.css +0 -0
@@ -0,0 +1,317 @@
1
+ @scope (nav-group-ui) {
2
+ :where(:scope) {
3
+ --nav-group-row-height: var(--a-size);
4
+ --nav-group-row-height-sm: var(--a-size-sm);
5
+ --nav-group-row-height-lg: var(--a-size-lg);
6
+ --nav-group-row-px: var(--a-ui-px);
7
+ --nav-group-row-gap: var(--a-space-1);
8
+ --nav-group-row-radius: var(--a-radius-md);
9
+ --nav-group-font-size: var(--a-ui-size);
10
+ --nav-group-font-size-sm: var(--a-ui-sm);
11
+ --nav-group-font-size-lg: var(--a-ui-lg);
12
+ --nav-group-fg: var(--a-fg);
13
+ --nav-group-fg-hover: var(--a-fg-strong);
14
+ --nav-group-fg-muted: var(--a-fg-muted);
15
+ --nav-group-fg-selected: var(--a-fg-strong);
16
+ --nav-group-bg-hover: var(--a-bg-muted);
17
+ --nav-group-icon-size: calc(var(--nav-group-row-height) - var(--a-space-2));
18
+ --nav-group-badge-size: var(--a-ui-sm);
19
+
20
+ --nav-item-child-height: var(--a-size-sm);
21
+ --nav-item-child-font: var(--nav-group-font-size);
22
+ }
23
+
24
+ :scope {
25
+ box-sizing: border-box;
26
+ display: flex;
27
+ flex-direction: column;
28
+ gap: var(--nav-gap);
29
+ position: relative;
30
+ }
31
+
32
+ /* Continuous indent rail */
33
+ :scope[open]::after {
34
+ content: '';
35
+ position: absolute;
36
+ left: calc(var(--nav-group-row-px) + var(--nav-group-icon-size) / 2);
37
+ transform: translateX(-50%);
38
+ top: var(--nav-group-row-height);
39
+ bottom: calc(var(--nav-group-row-height) / 2);
40
+ width: 1px;
41
+ background: var(--nav-group-indent-rail-bg);
42
+ pointer-events: none;
43
+ }
44
+ :scope[open] > [slot="header"],
45
+ :scope[open] > [slot="header"] [slot="icon"] {
46
+ color: var(--nav-group-fg-selected);
47
+ }
48
+
49
+ /* Header row */
50
+ [slot="header"] {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: var(--nav-group-row-gap);
54
+ height: var(--nav-group-row-height);
55
+ padding: 0 var(--nav-group-row-px);
56
+ border-radius: var(--nav-group-row-radius);
57
+ font-size: var(--nav-group-font-size);
58
+ color: var(--nav-group-fg);
59
+ cursor: pointer;
60
+ user-select: none;
61
+ white-space: nowrap;
62
+ transition:
63
+ background var(--nav-duration-fast) var(--nav-easing),
64
+ color var(--nav-duration-fast) var(--nav-easing);
65
+ outline: none;
66
+ }
67
+
68
+ [slot="header"]:hover {
69
+ background: var(--nav-group-bg-hover);
70
+ color: var(--nav-group-fg-hover);
71
+ }
72
+
73
+ [slot="header"]:hover [slot="icon"] {
74
+ color: var(--nav-group-fg-hover);
75
+ }
76
+
77
+ [slot="header"]:focus-visible {
78
+ background: var(--nav-group-bg-hover);
79
+ color: var(--nav-group-fg-hover);
80
+ outline: none;
81
+ }
82
+
83
+ [slot="header"] [slot="icon"] {
84
+ width: var(--nav-group-icon-size);
85
+ height: var(--nav-group-icon-size);
86
+ flex-shrink: 0;
87
+ color: var(--nav-group-fg-muted);
88
+ transition: color var(--nav-duration-fast) var(--nav-easing);
89
+ display: flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ }
93
+
94
+ [slot="header"] [slot="icon"] icon-ui {
95
+ --a-icon-size: calc(var(--nav-group-icon-font-size) + 2px);
96
+ }
97
+
98
+ [slot="header"] [slot="text"] {
99
+ flex: 1;
100
+ min-width: 0;
101
+ overflow: hidden;
102
+ text-overflow: ellipsis;
103
+ font-weight: var(--nav-group-text-weight);
104
+ }
105
+
106
+ [slot="header"] [slot="badge"] {
107
+ font-size: var(--nav-group-badge-size);
108
+ color: var(--nav-group-fg-muted);
109
+ background: var(--nav-group-badge-bg);
110
+ padding: 1px var(--nav-group-badge-px);
111
+ border-radius: var(--nav-group-badge-radius);
112
+ line-height: 1.4;
113
+ }
114
+
115
+ [slot="header"] [slot="caret"] {
116
+ /*--a-icon-size: 0.5rem;*/
117
+ color: var(--nav-group-fg-muted);
118
+ transition:
119
+ transform var(--nav-duration-fast) var(--nav-easing),
120
+ color var(--nav-duration-fast) var(--nav-easing);
121
+ transform: rotate(90deg);
122
+ flex-shrink: 0;
123
+
124
+ --a-icon-size: var(--a-caret-size);
125
+ }
126
+
127
+ [slot="header"]:hover [slot="caret"] {
128
+ color: var(--nav-group-fg-hover);
129
+ }
130
+
131
+ :scope:not([open]) > [slot="header"] [slot="caret"] {
132
+ transform: rotate(0deg);
133
+ }
134
+
135
+ /* Children — hidden when collapsed */
136
+ :scope:not([open]) > nav-item-ui {
137
+ display: none;
138
+ }
139
+
140
+ /* Child items default to sm for visual hierarchy */
141
+ :scope > nav-item-ui:not([size]) {
142
+ height: var(--nav-item-child-height);
143
+ font-size: var(--nav-item-child-font);
144
+ }
145
+
146
+ /* ── Collapsed nav: hide text, badge, caret ── */
147
+ nav-ui[collapsed] & [slot="text"],
148
+ nav-ui[collapsed] & [slot="badge"],
149
+ nav-ui[collapsed] & [slot="caret"] {
150
+ display: none;
151
+ }
152
+
153
+ nav-ui[collapsed] & [slot="header"] {
154
+ justify-content: center;
155
+ padding: 0;
156
+ }
157
+
158
+ nav-ui[collapsed] & {
159
+ align-self: stretch;
160
+ }
161
+
162
+ nav-ui[collapsed] &::after {
163
+ display: none;
164
+ }
165
+
166
+ @container sidebar (max-width: 96px) {
167
+ [slot="text"], [slot="badge"], [slot="caret"] {
168
+ display: none !important;
169
+ }
170
+ nav-item-ui {
171
+ display: none !important;
172
+ }
173
+ [slot="header"] {
174
+ justify-content: center;
175
+ padding: 0;
176
+ }
177
+ [slot="icon"] icon-ui {
178
+ --a-icon-size: --a-icon-size;
179
+ }
180
+ [slot="caret"] icon-ui {
181
+ --a-icon-size: --a-caret-size;
182
+ }
183
+ :scope {
184
+ align-self: stretch;
185
+ }
186
+ :scope::after {
187
+ display: none;
188
+ }
189
+ }
190
+
191
+ /* ── Size variants ── */
192
+ :scope[size="sm"] {
193
+ --nav-group-row-height: var(--nav-group-row-height-sm);
194
+ --nav-group-font-size: var(--nav-group-font-size-sm);
195
+ }
196
+
197
+ :scope[size="lg"] {
198
+ --nav-group-row-height: var(--nav-group-row-height-lg);
199
+ --nav-group-font-size: var(--nav-group-font-size-lg);
200
+ }
201
+ }
202
+
203
+ /* Nav-group popover (outside @scope — lives in top layer)
204
+ Popovers are promoted to the top layer and cannot inherit
205
+ pattern-level custom properties, so raw --a-* tokens are
206
+ used intentionally here. */
207
+ nav-group-ui [slot="popover"] {
208
+ margin: 0;
209
+ padding: var(--a-space-1);
210
+ border: 1px solid var(--a-border-subtle);
211
+ border-radius: var(--a-radius);
212
+ background: var(--a-bg-subtle);
213
+ box-shadow: var(--a-shadow-lg);
214
+ min-width: 160px;
215
+ max-height: calc(100vh - 3rem);
216
+ overflow-y: auto;
217
+ font-size: var(--a-ui-size);
218
+ }
219
+
220
+ nav-group-ui [slot="popover-label"] {
221
+ padding: var(--a-space-1) var(--a-space-2);
222
+ font-weight: var(--a-weight-medium);
223
+ color: var(--a-fg-muted);
224
+ font-size: var(--a-ui-tiny);
225
+ text-transform: uppercase;
226
+ letter-spacing: 0.06em;
227
+ }
228
+
229
+ nav-group-ui [slot="popover"] [role="option"] {
230
+ padding: var(--a-space-1) var(--a-space-2);
231
+ border-radius: var(--a-radius);
232
+ color: var(--a-fg-subtle);
233
+ cursor: pointer;
234
+ white-space: nowrap;
235
+ transition:
236
+ background var(--a-duration-fast) var(--a-easing),
237
+ color var(--a-duration-fast) var(--a-easing);
238
+ }
239
+
240
+ nav-group-ui [slot="popover"] [role="option"]:hover {
241
+ background: var(--a-bg-hover);
242
+ color: var(--a-fg-strong);
243
+ }
244
+
245
+ /* Selected / current option — mirrors the main rail's nav-item selection:
246
+ muted fill + leading 2px accent bar. */
247
+ nav-group-ui [slot="popover"] [role="option"][aria-current="page"],
248
+ nav-group-ui [slot="popover"] [role="option"][aria-selected="true"] {
249
+ position: relative;
250
+ background: var(--a-bg-hover);
251
+ color: var(--a-fg-strong);
252
+ font-weight: var(--a-weight-medium);
253
+ }
254
+
255
+ nav-group-ui [slot="popover"] [role="option"][aria-current="page"]::before,
256
+ nav-group-ui [slot="popover"] [role="option"][aria-selected="true"]::before {
257
+ content: '';
258
+ position: absolute;
259
+ inset-inline-start: calc(var(--a-space-2) * -0.5);
260
+ inset-block: 25%;
261
+ width: 2px;
262
+ border-radius: 1px;
263
+ background: var(--a-accent);
264
+ }
265
+
266
+ /* ── Section variant — groups render as kicker labels ──
267
+ The prior <section-nav-group-ui> defaulted to collapsible:false
268
+ (header was a label, children always visible). The consolidated
269
+ nav-group-ui defaults collapsible:true (the primary-variant default).
270
+ Section variant restores the old kicker rendering so subnav rails
271
+ show all children without an explicit [open] toggle.
272
+
273
+ Two ways to enable: either
274
+ (a) `<nav-group-ui variant="section">` directly, or
275
+ (b) `<nav-ui variant="section"> > nav-group-ui` (cascade from parent).
276
+ Both selectors apply the same kicker styles. */
277
+
278
+ nav-group-ui[variant="section"] > [slot="header"],
279
+ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"] {
280
+ height: auto;
281
+ padding: var(--a-space-3) var(--a-space-2) var(--a-space-1);
282
+ font-size: var(--a-kicker-sm, var(--a-ui-tiny));
283
+ font-weight: var(--a-weight-medium);
284
+ color: var(--a-fg-muted);
285
+ text-transform: uppercase;
286
+ letter-spacing: 0.06em;
287
+ cursor: default;
288
+ border-radius: 0;
289
+ }
290
+
291
+ nav-group-ui[variant="section"] > [slot="header"]:hover,
292
+ nav-group-ui[variant="section"] > [slot="header"]:focus-visible,
293
+ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"]:hover,
294
+ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"]:focus-visible {
295
+ background: transparent;
296
+ color: var(--a-fg-muted);
297
+ }
298
+
299
+ nav-group-ui[variant="section"] > [slot="header"] [slot="caret"],
300
+ nav-group-ui[variant="section"] > [slot="header"] [slot="icon"]:empty,
301
+ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"] [slot="caret"],
302
+ nav-ui[variant="section"] > nav-group-ui:not([variant]) > [slot="header"] [slot="icon"]:empty {
303
+ display: none;
304
+ }
305
+
306
+ /* Children always visible in section variant (override the
307
+ :scope:not([open]) > nav-item-ui hide rule from inside @scope). */
308
+ nav-group-ui[variant="section"]:not([open]) > nav-item-ui,
309
+ nav-ui[variant="section"] > nav-group-ui:not([variant]):not([open]) > nav-item-ui {
310
+ display: flex;
311
+ }
312
+
313
+ /* No indent rail in section variant — kicker layout doesn't carry it. */
314
+ nav-group-ui[variant="section"]::after,
315
+ nav-ui[variant="section"] > nav-group-ui:not([variant])::after {
316
+ display: none;
317
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * <nav-group-ui> — Collapsible labeled group of nav items inside <nav-ui>.
3
+ *
4
+ * Consolidates the prior `app-nav-group-ui` + `section-nav-group-ui`
5
+ * per ADR-0015 § Nav consolidation. Behavior is unified; the parent
6
+ * <nav-ui>'s [variant] drives the visual treatment.
7
+ *
8
+ * Has icon, label, optional badge, and a caret indicating open/closed.
9
+ * When the parent <nav-ui> is collapsed (primary variant), clicking the
10
+ * group opens a popover with its children instead of toggling inline
11
+ * expansion. When [collapsible] (or always for primary variant), inline
12
+ * click + keyboard toggle is supported.
13
+ */
14
+
15
+ import { UIElement } from '../../core/element.js';
16
+ import { anchorPopover } from '../../core/anchor.js';
17
+
18
+ class UINavGroup extends UIElement {
19
+ static properties = {
20
+ text: { type: String, default: '', reflect: true },
21
+ icon: { type: String, default: '', reflect: true },
22
+ badge: { type: String, default: '', reflect: true },
23
+ open: { type: Boolean, default: false, reflect: true },
24
+ collapsible: { type: Boolean, default: true, reflect: true },
25
+ variant: { type: String, default: '', reflect: true },
26
+ };
27
+
28
+ static template = () => null;
29
+
30
+ #popover = null;
31
+ #anchorCleanup = null;
32
+ #headerEl = null;
33
+
34
+ #onHeaderKey = (e) => {
35
+ if (!this.collapsible) return;
36
+ if (e.key === 'Enter' || e.key === ' ') {
37
+ e.preventDefault();
38
+ this.open = !this.open;
39
+ this.dispatchEvent(new CustomEvent('group-toggle', {
40
+ bubbles: true,
41
+ detail: { text: this.text, open: this.open },
42
+ }));
43
+ }
44
+ };
45
+
46
+ connected() {
47
+ this.setAttribute('role', 'group');
48
+
49
+ if (!this.querySelector(':scope > [slot="header"]')) {
50
+ this.#headerEl = document.createElement('div');
51
+ this.#headerEl.setAttribute('slot', 'header');
52
+ this.#headerEl.setAttribute('tabindex', '0');
53
+ this.#headerEl.innerHTML = `
54
+ <span slot="icon">${this.icon ? `<icon-ui name="${this.icon}"></icon-ui>` : ''}</span>
55
+ <span slot="text">${this.text}</span>
56
+ ${this.badge ? `<span slot="badge">${this.badge}</span>` : ''}
57
+ <icon-ui slot="caret" name="caret-right"></icon-ui>
58
+ `;
59
+ this.prepend(this.#headerEl);
60
+ } else {
61
+ this.#headerEl = this.querySelector(':scope > [slot="header"]');
62
+ }
63
+
64
+ this.#headerEl?.addEventListener('keydown', this.#onHeaderKey);
65
+ }
66
+
67
+ render() {
68
+ const textEl = this.querySelector('[slot="header"] [slot="text"]');
69
+ if (textEl) textEl.textContent = this.text;
70
+
71
+ const badgeEl = this.querySelector('[slot="header"] [slot="badge"]');
72
+ if (badgeEl) badgeEl.textContent = this.badge;
73
+
74
+ this.setAttribute('aria-expanded', String(this.open));
75
+ }
76
+
77
+ showPopover() {
78
+ if (!this.#popover) {
79
+ this.#popover = document.createElement('div');
80
+ this.#popover.setAttribute('slot', 'popover');
81
+ this.#popover.setAttribute('popover', 'auto');
82
+
83
+ const label = document.createElement('div');
84
+ label.setAttribute('slot', 'popover-label');
85
+ label.textContent = this.text;
86
+ this.#popover.appendChild(label);
87
+
88
+ for (const child of this.querySelectorAll(':scope > nav-item-ui')) {
89
+ const opt = document.createElement('div');
90
+ opt.setAttribute('role', 'option');
91
+ opt.dataset.sourceValue = child.getAttribute('value') || '';
92
+ opt.textContent = child.text;
93
+ opt.addEventListener('click', () => {
94
+ const nav = this.closest('nav-ui');
95
+ if (nav) nav.select(child);
96
+ this.#popover.hidePopover();
97
+ });
98
+ this.#popover.appendChild(opt);
99
+ }
100
+
101
+ this.appendChild(this.#popover);
102
+
103
+ this.#popover.addEventListener('toggle', (e) => {
104
+ if (e.newState === 'closed') {
105
+ this.#anchorCleanup?.();
106
+ this.#anchorCleanup = null;
107
+ }
108
+ });
109
+ }
110
+
111
+ for (const opt of this.#popover.querySelectorAll('[role="option"]')) {
112
+ const srcValue = opt.dataset.sourceValue;
113
+ const src = srcValue
114
+ ? this.querySelector(`:scope > nav-item-ui[value="${srcValue}"]`)
115
+ : null;
116
+ if (src?.hasAttribute('selected')) {
117
+ opt.setAttribute('aria-current', 'page');
118
+ opt.setAttribute('aria-selected', 'true');
119
+ } else {
120
+ opt.removeAttribute('aria-current');
121
+ opt.removeAttribute('aria-selected');
122
+ }
123
+ }
124
+
125
+ this.#popover.showPopover();
126
+
127
+ this.#anchorCleanup?.();
128
+ this.#anchorCleanup = anchorPopover(this, this.#popover, {
129
+ placement: 'right', gap: 4,
130
+ });
131
+ }
132
+
133
+ disconnected() {
134
+ this.#headerEl?.removeEventListener('keydown', this.#onHeaderKey);
135
+ this.#anchorCleanup?.();
136
+ this.#anchorCleanup = null;
137
+ this.#popover?.hidePopover?.();
138
+ }
139
+ }
140
+
141
+ customElements.define('nav-group-ui', UINavGroup);
142
+ export { UINavGroup };
@@ -0,0 +1,69 @@
1
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
2
+ name: UINavGroup
3
+ tag: nav-group-ui
4
+ component: NavGroup
5
+ category: layout
6
+ version: 1
7
+ description: |
8
+ Collapsible labeled group of <nav-item-ui> children inside <nav-ui>.
9
+ Consolidates the prior `app-nav-group-ui` + `section-nav-group-ui`
10
+ per ADR-0015 § Nav consolidation.
11
+
12
+ When the parent <nav-ui> is collapsed (primary variant), clicking the
13
+ group opens a popover with its children instead of toggling inline
14
+ expansion. Inline click + keyboard (Enter/Space) toggle is supported
15
+ when [collapsible] (default true).
16
+
17
+ props:
18
+ text:
19
+ type: string
20
+ default: ''
21
+ description: "Visible group label."
22
+ icon:
23
+ type: string
24
+ default: ''
25
+ description: "Optional leading icon name (resolved via <icon-ui>)."
26
+ badge:
27
+ type: string
28
+ default: ''
29
+ description: "Optional trailing badge (count, label)."
30
+ open:
31
+ type: boolean
32
+ default: false
33
+ description: "Inline-expanded state. Toggled by header click when [collapsible]."
34
+ collapsible:
35
+ type: boolean
36
+ default: true
37
+ description: "When true, the header row toggles the open state on click/keyboard."
38
+ variant:
39
+ type: string
40
+ default: ''
41
+ enum: ['', section]
42
+ description: "Visual treatment. Default ('') renders as a primary-rail group (icon row, caret, collapsible). 'section' renders the header as a static kicker label with always-visible children — matches the prior <section-nav-group-ui>. When the parent <nav-ui> carries variant=\"section\", this group inherits it via CSS cascade unless an explicit variant is set on the group."
43
+
44
+ events:
45
+ group-toggle:
46
+ description: "Fired when the header toggles via click/keyboard. Detail: { text, open }."
47
+
48
+ slots:
49
+ default:
50
+ description: "Children — typically <nav-item-ui> rows."
51
+ header:
52
+ description: "Optional custom header. Auto-generated when missing."
53
+
54
+ states:
55
+ - name: closed
56
+ description: Default. Children hidden.
57
+ - name: open
58
+ description: Children visible inline.
59
+
60
+ traits: []
61
+ tokens: {}
62
+ a2ui:
63
+ rules: []
64
+ anti_patterns: []
65
+ examples: []
66
+
67
+ keywords: [nav, navigation, group, sidebar, menu]
68
+ synonyms: {}
69
+ related: []
@@ -0,0 +1,106 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://adiaui.dev/a2ui/v0_9/components/NavItem.json",
4
+ "title": "NavItem",
5
+ "description": "Single navigation link inside <nav-ui> (optionally nested under\n<nav-group-ui>). Consolidates the prior `app-nav-item-ui` +\n`section-nav-item-ui` per ADR-0015 § Nav consolidation.\n\nSupports icon, label, optional badge, selected/disabled state, and\nkeyboard activation (Enter/Space). Selection is managed by the parent\n<nav-ui>; clicking or activating an item calls nav.select(this) and\nbubbles a `nav-select` event.\n",
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
+ "badge": {
17
+ "description": "Optional trailing badge.",
18
+ "type": "string",
19
+ "default": ""
20
+ },
21
+ "component": {
22
+ "const": "NavItem"
23
+ },
24
+ "disabled": {
25
+ "description": "Suppresses click/keyboard activation; greyed visually.",
26
+ "type": "boolean",
27
+ "default": false
28
+ },
29
+ "icon": {
30
+ "description": "Optional leading icon name.",
31
+ "type": "string",
32
+ "default": ""
33
+ },
34
+ "selected": {
35
+ "description": "Set by the parent <nav-ui>'s select() method.",
36
+ "type": "boolean",
37
+ "default": false
38
+ },
39
+ "text": {
40
+ "description": "Visible item label.",
41
+ "type": "string",
42
+ "default": ""
43
+ },
44
+ "value": {
45
+ "description": "Identifier — typically a route or anchor.",
46
+ "type": "string",
47
+ "default": ""
48
+ },
49
+ "variant": {
50
+ "description": "Visual treatment. Default ('') renders as a primary-rail item (reserved icon space, in-icon selected accent). 'section' renders flat — no icon space when absent, left-edge accent bar for selected — matching the prior <section-nav-item-ui>. When the parent <nav-ui> carries variant=\"section\", this item inherits it via CSS cascade unless an explicit variant is set.",
51
+ "type": "string",
52
+ "enum": [
53
+ "",
54
+ "section"
55
+ ],
56
+ "default": ""
57
+ }
58
+ },
59
+ "required": [
60
+ "component"
61
+ ],
62
+ "unevaluatedProperties": false,
63
+ "x-adiaui": {
64
+ "anti_patterns": [],
65
+ "category": "layout",
66
+ "events": {
67
+ "nav-select": {
68
+ "description": "Bubbles when the item is activated. Detail: { item, text, value }."
69
+ }
70
+ },
71
+ "examples": [],
72
+ "keywords": [
73
+ "nav",
74
+ "navigation",
75
+ "item",
76
+ "link",
77
+ "sidebar"
78
+ ],
79
+ "name": "UINavItem",
80
+ "related": [],
81
+ "slots": {
82
+ "default": {
83
+ "description": "Optional override of the default icon + text + badge stamping."
84
+ }
85
+ },
86
+ "states": [
87
+ {
88
+ "description": "Default.",
89
+ "name": "idle"
90
+ },
91
+ {
92
+ "description": "aria-current=page.",
93
+ "name": "selected"
94
+ },
95
+ {
96
+ "description": "Suppressed activation.",
97
+ "name": "disabled"
98
+ }
99
+ ],
100
+ "synonyms": {},
101
+ "tag": "nav-item-ui",
102
+ "tokens": {},
103
+ "traits": [],
104
+ "version": 1
105
+ }
106
+ }