@ds-mo/ui 12.5.0 → 12.6.0

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 (284) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/agent-patterns.json +21 -12
  3. package/dist/agent.json +1536 -1424
  4. package/dist/angular/ds-bar-workflow.d.ts +1 -1
  5. package/dist/angular/ds-bar-workflow.js +3 -3
  6. package/dist/angular/ds-mobile-bar-nav.d.ts +18 -0
  7. package/dist/angular/{ds-shell-mobile-bar.js → ds-mobile-bar-nav.js} +15 -15
  8. package/dist/angular/ds-mobile-header.d.ts +23 -0
  9. package/dist/angular/ds-mobile-header.js +45 -0
  10. package/dist/angular/ds-mobile-section-switcher.d.ts +18 -0
  11. package/dist/angular/{ds-shell-mobile-section-nav.js → ds-mobile-section-switcher.js} +15 -15
  12. package/dist/angular/ds-mobile-sheet-nav.d.ts +20 -0
  13. package/dist/angular/{ds-shell-mobile-nav.js → ds-mobile-sheet-nav.js} +13 -16
  14. package/dist/angular/ds-shell-app.d.ts +1 -1
  15. package/dist/angular/ds-shell-app.js +3 -3
  16. package/dist/angular/ds-shell-page.d.ts +1 -1
  17. package/dist/angular/ds-shell-page.js +3 -3
  18. package/dist/angular/index.d.ts +1 -1
  19. package/dist/angular/index.js +4 -3
  20. package/dist/angular/proxies.d.ts +4 -3
  21. package/dist/angular/proxies.js +4 -3
  22. package/dist/components/ds-agent-activity.js +1 -1
  23. package/dist/components/ds-agent-response.js +1 -1
  24. package/dist/components/ds-agent-tool-call.js +1 -1
  25. package/dist/components/ds-avatar.js +1 -1
  26. package/dist/components/ds-avatar.js.map +1 -1
  27. package/dist/components/ds-badge.js +1 -1
  28. package/dist/components/ds-bar-nav.js +1 -1
  29. package/dist/components/ds-bar-nav.js.map +1 -1
  30. package/dist/components/ds-bar-title.js +1 -1
  31. package/dist/components/ds-bar-title.js.map +1 -1
  32. package/dist/components/ds-bar-workflow.js +1 -1
  33. package/dist/components/ds-bar-workflow.js.map +1 -1
  34. package/dist/components/ds-breadcrumb.js +1 -1
  35. package/dist/components/ds-button-filled.js +1 -1
  36. package/dist/components/ds-button-unfilled.js +1 -1
  37. package/dist/components/ds-card-data-viz-bar.js +1 -1
  38. package/dist/components/ds-card-data-viz-donut.js +1 -1
  39. package/dist/components/ds-card-data-viz-line.js +1 -1
  40. package/dist/components/ds-card-setting.js +1 -1
  41. package/dist/components/ds-chart-bar.js +1 -1
  42. package/dist/components/ds-chart-donut.js +1 -1
  43. package/dist/components/ds-chart-legend.js +1 -1
  44. package/dist/components/ds-chart-legend.js.map +1 -1
  45. package/dist/components/ds-chart-line.js +1 -1
  46. package/dist/components/ds-checkbox.js +1 -1
  47. package/dist/components/ds-chip.js +1 -1
  48. package/dist/components/ds-chip.js.map +1 -1
  49. package/dist/components/ds-code-block.js +1 -1
  50. package/dist/components/ds-conversation-list-item.js +1 -1
  51. package/dist/components/ds-conversation-list-item.js.map +1 -1
  52. package/dist/components/ds-conversation-list-section.js +1 -1
  53. package/dist/components/ds-empty-state.js +1 -1
  54. package/dist/components/ds-field.js +1 -1
  55. package/dist/components/ds-input.js +1 -1
  56. package/dist/components/ds-input.js.map +1 -1
  57. package/dist/components/ds-loader.js +1 -1
  58. package/dist/components/ds-markdown.js +1 -1
  59. package/dist/components/ds-menu.js +1 -1
  60. package/dist/components/ds-message-composer.js +1 -1
  61. package/dist/components/ds-message-composer.js.map +1 -1
  62. package/dist/components/ds-message-scroller.js +1 -1
  63. package/dist/components/ds-message.js +1 -1
  64. package/dist/components/{ds-shell-mobile-nav.d.ts → ds-mobile-bar-nav.d.ts} +4 -4
  65. package/dist/components/ds-mobile-bar-nav.js +2 -0
  66. package/dist/components/ds-mobile-bar-nav.js.map +1 -0
  67. package/dist/components/ds-mobile-header.d.ts +11 -0
  68. package/dist/components/ds-mobile-header.js +2 -0
  69. package/dist/components/ds-mobile-header.js.map +1 -0
  70. package/dist/components/ds-mobile-section-switcher.d.ts +11 -0
  71. package/dist/components/ds-mobile-section-switcher.js +2 -0
  72. package/dist/components/ds-mobile-section-switcher.js.map +1 -0
  73. package/dist/components/{ds-shell-mobile-bar.d.ts → ds-mobile-sheet-nav.d.ts} +4 -4
  74. package/dist/components/ds-mobile-sheet-nav.js +2 -0
  75. package/dist/components/ds-mobile-sheet-nav.js.map +1 -0
  76. package/dist/components/ds-modal.js +1 -1
  77. package/dist/components/ds-modal.js.map +1 -1
  78. package/dist/components/ds-panel-nav.js +1 -1
  79. package/dist/components/ds-panel-nav.js.map +1 -1
  80. package/dist/components/ds-panel-sub-nav.js +1 -1
  81. package/dist/components/ds-panel-sub-nav.js.map +1 -1
  82. package/dist/components/ds-panel-tool-header.js +1 -1
  83. package/dist/components/ds-panel-tool-search.js +1 -1
  84. package/dist/components/ds-panel-tool-search.js.map +1 -1
  85. package/dist/components/ds-panel-tools.js +1 -1
  86. package/dist/components/ds-radio.js +1 -1
  87. package/dist/components/ds-radio.js.map +1 -1
  88. package/dist/components/ds-select-multi.js +1 -1
  89. package/dist/components/ds-select-multi.js.map +1 -1
  90. package/dist/components/ds-select.js +1 -1
  91. package/dist/components/ds-select.js.map +1 -1
  92. package/dist/components/ds-shell-app.js +1 -1
  93. package/dist/components/ds-shell-app.js.map +1 -1
  94. package/dist/components/ds-shell-gradient-picker.js +1 -1
  95. package/dist/components/ds-shell-gradient-picker.js.map +1 -1
  96. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  97. package/dist/components/ds-shell-page.js +1 -1
  98. package/dist/components/ds-shell-page.js.map +1 -1
  99. package/dist/components/ds-shell-tools.js +1 -1
  100. package/dist/components/ds-shell-tools.js.map +1 -1
  101. package/dist/components/ds-skeleton.js +1 -1
  102. package/dist/components/ds-skeleton.js.map +1 -1
  103. package/dist/components/ds-swatch-picker.js +1 -1
  104. package/dist/components/ds-switch.js +1 -1
  105. package/dist/components/ds-tab-group.js +1 -1
  106. package/dist/components/ds-tag.js +1 -1
  107. package/dist/components/ds-tag.js.map +1 -1
  108. package/dist/components/ds-toast.js +1 -1
  109. package/dist/components/ds-toast.js.map +1 -1
  110. package/dist/components/ds-tooltip-data-viz.js +1 -1
  111. package/dist/components/ds-tooltip.js +1 -1
  112. package/dist/components/ds-typing-indicator.js +1 -1
  113. package/dist/components/p--bSkr_yn.js +2 -0
  114. package/dist/components/p--bSkr_yn.js.map +1 -0
  115. package/dist/components/p-46nk9-RO.js +2 -0
  116. package/dist/components/p-46nk9-RO.js.map +1 -0
  117. package/dist/components/{p-9dQQSgwT.js → p-BHYrsGBw.js} +2 -2
  118. package/dist/components/p-BY0PzkUp.js +2 -0
  119. package/dist/components/p-BgGP65Nn.js +2 -0
  120. package/dist/components/p-BgGP65Nn.js.map +1 -0
  121. package/dist/components/p-BkAMkjIR.js +2 -0
  122. package/dist/components/{p-Co8hD3P-.js.map → p-BkAMkjIR.js.map} +1 -1
  123. package/dist/components/p-BrusnEYP.js.map +1 -1
  124. package/dist/components/p-C2ym_Ich.js +2 -0
  125. package/dist/components/{p-Biz6xo-z.js → p-CFpWrYAH.js} +2 -2
  126. package/dist/components/p-CICGtu7H.js +2 -0
  127. package/dist/components/{p-CtD24EyI.js.map → p-CICGtu7H.js.map} +1 -1
  128. package/dist/components/p-CLzlL3G4.js +2 -0
  129. package/dist/components/p-CLzlL3G4.js.map +1 -0
  130. package/dist/components/p-CXcjwduV.js +2 -0
  131. package/dist/components/{p-BhxwpOH8.js.map → p-CXcjwduV.js.map} +1 -1
  132. package/dist/components/p-Ca-I2UnB.js +2 -0
  133. package/dist/components/p-Ca-I2UnB.js.map +1 -0
  134. package/dist/components/p-CaRyxTMz.js +2 -0
  135. package/dist/components/p-CaRyxTMz.js.map +1 -0
  136. package/dist/components/{p-g40DTeV8.js → p-CvKKmZJj.js} +2 -2
  137. package/dist/components/p-D4o2D1hk.js +2 -0
  138. package/dist/components/p-D4o2D1hk.js.map +1 -0
  139. package/dist/components/{p-DXnFhmZF.js → p-D9iN80yX.js} +2 -2
  140. package/dist/components/p-DD1Lgs7O.js +2 -0
  141. package/dist/components/p-DD1Lgs7O.js.map +1 -0
  142. package/dist/components/{p-DjPZxzIG.js → p-DQDpDYyF.js} +2 -2
  143. package/dist/components/p-DTea1Du7.js +2 -0
  144. package/dist/components/p-DTea1Du7.js.map +1 -0
  145. package/dist/components/p-DWdRSOBV.js +2 -0
  146. package/dist/components/{p-BPS9VExm.js.map → p-DWdRSOBV.js.map} +1 -1
  147. package/dist/components/p-DcFfilOX.js +2 -0
  148. package/dist/components/p-DcFfilOX.js.map +1 -0
  149. package/dist/components/p-Dg3xLna0.js +2 -0
  150. package/dist/components/{p-C_0Q8Cnp.js.map → p-Dg3xLna0.js.map} +1 -1
  151. package/dist/components/p-DvVW0hxm.js +2 -0
  152. package/dist/components/p-DvVW0hxm.js.map +1 -0
  153. package/dist/components/p-YtgcuJYx.js +2 -0
  154. package/dist/components/{p-PZ6R_nGI.js.map → p-YtgcuJYx.js.map} +1 -1
  155. package/dist/components/p-loq_--ce.js +2 -0
  156. package/dist/components/{p-NUNsefU1.js.map → p-loq_--ce.js.map} +1 -1
  157. package/dist/docs/components.json +3586 -3064
  158. package/dist/lib/shell/index.d.ts +1 -1
  159. package/dist/lib/shell/index.js +2 -1
  160. package/dist/lib/shell/index.js.map +2 -2
  161. package/dist/lib/shell/shell-responsive.d.ts +3 -3
  162. package/dist/lib/utils/index.d.ts +1 -0
  163. package/dist/lib/utils/index.js +8 -0
  164. package/dist/lib/utils/index.js.map +3 -3
  165. package/dist/lib/utils/required-validity.d.ts +14 -0
  166. package/dist/mcp-data/registry/agent-activity.json +2 -2
  167. package/dist/mcp-data/registry/badge.json +2 -2
  168. package/dist/mcp-data/registry/bar-nav.json +2 -2
  169. package/dist/mcp-data/registry/bar-title.json +2 -2
  170. package/dist/mcp-data/registry/bar-workflow.json +25 -4
  171. package/dist/mcp-data/registry/breadcrumb.json +2 -2
  172. package/dist/mcp-data/registry/button-unfilled.json +3 -3
  173. package/dist/mcp-data/registry/chart-legend.json +1 -1
  174. package/dist/mcp-data/registry/checkbox.json +1 -1
  175. package/dist/mcp-data/registry/conversation-list-item.json +2 -2
  176. package/dist/mcp-data/registry/input.json +1 -1
  177. package/dist/mcp-data/registry/loader.json +2 -2
  178. package/dist/mcp-data/registry/mobile-bar-nav.json +333 -0
  179. package/dist/mcp-data/registry/mobile-header.json +351 -0
  180. package/dist/mcp-data/registry/mobile-section-switcher.json +210 -0
  181. package/dist/mcp-data/registry/mobile-sheet-nav.json +317 -0
  182. package/dist/mcp-data/registry/panel-nav.json +2 -2
  183. package/dist/mcp-data/registry/panel-tools.json +2 -2
  184. package/dist/mcp-data/registry/radio.json +1 -1
  185. package/dist/mcp-data/registry/registry.json +1544 -1429
  186. package/dist/mcp-data/registry/select-multi.json +1 -1
  187. package/dist/mcp-data/registry/select.json +2 -2
  188. package/dist/mcp-data/registry/shell-app.json +17 -17
  189. package/dist/mcp-data/registry/shell-page.json +26 -7
  190. package/dist/mcp-data/registry/shell-tools.json +10 -7
  191. package/dist/mcp-data/registry/switch.json +1 -1
  192. package/dist/mcp-data/registry/toast.json +2 -2
  193. package/dist/react/components.d.ts +4 -3
  194. package/dist/react/components.js +4 -3
  195. package/dist/react/ds-mobile-bar-nav.d.ts +13 -0
  196. package/dist/react/ds-mobile-bar-nav.js +15 -0
  197. package/dist/react/ds-mobile-header.d.ts +13 -0
  198. package/dist/react/ds-mobile-header.js +15 -0
  199. package/dist/react/ds-mobile-section-switcher.d.ts +12 -0
  200. package/dist/react/ds-mobile-section-switcher.js +12 -0
  201. package/dist/react/ds-mobile-sheet-nav.d.ts +14 -0
  202. package/dist/react/ds-mobile-sheet-nav.js +16 -0
  203. package/dist/types/components/BarWorkflow/BarWorkflow.d.ts +6 -0
  204. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +1 -1
  205. package/dist/types/components/MobileBarNav/MobileBarNav.d.ts +26 -0
  206. package/dist/types/components/MobileBarNav/index.d.ts +4 -0
  207. package/dist/types/components/MobileBarNav/mobile-bar-nav-types.d.ts +5 -0
  208. package/dist/types/components/MobileHeader/MobileHeader.d.ts +39 -0
  209. package/dist/types/components/MobileHeader/index.d.ts +2 -0
  210. package/dist/types/components/MobileHeader/mobile-header-types.d.ts +5 -0
  211. package/dist/types/components/MobileSectionSwitcher/MobileSectionSwitcher.d.ts +35 -0
  212. package/dist/types/components/MobileSectionSwitcher/index.d.ts +3 -0
  213. package/dist/types/components/MobileSectionSwitcher/mobile-section-switcher-types.d.ts +4 -0
  214. package/dist/types/components/MobileSectionSwitcher/mobile-section-switcher-utils.d.ts +10 -0
  215. package/dist/types/components/{ShellMobileNav/ShellMobileNav.d.ts → MobileSheetNav/MobileSheetNav.d.ts} +5 -7
  216. package/dist/types/components/MobileSheetNav/index.d.ts +1 -0
  217. package/dist/types/components/ShellApp/ShellApp.d.ts +4 -4
  218. package/dist/types/components/ShellPage/ShellPage.d.ts +4 -0
  219. package/dist/types/components.d.ts +530 -381
  220. package/dist/types/shell/index.d.ts +1 -1
  221. package/dist/types/shell/shell-responsive.d.ts +3 -3
  222. package/dist/types/utils/index.d.ts +1 -0
  223. package/dist/types/utils/required-validity.d.ts +15 -0
  224. package/package.json +1 -1
  225. package/dist/angular/ds-shell-mobile-bar.d.ts +0 -18
  226. package/dist/angular/ds-shell-mobile-nav.d.ts +0 -23
  227. package/dist/angular/ds-shell-mobile-section-nav.d.ts +0 -18
  228. package/dist/components/ds-shell-mobile-bar.js +0 -2
  229. package/dist/components/ds-shell-mobile-bar.js.map +0 -1
  230. package/dist/components/ds-shell-mobile-nav.js +0 -2
  231. package/dist/components/ds-shell-mobile-nav.js.map +0 -1
  232. package/dist/components/ds-shell-mobile-section-nav.d.ts +0 -11
  233. package/dist/components/ds-shell-mobile-section-nav.js +0 -2
  234. package/dist/components/ds-shell-mobile-section-nav.js.map +0 -1
  235. package/dist/components/p-B6Vuayt6.js +0 -2
  236. package/dist/components/p-B6Vuayt6.js.map +0 -1
  237. package/dist/components/p-BPS9VExm.js +0 -2
  238. package/dist/components/p-BVV_rlIP.js +0 -2
  239. package/dist/components/p-BVV_rlIP.js.map +0 -1
  240. package/dist/components/p-BhxwpOH8.js +0 -2
  241. package/dist/components/p-BtEjlcB9.js +0 -2
  242. package/dist/components/p-BtEjlcB9.js.map +0 -1
  243. package/dist/components/p-CH6cNXXF.js +0 -2
  244. package/dist/components/p-CH6cNXXF.js.map +0 -1
  245. package/dist/components/p-C_0Q8Cnp.js +0 -2
  246. package/dist/components/p-Ce52yVXF.js +0 -2
  247. package/dist/components/p-Ce52yVXF.js.map +0 -1
  248. package/dist/components/p-CgHTNfC1.js +0 -2
  249. package/dist/components/p-CgHTNfC1.js.map +0 -1
  250. package/dist/components/p-Co8hD3P-.js +0 -2
  251. package/dist/components/p-CoYFJD-w.js +0 -2
  252. package/dist/components/p-CoYFJD-w.js.map +0 -1
  253. package/dist/components/p-Cpr3K41-.js +0 -2
  254. package/dist/components/p-Cpr3K41-.js.map +0 -1
  255. package/dist/components/p-CtD24EyI.js +0 -2
  256. package/dist/components/p-DYqReipj.js +0 -2
  257. package/dist/components/p-DYqReipj.js.map +0 -1
  258. package/dist/components/p-NUNsefU1.js +0 -2
  259. package/dist/components/p-PZ6R_nGI.js +0 -2
  260. package/dist/components/p-jCWtxthA.js +0 -2
  261. package/dist/components/p-yhj1lIPx.js +0 -2
  262. package/dist/mcp-data/registry/shell-mobile-bar.json +0 -314
  263. package/dist/mcp-data/registry/shell-mobile-nav.json +0 -348
  264. package/dist/mcp-data/registry/shell-mobile-section-nav.json +0 -267
  265. package/dist/react/ds-shell-mobile-bar.d.ts +0 -13
  266. package/dist/react/ds-shell-mobile-bar.js +0 -15
  267. package/dist/react/ds-shell-mobile-nav.d.ts +0 -15
  268. package/dist/react/ds-shell-mobile-nav.js +0 -17
  269. package/dist/react/ds-shell-mobile-section-nav.d.ts +0 -12
  270. package/dist/react/ds-shell-mobile-section-nav.js +0 -12
  271. package/dist/types/components/ShellMobileBar/ShellMobileBar.d.ts +0 -25
  272. package/dist/types/components/ShellMobileBar/index.d.ts +0 -4
  273. package/dist/types/components/ShellMobileBar/shell-mobile-bar-types.d.ts +0 -5
  274. package/dist/types/components/ShellMobileNav/index.d.ts +0 -2
  275. package/dist/types/components/ShellMobileNav/shell-mobile-nav-types.d.ts +0 -6
  276. package/dist/types/components/ShellMobileSectionNav/ShellMobileSectionNav.d.ts +0 -30
  277. package/dist/types/components/ShellMobileSectionNav/index.d.ts +0 -2
  278. /package/dist/components/{p-9dQQSgwT.js.map → p-BHYrsGBw.js.map} +0 -0
  279. /package/dist/components/{p-jCWtxthA.js.map → p-BY0PzkUp.js.map} +0 -0
  280. /package/dist/components/{p-yhj1lIPx.js.map → p-C2ym_Ich.js.map} +0 -0
  281. /package/dist/components/{p-Biz6xo-z.js.map → p-CFpWrYAH.js.map} +0 -0
  282. /package/dist/components/{p-g40DTeV8.js.map → p-CvKKmZJj.js.map} +0 -0
  283. /package/dist/components/{p-DXnFhmZF.js.map → p-D9iN80yX.js.map} +0 -0
  284. /package/dist/components/{p-DjPZxzIG.js.map → p-DQDpDYyF.js.map} +0 -0
@@ -1057,6 +1057,7 @@
1057
1057
  ],
1058
1058
  "commonlyComposedWith": [
1059
1059
  "component:ds-shell-page",
1060
+ "component:ds-mobile-header",
1060
1061
  "component:ds-button-filled",
1061
1062
  "component:ds-button-unfilled",
1062
1063
  "component:ds-text",
@@ -1071,7 +1072,7 @@
1071
1072
  "Use submitAction.type=submit inside a form so the final action preserves native submission semantics."
1072
1073
  ],
1073
1074
  "states": [
1074
- "BarWorkflow always renders compact 48px bold-brand chrome and has no expanded, constrained, or responsive variant.",
1075
+ "BarWorkflow always renders compact 48px bold-brand chrome; responsiveMode changes only the action geometry, never workflow state or hierarchy.",
1075
1076
  "An unrecognized value resolves navigation from the first step without mutating the controlled value.",
1076
1077
  "The first step omits Previous. Intermediate steps show Previous and Next. The last step replaces Next with the Check Save or Submit action.",
1077
1078
  "The default empty steps array is a single-step flow with the plain heading, no Previous control, and the final action visible. An explicit one-step array behaves the same way.",
@@ -1079,7 +1080,8 @@
1079
1080
  "submitAction owns the final label, native button type, inactive state, and loading state."
1080
1081
  ],
1081
1082
  "responsiveBehavior": [
1082
- "BarWorkflow does not expose a presentation variant and never collapses its navigation actions.",
1083
+ "Desktop and tablet keep the established left-aligned identity and trailing actions.",
1084
+ "Mobile uses symmetric MobileHeader geometry with Exit leading, the title and step count centered, and Previous plus Next or Submit trailing.",
1083
1085
  "The heading truncates before Exit, Previous, and Next or Submit lose their complete hit targets.",
1084
1086
  "When slotted into ShellPage, BarWorkflow remains compact while ShellPage continues to provide sticky placement."
1085
1087
  ],
@@ -1133,6 +1135,10 @@
1133
1135
  "type": "string",
1134
1136
  "required": false
1135
1137
  },
1138
+ "responsiveMode": {
1139
+ "type": "ShellResponsiveMode",
1140
+ "required": false
1141
+ },
1136
1142
  "steps": {
1137
1143
  "type": "BarWorkflowStep[]",
1138
1144
  "required": false
@@ -1174,6 +1180,7 @@
1174
1180
  "registryDependencies": [
1175
1181
  "button-filled",
1176
1182
  "button-unfilled",
1183
+ "mobile-header",
1177
1184
  "text",
1178
1185
  "tooltip"
1179
1186
  ]
@@ -4957,497 +4964,312 @@
4957
4964
  ]
4958
4965
  },
4959
4966
  {
4960
- "name": "modal",
4961
- "title": "Modal",
4962
- "description": "Dismissible native top-layer dialog for a focused confirmation or short blocking task, with a fixed title-and-close header, composable content, and an optional two-action footer.",
4967
+ "name": "mobile-bar-nav",
4968
+ "title": "MobileBarNav",
4969
+ "description": "Persistent mobile shell navigation for Menu, the router-derived current area, Search, Agents, and Inbox.",
4963
4970
  "type": "registry:ui",
4964
4971
  "meta": {
4965
4972
  "library": "@ds-mo/ui",
4966
4973
  "distribution": "npm",
4967
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/modal",
4968
- "source": "src/wc/components/Modal/Modal.tsx",
4974
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/mobile-bar-nav",
4975
+ "source": "src/wc/components/MobileBarNav/MobileBarNav.tsx",
4969
4976
  "intentStatus": "complete",
4970
4977
  "intent": {
4971
- "audience": "general",
4972
- "status": "stable",
4973
- "summary": "Dismissible native top-layer dialog for a focused confirmation or short blocking task, with a fixed title-and-close header, composable content, and an optional two-action footer.",
4978
+ "audience": "specialized",
4979
+ "status": "experimental",
4980
+ "summary": "Persistent mobile shell navigation for Menu, the router-derived current area, Search, Agents, and Inbox.",
4974
4981
  "useWhen": [
4975
- "The user must confirm or cancel one focused decision before returning to the underlying interface.",
4976
- "A short blocking task or compact form needs dialog semantics, focus containment, and explicit completion actions.",
4977
- "The content can be safely dismissed through Close, Escape, or the backdrop."
4982
+ "ShellApp is rendering its dedicated below-768px application composition."
4978
4983
  ],
4979
4984
  "avoidWhen": [
4980
- "The message is non-blocking feedback or a transient status update.",
4981
- "The interaction is a contextual list of commands anchored to a trigger.",
4982
- "The workflow is multi-step, long-form, or requires substantial navigation.",
4983
- "Dismissal would lose work or leave an irreversible operation in an unsafe state.",
4984
- "A second modal would be opened over an existing modal."
4985
- ],
4986
- "alternatives": [
4987
- {
4988
- "when": "The user needs non-blocking feedback or a transient status message.",
4989
- "component": "component:ds-toast",
4990
- "reason": "Toast communicates transient status without trapping focus or blocking the page."
4991
- },
4992
- {
4993
- "when": "A trigger reveals a short contextual list of commands.",
4994
- "component": "component:ds-menu",
4995
- "reason": "Menu provides anchored command semantics without creating a blocking dialog."
4996
- },
4997
- {
4998
- "when": "Editable settings should remain visible without blocking the rest of the interface.",
4999
- "component": "component:ds-card-setting",
5000
- "reason": "CardSetting provides a persistent controlled settings workflow without modal focus containment."
5001
- }
4985
+ "Rendering desktop or tablet shell chrome.",
4986
+ "An arbitrary set of product tabs is required."
5002
4987
  ],
5003
4988
  "commonlyComposedWith": [
5004
- "component:ds-button-filled",
5005
- "component:ds-button-unfilled",
5006
- "component:ds-field",
5007
- "component:ds-text"
4989
+ "component:ds-shell-app"
4990
+ ],
4991
+ "patterns": [
4992
+ "pattern:application-shell"
5008
4993
  ],
5009
4994
  "accessibility": [
5010
- "Provide a concise visible heading; the component uses it as the dialog's accessible name.",
5011
- "Give the primary explanatory copy a stable id and pass it through aria-describedby so assistive technology receives the decision context.",
5012
- "Opening the native modal dialog moves focus to the header Close action, whose visible tooltip matches its accessible name, traps Tab navigation inside the top layer, and makes outside content inert.",
5013
- "Close, Escape, and backdrop activation emit dsClose with close-button, escape, or backdrop reason before beginning dismissal; use the component only when every dismissal path is safe.",
5014
- "After exit motion completes, the native dialog leaves the top layer, focus returns to the previously focused element, and dsAfterClose emits.",
5015
- "Use visible label-only footer buttons. Keep at most two actions: one bold filled primary action followed by one bordered unfilled action, or two bordered unfilled actions.",
5016
- "Use negative intent for a filled destructive action and state the irreversible consequence in the content.",
5017
- "Do not open a modal from another modal; keep one blocking decision in focus at a time."
4995
+ "Every icon-only item keeps a localized accessible name.",
4996
+ "Only the active destination exposes aria-current; Menu exposes its controlled pane through aria-expanded."
5018
4997
  ],
5019
4998
  "states": [
5020
- "The owner opens the modal through the open property and responds to the typed dsClose detail for application state synchronization or dismissal analytics.",
5021
- "The component mutates open to false for Close, Escape, and backdrop dismissal while retaining its rendered surface through exit motion.",
5022
- "The default slot owns task content; the named footer slot is optional and is hidden when no actions are assigned.",
5023
- "Primary actions use a bold filled button with semantic intent. Secondary and cancel actions use bordered label-only unfilled buttons.",
5024
- "The owner performs save, delete, cancel, and other product consequences before or while closing the modal."
4999
+ "The fixed groups are Menu plus current area, followed by Search, Inbox, and Agents.",
5000
+ "Selection promotes foreground to primary without painting a selected fill; unselected destinations use tertiary foreground.",
5001
+ "Opening Mobile Sheet Nav replaces the Menu glyph with Cross while preserving its accessible name.",
5002
+ "Reselecting an active destination does not reset its nested state."
5025
5003
  ],
5026
5004
  "responsiveBehavior": [
5027
- "Choose the smallest sm, md, or lg width that fits the focused task; the top-layer dialog clamps to the viewport with token-based outer space.",
5028
- "Content scrolls independently when needed while the 64px header and optional 64px footer remain fixed.",
5029
- "Avoid layouts whose minimum content width exceeds the narrow viewport clamp.",
5030
- "The native top layer escapes transformed ancestors, clipping containers, and application stacking contexts without moving slotted content."
5005
+ "Render only below the mobile breakpoint and preserve safe-area clearance.",
5006
+ "The two icon-only control groups remain centered with fixed 40px targets and a divider between Menu and current area."
5031
5007
  ],
5032
- "frameworkCaveats": {
5033
- "customElements": [
5034
- "Set open as a JavaScript property when controlling the modal; inspect dsClose.detail.reason and use dsAfterClose for cleanup that must wait for exit motion and focus restoration.",
5035
- "Connect the most relevant slotted explanatory text through aria-describedby.",
5036
- "Footer actions are slotted application-owned controls and must implement their own product consequence."
5037
- ],
5038
- "react": [
5039
- "Pass open to DsModal, inspect onDsClose event detail, and use onDsAfterClose only for cleanup after exit motion and focus restoration.",
5040
- "Connect the most relevant slotted explanatory text through aria-describedby.",
5041
- "Assign footer controls with slot=\"footer\" and handle each action before updating open."
5042
- ],
5043
- "angular": [
5044
- "Bind [open], inspect $event.detail from (dsClose), and use (dsAfterClose) only for cleanup after exit motion and focus restoration.",
5045
- "Connect the most relevant slotted explanatory text through aria-describedby.",
5046
- "Assign footer controls with slot=\"footer\" and handle each action before updating open."
5047
- ]
5048
- },
5049
5008
  "references": [
5050
5009
  {
5051
- "label": "Storybook confirmation and footer examples",
5052
- "path": "src/wc/components/Modal/Modal.stories.ts"
5053
- },
5054
- {
5055
- "label": "Cross-browser focus, dismissal, geometry, and accessibility coverage",
5056
- "path": "tests/e2e/accessibility-overlays.spec.ts"
5057
- },
5058
- {
5059
- "label": "Reduced-motion overlay coverage",
5060
- "path": "tests/e2e/reduced-motion.spec.ts"
5010
+ "label": "Storybook",
5011
+ "path": "src/wc/components/MobileBarNav/MobileBarNav.stories.ts"
5061
5012
  }
5062
5013
  ]
5063
5014
  },
5064
5015
  "props": {
5065
- "ariaDescribedby": {
5066
- "type": "string | undefined",
5016
+ "activeDestination": {
5017
+ "type": "MobileDestination",
5067
5018
  "required": false
5068
5019
  },
5069
- "closeAriaLabel": {
5020
+ "agentsDot": {
5021
+ "type": "boolean",
5022
+ "required": false
5023
+ },
5024
+ "agentsLabel": {
5070
5025
  "type": "string",
5071
5026
  "required": false
5072
5027
  },
5073
- "heading": {
5028
+ "currentArea": {
5029
+ "type": "PanelNavItem",
5030
+ "required": false
5031
+ },
5032
+ "helpLabel": {
5074
5033
  "type": "string",
5075
- "required": true
5034
+ "required": false
5076
5035
  },
5077
- "modalWidth": {
5078
- "type": "ModalWidth | string",
5036
+ "inboxDot": {
5037
+ "type": "boolean",
5079
5038
  "required": false
5080
5039
  },
5081
- "open": {
5040
+ "inboxLabel": {
5041
+ "type": "string",
5042
+ "required": false
5043
+ },
5044
+ "menuLabel": {
5045
+ "type": "string",
5046
+ "required": false
5047
+ },
5048
+ "searchDot": {
5049
+ "type": "boolean",
5050
+ "required": false
5051
+ },
5052
+ "searchLabel": {
5053
+ "type": "string",
5054
+ "required": false
5055
+ },
5056
+ "sheetNavExpanded": {
5082
5057
  "type": "boolean",
5083
5058
  "required": false
5084
5059
  }
5085
5060
  },
5086
5061
  "events": [
5087
5062
  {
5088
- "name": "dsAfterClose",
5089
- "detail": "void"
5063
+ "name": "dsDestinationChange",
5064
+ "detail": "MobileBarNavDestinationDetail"
5090
5065
  },
5091
5066
  {
5092
- "name": "dsClose",
5093
- "detail": "ModalCloseDetail"
5067
+ "name": "dsSheetNavToggle",
5068
+ "detail": "boolean"
5094
5069
  }
5095
5070
  ],
5096
5071
  "slots": [],
5097
5072
  "exports": {
5098
- "customElement": "ds-modal",
5099
- "react": "DsModal",
5100
- "angular": "DsModal"
5073
+ "customElement": "ds-mobile-bar-nav",
5074
+ "react": "DsMobileBarNav",
5075
+ "angular": "DsMobileBarNav"
5101
5076
  }
5102
5077
  },
5103
5078
  "dependencies": [
5104
5079
  "@ds-mo/ui",
5105
- "@ds-mo/tokens"
5080
+ "@ds-mo/tokens",
5081
+ "@ds-mo/icons"
5106
5082
  ],
5107
5083
  "registryDependencies": [
5108
- "button-unfilled",
5109
- "text",
5110
- "tooltip"
5084
+ "badge",
5085
+ "icon"
5111
5086
  ]
5112
5087
  },
5113
5088
  {
5114
- "name": "panel-nav",
5115
- "title": "PanelNav",
5116
- "description": "The single persistent primary navigation for an application, providing grouped top-level destinations, active-route state, standard dashboard/settings switching, user access, and collapsible desktop and tablet presentation.",
5089
+ "name": "mobile-header",
5090
+ "title": "MobileHeader",
5091
+ "description": "Consistent mobile top chrome with symmetric action lanes, a centered page identity or peer-section chooser, and an optional subordinate page-section row.",
5117
5092
  "type": "registry:ui",
5118
5093
  "meta": {
5119
5094
  "library": "@ds-mo/ui",
5120
5095
  "distribution": "npm",
5121
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-nav",
5122
- "source": "src/wc/components/PanelNav/PanelNav.tsx",
5096
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/mobile-header",
5097
+ "source": "src/wc/components/MobileHeader/MobileHeader.tsx",
5123
5098
  "intentStatus": "complete",
5124
5099
  "intent": {
5125
5100
  "audience": "specialized",
5126
- "status": "stable",
5127
- "summary": "The single persistent primary navigation for an application, providing grouped top-level destinations, active-route state, standard dashboard/settings switching, user access, and collapsible desktop and tablet presentation.",
5101
+ "status": "experimental",
5102
+ "summary": "Consistent mobile top chrome with symmetric action lanes, a centered page identity or peer-section chooser, and an optional subordinate page-section row.",
5128
5103
  "useWhen": [
5129
- "Building the one primary navigation surface for an application that uses the CompoMo system.",
5130
- "Top-level destinations must remain consistently available while the application's page content changes.",
5131
- "Primary destinations need visual grouping, icons, notification indicators, active-route state, and expanded or collapsed presentation."
5104
+ "A routed page, persistent tool, account surface, or workflow needs the canonical mobile header presentation."
5132
5105
  ],
5133
5106
  "avoidWhen": [
5134
- "A second navigation surface is needed within the same application; an application must have only one PanelNav.",
5135
- "The choices represent sections within the active primary destination; use BarNav instead.",
5136
- "The choices switch local content without changing the application's primary destination; use TabGroup instead.",
5137
- "The interaction performs a command or presents temporary contextual choices; use a button or Menu instead.",
5138
- "Building navigation below the mobile breakpoint; use the application's dedicated mobile navigation component instead."
5139
- ],
5140
- "alternatives": [
5141
- {
5142
- "when": "The choices represent route sections within the active primary destination.",
5143
- "component": "component:ds-bar-nav",
5144
- "reason": "BarNav owns secondary section navigation within the destination selected by PanelNav."
5145
- },
5146
- {
5147
- "when": "The choices switch local content without changing the application's primary destination.",
5148
- "component": "component:ds-tab-group",
5149
- "reason": "TabGroup owns local view selection and tab semantics."
5150
- },
5151
- {
5152
- "when": "The choices are commands or temporary contextual actions.",
5153
- "component": "component:ds-menu",
5154
- "reason": "Menu owns transient action and option collections rather than persistent destinations."
5155
- }
5107
+ "Rendering desktop BarTitle, BarNav, or PanelToolHeader.",
5108
+ "Rendering the Mobile Sheet Nav utility lane."
5156
5109
  ],
5157
5110
  "commonlyComposedWith": [
5158
- "component:ds-shell-app",
5159
- "component:ds-bar-nav",
5160
- "component:ds-panel-tools",
5161
- "component:ds-menu"
5111
+ "component:ds-mobile-section-switcher",
5112
+ "component:ds-shell-page",
5113
+ "component:ds-shell-tools"
5162
5114
  ],
5163
5115
  "patterns": [
5164
5116
  "pattern:application-shell"
5165
5117
  ],
5166
5118
  "accessibility": [
5167
- "Give every primary destination a concise visible label and an icon that supports rather than replaces that label.",
5168
- "Provide localized dashboard, settings, account, navigation, collapse, and expand labels.",
5169
- "Preserve accessible destination names when the panel is collapsed to icon-only presentation.",
5170
- "Use notification dots as supplemental status and never as the only indication of important information.",
5171
- "When the destination body overflows, it becomes a localized keyboard-focusable scroll region in addition to the roving destination controls.",
5172
- "Keep the standard dashboard/settings switch and user/account entry available in the footer."
5119
+ "Static screens render a real h1 or h2 according to headingLevel.",
5120
+ "Section-switching screens expose an equivalent semantic heading alongside the accessible popup trigger.",
5121
+ "Subsections use a separately named navigation landmark and never replace the semantic page identity.",
5122
+ "Leading and trailing slotted icon actions retain their own accessible names and tooltips."
5173
5123
  ],
5174
5124
  "states": [
5175
- "Render exactly one PanelNav per application; it owns primary application destinations and no other navigation role.",
5176
- "The host router owns the current route; prefer currentUrl for active destination matching and use activeId only when route matching is unavailable.",
5177
- "Use anchor mode for native links or routers that intercept anchors; use event mode when the host performs navigation from dsNavSelect.",
5178
- "Groups visually organize top-level destinations only and must not be interpreted as nested or expandable navigation.",
5179
- "Dashboard presents day-to-day operational destinations; Settings presents administrative and configuration destinations.",
5180
- "The standard footer switches the entire destination collection and navStyle between Dashboard and Settings and exposes the user/account entry.",
5181
- "The host owns the external user menu opened from dsNavUserAction.",
5182
- "Item and header controls inherit the shared md control radius while local shell geometry continues to own collapsed layout and footer animation positioning.",
5183
- "On desktop, allow user-controlled expand and collapse and persist the preference with storageKey when cross-session persistence is appropriate."
5125
+ "Without multiple sections the center renders heading.",
5126
+ "With multiple sections the center renders the controlled MobileSectionSwitcher.",
5127
+ "Optional subsections render in a second row and emit dsSubsectionChange without changing the primary section.",
5128
+ "Sections represent peer destinations at the current navigation level; subsections represent local views beneath the selected page or detail identity.",
5129
+ "Brand tone changes surface and foreground without changing geometry or interaction ownership."
5184
5130
  ],
5185
5131
  "responsiveBehavior": [
5186
- "At 1200px and wider, default to expanded, allow the user to expand or collapse, and restore the locally persisted desktop preference when available.",
5187
- "From 768px through 1199px, present PanelNav permanently collapsed and do not allow user expansion.",
5188
- "Below 768px, the consuming application replaces PanelNav with a dedicated mobile navigation component; PanelNav does not own mobile navigation.",
5189
- "ShellApp permanently owns responsive composition: it determines shell mode, enforces tablet collapse, and replaces PanelNav with future mobile navigation below 768px.",
5190
- "When the viewport is below breakpoint, PanelNav locks collapsed, disables its header toggle affordance, and preserves the persisted desktop collapse preference.",
5191
- "Collapsed presentation must preserve destination ordering, active state, notification status, and accessible names."
5132
+ "The primary 48px lane is dedicated to the below-768px presentation; optional subsections add one subordinate 48px lane.",
5133
+ "Equal flexible side lanes keep the center mathematically aligned when actions are asymmetric."
5192
5134
  ],
5193
- "frameworkCaveats": {
5194
- "customElements": [
5195
- "Assign groups as a JavaScript property for structured data; a JSON string attribute is also supported.",
5196
- "Set nav-style before the element connects when first-paint style must match the current route."
5197
- ],
5198
- "react": [
5199
- "Pass groups as an array through the generated React wrapper and synchronize currentUrl with the host router.",
5200
- "ShellApp owns mobile replacement; PanelNav enforces its configured breakpoint expansion lock."
5201
- ],
5202
- "angular": [
5203
- "Import DsPanelNav from @ds-mo/ui/angular/ds-panel-nav and bind groups as a property.",
5204
- "Bind both the nav-style attribute and navStyle property when first-paint route styling must be deterministic.",
5205
- "ShellApp owns mobile replacement; PanelNav enforces its configured breakpoint expansion lock."
5206
- ]
5207
- },
5208
5135
  "references": [
5209
5136
  {
5210
- "label": "Executable Storybook examples",
5211
- "path": "src/wc/components/PanelNav/PanelNav.stories.ts"
5212
- },
5213
- {
5214
- "label": "Framework and routing integration",
5215
- "path": "docs/framework-integration.md"
5216
- },
5217
- {
5218
- "label": "Application shell composition",
5219
- "path": "agent/patterns/application-shell/pattern.agent.json"
5137
+ "label": "Storybook",
5138
+ "path": "src/wc/components/MobileHeader/MobileHeader.stories.ts"
5220
5139
  }
5221
5140
  ]
5222
5141
  },
5223
5142
  "props": {
5224
- "accountLabel": {
5143
+ "heading": {
5225
5144
  "type": "string",
5226
5145
  "required": false
5227
5146
  },
5228
- "accountMenuExpanded": {
5229
- "type": "boolean",
5147
+ "headingLevel": {
5148
+ "type": "MobileHeaderHeadingLevel",
5230
5149
  "required": false
5231
5150
  },
5232
- "activeId": {
5233
- "type": "string",
5151
+ "sections": {
5152
+ "type": "TabItem[]",
5234
5153
  "required": false
5235
5154
  },
5236
- "breakpoint": {
5237
- "type": "number",
5155
+ "sectionsAriaLabel": {
5156
+ "type": "string",
5238
5157
  "required": false
5239
5158
  },
5240
- "collapseNavigationLabel": {
5159
+ "sectionsJson": {
5241
5160
  "type": "string",
5242
5161
  "required": false
5243
5162
  },
5244
- "collapsed": {
5245
- "type": "boolean",
5163
+ "subsections": {
5164
+ "type": "TabItem[]",
5246
5165
  "required": false
5247
5166
  },
5248
- "currentUrl": {
5167
+ "subsectionsAriaLabel": {
5249
5168
  "type": "string",
5250
5169
  "required": false
5251
5170
  },
5252
- "dashboardLabel": {
5171
+ "subsectionsJson": {
5253
5172
  "type": "string",
5254
5173
  "required": false
5255
5174
  },
5256
- "dashboardNavigationLabel": {
5175
+ "subvalue": {
5257
5176
  "type": "string",
5258
5177
  "required": false
5259
5178
  },
5260
- "disableViewTransition": {
5261
- "type": "boolean",
5262
- "required": false
5263
- },
5264
- "expandNavigationLabel": {
5265
- "type": "string",
5266
- "required": false
5267
- },
5268
- "groups": {
5269
- "type": "string | PanelNavGroup[]",
5270
- "required": false
5271
- },
5272
- "navStyle": {
5273
- "type": "NavChromeStyle",
5274
- "required": false
5275
- },
5276
- "navigationItemsLabel": {
5277
- "type": "string",
5278
- "required": false
5279
- },
5280
- "routerMode": {
5281
- "type": "PanelNavRouterMode",
5282
- "required": false
5283
- },
5284
- "settingsLabel": {
5285
- "type": "string",
5286
- "required": false
5287
- },
5288
- "settingsNavigationLabel": {
5289
- "type": "string",
5290
- "required": false
5291
- },
5292
- "storageKey": {
5293
- "type": "string",
5294
- "required": false
5295
- },
5296
- "userInitial": {
5297
- "type": "string",
5179
+ "tone": {
5180
+ "type": "MobileHeaderTone",
5298
5181
  "required": false
5299
5182
  },
5300
- "userName": {
5183
+ "value": {
5301
5184
  "type": "string",
5302
5185
  "required": false
5303
5186
  }
5304
5187
  },
5305
5188
  "events": [
5306
5189
  {
5307
- "name": "dsChromeTransitionEnd",
5308
- "detail": "ChromeTransitionDetail"
5309
- },
5310
- {
5311
- "name": "dsChromeTransitionStart",
5312
- "detail": "ChromeTransitionDetail"
5313
- },
5314
- {
5315
- "name": "dsNavFooterAction",
5316
- "detail": "void"
5317
- },
5318
- {
5319
- "name": "dsNavSelect",
5190
+ "name": "dsSectionChange",
5320
5191
  "detail": "string"
5321
5192
  },
5322
5193
  {
5323
- "name": "dsNavToggle",
5324
- "detail": "boolean"
5325
- },
5326
- {
5327
- "name": "dsNavUserAction",
5328
- "detail": "PanelNavUserActionDetail"
5194
+ "name": "dsSubsectionChange",
5195
+ "detail": "string"
5329
5196
  }
5330
5197
  ],
5331
5198
  "slots": [],
5332
5199
  "exports": {
5333
- "customElement": "ds-panel-nav",
5334
- "react": "DsPanelNav",
5335
- "angular": "DsPanelNav"
5200
+ "customElement": "ds-mobile-header",
5201
+ "react": "DsMobileHeader",
5202
+ "angular": "DsMobileHeader"
5336
5203
  }
5337
5204
  },
5338
5205
  "dependencies": [
5339
5206
  "@ds-mo/ui",
5340
- "@ds-mo/tokens",
5341
- "@ds-mo/icons"
5207
+ "@ds-mo/tokens"
5342
5208
  ],
5343
5209
  "registryDependencies": [
5344
- "badge",
5345
- "button-unfilled",
5346
- "icon",
5347
- "text",
5348
- "tooltip"
5210
+ "mobile-section-switcher",
5211
+ "text"
5349
5212
  ]
5350
5213
  },
5351
5214
  {
5352
- "name": "panel-sub-nav",
5353
- "title": "PanelSubNav",
5354
- "description": "Persistent vertical tab navigation for a panel or card side rail, switching adjacent local content with menu-like selected fill and stable text weight.",
5215
+ "name": "mobile-section-switcher",
5216
+ "title": "MobileSectionSwitcher",
5217
+ "description": "Controlled mobile section chooser showing the current section, adjacent-position hints, and a complete tap menu.",
5355
5218
  "type": "registry:ui",
5356
5219
  "meta": {
5357
5220
  "library": "@ds-mo/ui",
5358
5221
  "distribution": "npm",
5359
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-sub-nav",
5360
- "source": "src/wc/components/PanelSubNav/PanelSubNav.tsx",
5222
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/mobile-section-switcher",
5223
+ "source": "src/wc/components/MobileSectionSwitcher/MobileSectionSwitcher.tsx",
5361
5224
  "intentStatus": "complete",
5362
5225
  "intent": {
5363
- "audience": "general",
5364
- "status": "stable",
5365
- "summary": "Persistent vertical tab navigation for a panel or card side rail, switching adjacent local content with menu-like selected fill and stable text weight.",
5226
+ "audience": "specialized",
5227
+ "status": "experimental",
5228
+ "summary": "Controlled mobile section chooser showing the current section, adjacent-position hints, and a complete tap menu.",
5366
5229
  "useWhen": [
5367
- "A panel or card side rail needs a persistent vertical list that switches adjacent local content.",
5368
- "Each concise text label controls an immediately available tabpanel without changing application routes."
5230
+ "A mobile page or tool header must combine current-page identity with ordered peer-section navigation."
5369
5231
  ],
5370
5232
  "avoidWhen": [
5371
- "The navigation is not contained in a panel or card side rail.",
5372
- "Local views should be arranged horizontally; use TabGroup instead.",
5373
- "The choices navigate routes in application shell chrome; use PanelNav or BarNav instead.",
5374
- "The choices are temporary commands or contextual options; use Menu instead.",
5375
- "Rows need icons, subtext, notification dots, nested levels, or section headers."
5376
- ],
5377
- "alternatives": [
5378
- {
5379
- "when": "Local panel choices fit a horizontal tab row.",
5380
- "component": "component:ds-tab-group",
5381
- "reason": "TabGroup is the horizontal local-view counterpart."
5382
- },
5383
- {
5384
- "when": "The choices are primary application destinations.",
5385
- "component": "component:ds-panel-nav",
5386
- "reason": "PanelNav owns primary application navigation."
5387
- },
5388
- {
5389
- "when": "The choices are secondary application routes.",
5390
- "component": "component:ds-bar-nav",
5391
- "reason": "BarNav owns route sections inside ShellApp."
5392
- },
5393
- {
5394
- "when": "The choices are transient actions or options.",
5395
- "component": "component:ds-menu",
5396
- "reason": "Menu owns temporary popup collections."
5397
- }
5233
+ "Rendering desktop BarNav.",
5234
+ "The destination collection is primary application navigation."
5398
5235
  ],
5399
5236
  "commonlyComposedWith": [
5400
- "component:ds-card-setting",
5401
- "component:ds-text"
5237
+ "component:ds-mobile-header"
5238
+ ],
5239
+ "patterns": [
5240
+ "pattern:application-shell"
5402
5241
  ],
5403
5242
  "accessibility": [
5404
- "Provide an accessible name with aria-label or aria-labelledby.",
5405
- "Give every item a unique id and the id of its controlled tabpanel.",
5406
- "Keep each controlled tabpanel labelled by its matching item id.",
5407
- "Always provide a valid selected item when enabled items exist so exactly one tab and panel are active.",
5408
- "ArrowUp and ArrowDown move and activate selection; Home and End select the first and last available items.",
5409
- "Do not use selected text weight as the selection cue; active fill and primary foreground communicate selection."
5243
+ "The trigger exposes the current section, popup relationship, and expanded state.",
5244
+ "Decorative previous and next position hints are hidden from assistive technology.",
5245
+ "The menu is always available so a future swipe gesture is never the only navigation mechanism."
5410
5246
  ],
5411
5247
  "states": [
5412
- "The parent owns the canonical selected value and panel visibility, and should update both from dsChange.",
5413
- "A missing, empty, or unknown selected value is invalid when enabled items exist; the component does not choose a fallback selection.",
5414
- "Inactive items remain visible but cannot be focused or selected.",
5415
- "Selection is singular and follows keyboard focus.",
5416
- "The omitted default surface treatment is for primary and secondary parent surfaces and uses the brand-active selected fill; pass faint explicitly on faint surfaces to use the neutral active fill.",
5417
- "Rows contain one text label only and do not express nested navigation or grouped hierarchy."
5248
+ "Selection is controlled and dsChange reports intent without mutating value.",
5249
+ "Dividers group menu items but never participate in previous or next resolution.",
5250
+ "The first and last selectable sections expose only the available neighboring direction."
5418
5251
  ],
5419
5252
  "responsiveBehavior": [
5420
- "The component remains vertical at every width.",
5421
- "The consuming panel owns responsive adaptation and decides whether to reposition or replace the side rail."
5253
+ "Use only in the dedicated mobile header presentation."
5422
5254
  ],
5423
- "frameworkCaveats": {
5424
- "customElements": [
5425
- "Assign items as a JavaScript property because structured arrays are not represented by HTML attributes.",
5426
- "Keep value synchronized to a valid enabled item and update the controlled panel from dsChange."
5427
- ],
5428
- "react": [
5429
- "Pass items as an array through the generated wrapper, keep value controlled, and use onDsChange to synchronize the visible panel."
5430
- ],
5431
- "angular": [
5432
- "Bind items and a valid value as properties, and handle dsChange to synchronize the visible panel."
5433
- ]
5434
- }
5255
+ "references": [
5256
+ {
5257
+ "label": "Storybook",
5258
+ "path": "src/wc/components/MobileSectionSwitcher/MobileSectionSwitcher.stories.ts"
5259
+ }
5260
+ ]
5435
5261
  },
5436
5262
  "props": {
5437
- "ariaLabel": {
5438
- "type": "string | null",
5439
- "required": false
5440
- },
5441
- "ariaLabelledby": {
5442
- "type": "string | undefined",
5263
+ "navigationLabel": {
5264
+ "type": "string",
5443
5265
  "required": false
5444
5266
  },
5445
- "background": {
5446
- "type": "PanelSubNavBackground | undefined",
5267
+ "sections": {
5268
+ "type": "TabItem[]",
5447
5269
  "required": false
5448
5270
  },
5449
- "items": {
5450
- "type": "PanelSubNavItem[]",
5271
+ "sectionsJson": {
5272
+ "type": "string",
5451
5273
  "required": false
5452
5274
  },
5453
5275
  "value": {
@@ -5463,9 +5285,9 @@
5463
5285
  ],
5464
5286
  "slots": [],
5465
5287
  "exports": {
5466
- "customElement": "ds-panel-sub-nav",
5467
- "react": "DsPanelSubNav",
5468
- "angular": "DsPanelSubNav"
5288
+ "customElement": "ds-mobile-section-switcher",
5289
+ "react": "DsMobileSectionSwitcher",
5290
+ "angular": "DsMobileSectionSwitcher"
5469
5291
  }
5470
5292
  },
5471
5293
  "dependencies": [
@@ -5473,388 +5295,391 @@
5473
5295
  "@ds-mo/tokens"
5474
5296
  ],
5475
5297
  "registryDependencies": [
5298
+ "menu",
5476
5299
  "text"
5477
5300
  ]
5478
5301
  },
5479
5302
  {
5480
- "name": "panel-tool-header",
5481
- "title": "PanelToolHeader",
5482
- "description": "Canonical left-aligned PanelTools header with an optional leading navigation or dismiss action and application-owned trailing icon actions.",
5303
+ "name": "mobile-sheet-nav",
5304
+ "title": "MobileSheetNav",
5305
+ "description": "Full-height mobile navigation sheet with a single brand, context, and utility header above large primary destinations.",
5483
5306
  "type": "registry:ui",
5484
5307
  "meta": {
5485
5308
  "library": "@ds-mo/ui",
5486
5309
  "distribution": "npm",
5487
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tool-header",
5488
- "source": "src/wc/components/PanelToolHeader/PanelToolHeader.tsx",
5310
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/mobile-sheet-nav",
5311
+ "source": "src/wc/components/MobileSheetNav/MobileSheetNav.tsx",
5489
5312
  "intentStatus": "complete",
5490
5313
  "intent": {
5491
- "audience": "general",
5314
+ "audience": "specialized",
5492
5315
  "status": "experimental",
5493
- "summary": "Canonical left-aligned PanelTools header with an optional leading navigation or dismiss action and application-owned trailing icon actions.",
5316
+ "summary": "Full-height mobile navigation sheet with a single brand, context, and utility header above large primary destinations.",
5494
5317
  "useWhen": [
5495
- "PanelTools needs its one shared root or detail header.",
5496
- "A tool header needs a title with optional Back or Close navigation, menu, fullscreen, or other compact icon actions."
5318
+ "The mobile ShellApp Menu control needs to expose the complete primary navigation collection."
5497
5319
  ],
5498
5320
  "avoidWhen": [
5499
- "Rendering inside a PanelTools tool body; PanelTools already composes this canonical header above the body.",
5500
- "The header belongs to page content."
5321
+ "Rendering desktop PanelNav.",
5322
+ "Switching local page content."
5501
5323
  ],
5502
5324
  "commonlyComposedWith": [
5503
- "component:ds-button-unfilled"
5325
+ "component:ds-shell-app",
5326
+ "component:ds-mobile-bar-nav"
5327
+ ],
5328
+ "patterns": [
5329
+ "pattern:application-shell"
5504
5330
  ],
5505
5331
  "accessibility": [
5506
- "Leading navigation or dismiss actions and trailing icon actions require concise localized names; the header reuses each name as the action tooltip.",
5507
- "The visible heading names the active panel or subview."
5332
+ "The sheet is a named navigation landmark and retains visible labels for every primary destination.",
5333
+ "Dashboard and Settings use icon-only tabs with localized accessible names; Help and Account use icon-only actions with matching tooltips.",
5334
+ "Escape requests dismissal and opening moves focus to the selected or first available area."
5508
5335
  ],
5509
5336
  "states": [
5510
- "The title remains left aligned whether the header has no actions, Back, one trailing action, or several trailing actions.",
5511
- "Leading and trailing control zones never shrink; only the title consumes and truncates within the remaining width, with a fixed 4px gap between zones.",
5512
- "Header chrome text is not selectable; actions remain keyboard focusable and interactive.",
5513
- "Adjacent trailing actions keep the shared 4px control gap in drawer and fullscreen presentations.",
5514
- "When fullscreen and overflow actions appear together, author fullscreen before overflow so Ellipses remains the rightmost action.",
5515
- "PanelTools supplies application-owned actions and relays their ids through its shared dsHeaderAction event."
5337
+ "Dashboard and Settings change only the flat destination collection being browsed.",
5338
+ "Area, Help, and Account events express intent while the application owns navigation and product behavior."
5516
5339
  ],
5517
5340
  "responsiveBehavior": [
5518
- "The title truncates between optional leading navigation and trailing action zones."
5341
+ "The pane fills the mobile content stage while the bottom bar remains available."
5519
5342
  ],
5520
5343
  "references": [
5521
5344
  {
5522
- "label": "Standalone examples",
5523
- "path": "src/wc/components/PanelToolHeader/PanelToolHeader.stories.ts"
5345
+ "label": "Storybook",
5346
+ "path": "src/wc/components/MobileSheetNav/MobileSheetNav.stories.ts"
5524
5347
  }
5525
5348
  ]
5526
5349
  },
5527
5350
  "props": {
5528
- "actions": {
5529
- "type": "PanelToolsHeaderAction[]",
5530
- "required": false
5531
- },
5532
- "backAriaLabel": {
5351
+ "accountLabel": {
5533
5352
  "type": "string",
5534
5353
  "required": false
5535
5354
  },
5536
- "backIcon": {
5537
- "type": "string",
5355
+ "browseContext": {
5356
+ "type": "NavChromeStyle",
5538
5357
  "required": false
5539
5358
  },
5540
- "heading": {
5359
+ "currentUrl": {
5541
5360
  "type": "string",
5542
5361
  "required": false
5543
5362
  },
5544
- "menuAriaLabel": {
5545
- "type": "string",
5363
+ "dashboardGroups": {
5364
+ "type": "PanelNavGroup[]",
5546
5365
  "required": false
5547
5366
  },
5548
- "menuControls": {
5549
- "type": "string | undefined",
5367
+ "dashboardLabel": {
5368
+ "type": "string",
5550
5369
  "required": false
5551
5370
  },
5552
- "menuExpanded": {
5553
- "type": "boolean",
5371
+ "helpLabel": {
5372
+ "type": "string",
5554
5373
  "required": false
5555
5374
  },
5556
- "menuTriggerId": {
5375
+ "navigationLabel": {
5557
5376
  "type": "string",
5558
5377
  "required": false
5559
5378
  },
5560
- "showBack": {
5379
+ "open": {
5561
5380
  "type": "boolean",
5562
5381
  "required": false
5563
5382
  },
5564
- "showMenu": {
5565
- "type": "boolean",
5383
+ "settingsGroups": {
5384
+ "type": "PanelNavGroup[]",
5385
+ "required": false
5386
+ },
5387
+ "settingsLabel": {
5388
+ "type": "string",
5566
5389
  "required": false
5567
5390
  }
5568
5391
  },
5569
5392
  "events": [
5570
5393
  {
5571
- "name": "dsAction",
5572
- "detail": "{ id: string; originalEvent: MouseEvent }"
5394
+ "name": "dsAreaSelect",
5395
+ "detail": "string"
5573
5396
  },
5574
5397
  {
5575
- "name": "dsBack",
5576
- "detail": "MouseEvent"
5398
+ "name": "dsBrowseContextChange",
5399
+ "detail": "NavChromeStyle"
5577
5400
  },
5578
5401
  {
5579
- "name": "dsMenuToggle",
5580
- "detail": "MouseEvent"
5402
+ "name": "dsClose",
5403
+ "detail": "void"
5581
5404
  }
5582
5405
  ],
5583
5406
  "slots": [],
5584
5407
  "exports": {
5585
- "customElement": "ds-panel-tool-header",
5586
- "react": "DsPanelToolHeader",
5587
- "angular": "DsPanelToolHeader"
5408
+ "customElement": "ds-mobile-sheet-nav",
5409
+ "react": "DsMobileSheetNav",
5410
+ "angular": "DsMobileSheetNav"
5588
5411
  }
5589
5412
  },
5590
5413
  "dependencies": [
5591
5414
  "@ds-mo/ui",
5592
- "@ds-mo/tokens"
5415
+ "@ds-mo/tokens",
5416
+ "@ds-mo/icons"
5593
5417
  ],
5594
5418
  "registryDependencies": [
5419
+ "badge",
5595
5420
  "button-unfilled",
5421
+ "icon",
5422
+ "tab-group",
5596
5423
  "text",
5597
5424
  "tooltip"
5598
5425
  ]
5599
5426
  },
5600
5427
  {
5601
- "name": "panel-tool-search",
5602
- "title": "PanelToolSearch",
5603
- "description": "Transparent search row for the top of a PanelTools product view, with a fixed 48px allocation around the standard md search control and an optional filter-menu trigger.",
5428
+ "name": "modal",
5429
+ "title": "Modal",
5430
+ "description": "Dismissible native top-layer dialog for a focused confirmation or short blocking task, with a fixed title-and-close header, composable content, and an optional two-action footer.",
5604
5431
  "type": "registry:ui",
5605
5432
  "meta": {
5606
5433
  "library": "@ds-mo/ui",
5607
5434
  "distribution": "npm",
5608
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tool-search",
5609
- "source": "src/wc/components/PanelToolSearch/PanelToolSearch.tsx",
5435
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/modal",
5436
+ "source": "src/wc/components/Modal/Modal.tsx",
5610
5437
  "intentStatus": "complete",
5611
5438
  "intent": {
5612
5439
  "audience": "general",
5613
- "status": "experimental",
5614
- "summary": "Transparent search row for the top of a PanelTools product view, with a fixed 48px allocation around the standard md search control and an optional filter-menu trigger.",
5440
+ "status": "stable",
5441
+ "summary": "Dismissible native top-layer dialog for a focused confirmation or short blocking task, with a fixed title-and-close header, composable content, and an optional two-action footer.",
5615
5442
  "useWhen": [
5616
- "A PanelTools base view filters or searches the tool's own content.",
5617
- "Several tool products need the same search-row geometry directly below the shared PanelTools header.",
5618
- "The product needs a compact filter menu next to search while keeping its filter choices and matching policy application-owned."
5443
+ "The user must confirm or cancel one focused decision before returning to the underlying interface.",
5444
+ "A short blocking task or compact form needs dialog semantics, focus containment, and explicit completion actions.",
5445
+ "The content can be safely dismissed through Close, Escape, or the backdrop."
5619
5446
  ],
5620
5447
  "avoidWhen": [
5621
- "The search belongs inside a Select or SelectMulti popup; use that component's searchable behavior.",
5622
- "A form needs a labelled standalone field; compose ds-input inside ds-field instead."
5448
+ "The message is non-blocking feedback or a transient status update.",
5449
+ "The interaction is a contextual list of commands anchored to a trigger.",
5450
+ "The workflow is multi-step, long-form, or requires substantial navigation.",
5451
+ "Dismissal would lose work or leave an irreversible operation in an unsafe state.",
5452
+ "A second modal would be opened over an existing modal."
5453
+ ],
5454
+ "alternatives": [
5455
+ {
5456
+ "when": "The user needs non-blocking feedback or a transient status message.",
5457
+ "component": "component:ds-toast",
5458
+ "reason": "Toast communicates transient status without trapping focus or blocking the page."
5459
+ },
5460
+ {
5461
+ "when": "A trigger reveals a short contextual list of commands.",
5462
+ "component": "component:ds-menu",
5463
+ "reason": "Menu provides anchored command semantics without creating a blocking dialog."
5464
+ },
5465
+ {
5466
+ "when": "Editable settings should remain visible without blocking the rest of the interface.",
5467
+ "component": "component:ds-card-setting",
5468
+ "reason": "CardSetting provides a persistent controlled settings workflow without modal focus containment."
5469
+ }
5623
5470
  ],
5624
5471
  "commonlyComposedWith": [
5625
- "component:ds-panel-tools",
5626
- "component:ds-conversation-list",
5627
- "component:ds-input"
5472
+ "component:ds-button-filled",
5473
+ "component:ds-button-unfilled",
5474
+ "component:ds-field",
5475
+ "component:ds-text"
5628
5476
  ],
5629
5477
  "accessibility": [
5630
- "Provide an aria-label that names the searched domain, such as Search agent chats or Search messages.",
5631
- "The standard search clear action restores focus, uses the concise localized clearLabel by itself for both its tooltip and accessible name, and emits both the empty query and dsClear.",
5632
- "When showFilter is enabled, provide stable filterTriggerId and filterControls values, synchronize filterExpanded with the controlled menu, and restore focus after selection; filterAriaLabel also labels its tooltip."
5478
+ "Provide a concise visible heading; the component uses it as the dialog's accessible name.",
5479
+ "Give the primary explanatory copy a stable id and pass it through aria-describedby so assistive technology receives the decision context.",
5480
+ "Opening the native modal dialog moves focus to the header Close action, whose visible tooltip matches its accessible name, traps Tab navigation inside the top layer, and makes outside content inert.",
5481
+ "Close, Escape, and backdrop activation emit dsClose with close-button, escape, or backdrop reason before beginning dismissal; use the component only when every dismissal path is safe.",
5482
+ "After exit motion completes, the native dialog leaves the top layer, focus returns to the previously focused element, and dsAfterClose emits.",
5483
+ "Use visible label-only footer buttons. Keep at most two actions: one bold filled primary action followed by one bordered unfilled action, or two bordered unfilled actions.",
5484
+ "Use negative intent for a filled destructive action and state the irreversible consequence in the content.",
5485
+ "Do not open a modal from another modal; keep one blocking decision in focus at a time."
5633
5486
  ],
5634
5487
  "states": [
5635
- "The row is always 48px high with 8px outer padding and a complete md search recipe: 32px control, text-body-medium at 14px/20px, and a 20px md search icon.",
5636
- "The search icon stays foreground-secondary at rest, hover, focus, active, and while the query is filled.",
5637
- "The row and control surface remain transparent so the ShellApp chrome wash is visible behind them.",
5638
- "The row divider remains the same tertiary 1px boundary while the input is focused because it belongs to the 48px container rather than the input control.",
5639
- "With filtering enabled, the md search control, decorative vertical divider, and borderless md Filter action are separated by 8px; filterActive promotes only the trigger foreground without adding a selected fill."
5488
+ "The owner opens the modal through the open property and responds to the typed dsClose detail for application state synchronization or dismissal analytics.",
5489
+ "The component mutates open to false for Close, Escape, and backdrop dismissal while retaining its rendered surface through exit motion.",
5490
+ "The default slot owns task content; the named footer slot is optional and is hidden when no actions are assigned.",
5491
+ "Primary actions use a bold filled button with semantic intent. Secondary and cancel actions use bordered label-only unfilled buttons.",
5492
+ "The owner performs save, delete, cancel, and other product consequences before or while closing the modal."
5640
5493
  ],
5641
5494
  "responsiveBehavior": [
5642
- "The row fills the available drawer or fullscreen width, allows its search region to shrink inside a 300px drawer without pushing the filter trigger under the tool rail, and does not reduce its control below md density."
5495
+ "Choose the smallest sm, md, or lg width that fits the focused task; the top-layer dialog clamps to the viewport with token-based outer space.",
5496
+ "Content scrolls independently when needed while the 64px header and optional 64px footer remain fixed.",
5497
+ "Avoid layouts whose minimum content width exceeds the narrow viewport clamp.",
5498
+ "The native top layer escapes transformed ancestors, clipping containers, and application stacking contexts without moving slotted content."
5643
5499
  ],
5644
5500
  "frameworkCaveats": {
5645
5501
  "customElements": [
5646
- "Listen for dsChange to receive the current string query and dsClear when the clear action is used.",
5647
- "Listen for dsFilterToggle and pair the trigger with an externally controlled ds-menu; product-specific filter labels and filtering remain outside this component."
5502
+ "Set open as a JavaScript property when controlling the modal; inspect dsClose.detail.reason and use dsAfterClose for cleanup that must wait for exit motion and focus restoration.",
5503
+ "Connect the most relevant slotted explanatory text through aria-describedby.",
5504
+ "Footer actions are slotted application-owned controls and must implement their own product consequence."
5648
5505
  ],
5649
5506
  "react": [
5650
- "Use DsPanelToolSearch, bind value for controlled state, and handle onDsChange.",
5651
- "Bind the optional filter trigger state and connect onDsFilterToggle to a controlled DsMenu."
5507
+ "Pass open to DsModal, inspect onDsClose event detail, and use onDsAfterClose only for cleanup after exit motion and focus restoration.",
5508
+ "Connect the most relevant slotted explanatory text through aria-describedby.",
5509
+ "Assign footer controls with slot=\"footer\" and handle each action before updating open."
5652
5510
  ],
5653
5511
  "angular": [
5654
- "Import DsPanelToolSearch and bind value as a property; this search composition is not a form value accessor.",
5655
- "Bind showFilter, filterExpanded, and filterActive, then connect dsFilterToggle to a product-owned ds-menu."
5512
+ "Bind [open], inspect $event.detail from (dsClose), and use (dsAfterClose) only for cleanup after exit motion and focus restoration.",
5513
+ "Connect the most relevant slotted explanatory text through aria-describedby.",
5514
+ "Assign footer controls with slot=\"footer\" and handle each action before updating open."
5656
5515
  ]
5657
5516
  },
5658
5517
  "references": [
5659
5518
  {
5660
- "label": "Storybook examples",
5661
- "path": "src/wc/components/PanelToolSearch/PanelToolSearch.stories.ts"
5519
+ "label": "Storybook confirmation and footer examples",
5520
+ "path": "src/wc/components/Modal/Modal.stories.ts"
5521
+ },
5522
+ {
5523
+ "label": "Cross-browser focus, dismissal, geometry, and accessibility coverage",
5524
+ "path": "tests/e2e/accessibility-overlays.spec.ts"
5525
+ },
5526
+ {
5527
+ "label": "Reduced-motion overlay coverage",
5528
+ "path": "tests/e2e/reduced-motion.spec.ts"
5662
5529
  }
5663
5530
  ]
5664
5531
  },
5665
5532
  "props": {
5666
- "ariaLabel": {
5667
- "type": "string",
5668
- "required": false
5669
- },
5670
- "controls": {
5533
+ "ariaDescribedby": {
5671
5534
  "type": "string | undefined",
5672
5535
  "required": false
5673
5536
  },
5674
- "filterActive": {
5675
- "type": "boolean",
5676
- "required": false
5677
- },
5678
- "filterAriaLabel": {
5537
+ "closeAriaLabel": {
5679
5538
  "type": "string",
5680
5539
  "required": false
5681
5540
  },
5682
- "filterControls": {
5683
- "type": "string | undefined",
5684
- "required": false
5685
- },
5686
- "filterExpanded": {
5687
- "type": "boolean",
5688
- "required": false
5689
- },
5690
- "filterTriggerId": {
5541
+ "heading": {
5691
5542
  "type": "string",
5692
- "required": false
5693
- },
5694
- "isInactive": {
5695
- "type": "boolean",
5696
- "required": false
5543
+ "required": true
5697
5544
  },
5698
- "placeholder": {
5699
- "type": "string",
5545
+ "modalWidth": {
5546
+ "type": "ModalWidth | string",
5700
5547
  "required": false
5701
5548
  },
5702
- "showFilter": {
5549
+ "open": {
5703
5550
  "type": "boolean",
5704
5551
  "required": false
5705
- },
5706
- "value": {
5707
- "type": "string",
5708
- "required": false
5709
5552
  }
5710
5553
  },
5711
5554
  "events": [
5712
5555
  {
5713
- "name": "dsChange",
5714
- "detail": "string"
5715
- },
5716
- {
5717
- "name": "dsClear",
5556
+ "name": "dsAfterClose",
5718
5557
  "detail": "void"
5719
5558
  },
5720
5559
  {
5721
- "name": "dsFilterToggle",
5722
- "detail": "MouseEvent"
5560
+ "name": "dsClose",
5561
+ "detail": "ModalCloseDetail"
5723
5562
  }
5724
5563
  ],
5725
5564
  "slots": [],
5726
5565
  "exports": {
5727
- "customElement": "ds-panel-tool-search",
5728
- "react": "DsPanelToolSearch",
5729
- "angular": "DsPanelToolSearch"
5566
+ "customElement": "ds-modal",
5567
+ "react": "DsModal",
5568
+ "angular": "DsModal"
5730
5569
  }
5731
5570
  },
5732
5571
  "dependencies": [
5733
5572
  "@ds-mo/ui",
5734
- "@ds-mo/tokens",
5735
- "@ds-mo/icons"
5573
+ "@ds-mo/tokens"
5736
5574
  ],
5737
5575
  "registryDependencies": [
5738
5576
  "button-unfilled",
5739
- "divider",
5740
- "icon",
5741
5577
  "text",
5742
5578
  "tooltip"
5743
5579
  ]
5744
5580
  },
5745
5581
  {
5746
- "name": "panel-tools",
5747
- "title": "PanelTools",
5748
- "description": "Required ShellApp utility rail and persistent drawer host for the fixed set of global Search, Agents, Messages, Stacks, Activity, and Help products.",
5582
+ "name": "panel-nav",
5583
+ "title": "PanelNav",
5584
+ "description": "The single persistent primary navigation for an application, providing grouped top-level destinations, active-route state, standard dashboard/settings switching, user access, and collapsible desktop and tablet presentation.",
5749
5585
  "type": "registry:ui",
5750
5586
  "meta": {
5751
5587
  "library": "@ds-mo/ui",
5752
5588
  "distribution": "npm",
5753
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tools",
5754
- "source": "src/wc/components/PanelTools/PanelTools.tsx",
5589
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-nav",
5590
+ "source": "src/wc/components/PanelNav/PanelNav.tsx",
5755
5591
  "intentStatus": "complete",
5756
5592
  "intent": {
5757
5593
  "audience": "specialized",
5758
5594
  "status": "stable",
5759
- "summary": "Required ShellApp utility rail and persistent drawer host for the fixed set of global Search, Agents, Messages, Stacks, Activity, and Help products.",
5595
+ "summary": "The single persistent primary navigation for an application, providing grouped top-level destinations, active-route state, standard dashboard/settings switching, user access, and collapsible desktop and tablet presentation.",
5760
5596
  "useWhen": [
5761
- "Composing the required global tools region inside the application's single ShellApp.",
5762
- "Users need to move between application-wide utilities without losing each tool's in-progress state.",
5763
- "Search, AI conversations, user messages, review stacks, notifications, or help content must remain available alongside route content."
5597
+ "Building the one primary navigation surface for an application that uses the CompoMo system.",
5598
+ "Top-level destinations must remain consistently available while the application's page content changes.",
5599
+ "Primary destinations need visual grouping, icons, notification indicators, active-route state, and expanded or collapsed presentation."
5764
5600
  ],
5765
5601
  "avoidWhen": [
5766
- "The action is specific to the current page or selected content rather than globally available across the application.",
5767
- "The item navigates to a primary or secondary route; use PanelNav or BarNav instead.",
5768
- "A consumer wants to add arbitrary tools, reorder fixed tools, or repurpose a semantic tool id.",
5769
- "Building the mobile tools experience; future mobile ShellApp composition uses a different bottom-bar and panel pattern.",
5770
- "PanelTools would be mounted outside the application's single ShellApp."
5602
+ "A second navigation surface is needed within the same application; an application must have only one PanelNav.",
5603
+ "The choices represent sections within the active primary destination; use BarNav instead.",
5604
+ "The choices switch local content without changing the application's primary destination; use TabGroup instead.",
5605
+ "The interaction performs a command or presents temporary contextual choices; use a button or Menu instead.",
5606
+ "Building navigation below the mobile breakpoint; use the application's dedicated mobile navigation component instead."
5771
5607
  ],
5772
5608
  "alternatives": [
5773
5609
  {
5774
- "when": "The action navigates to a top-level application destination.",
5775
- "component": "component:ds-panel-nav",
5776
- "reason": "PanelNav exclusively owns primary application navigation."
5610
+ "when": "The choices represent route sections within the active primary destination.",
5611
+ "component": "component:ds-bar-nav",
5612
+ "reason": "BarNav owns secondary section navigation within the destination selected by PanelNav."
5777
5613
  },
5778
5614
  {
5779
- "when": "The action navigates between route sections of the active destination.",
5780
- "component": "component:ds-bar-nav",
5781
- "reason": "BarNav exclusively owns secondary route navigation."
5615
+ "when": "The choices switch local content without changing the application's primary destination.",
5616
+ "component": "component:ds-tab-group",
5617
+ "reason": "TabGroup owns local view selection and tab semantics."
5782
5618
  },
5783
5619
  {
5784
- "when": "Temporary contextual actions or options are needed.",
5620
+ "when": "The choices are commands or temporary contextual actions.",
5785
5621
  "component": "component:ds-menu",
5786
- "reason": "Menu owns transient contextual choices rather than persistent global products."
5622
+ "reason": "Menu owns transient action and option collections rather than persistent destinations."
5787
5623
  }
5788
5624
  ],
5789
5625
  "commonlyComposedWith": [
5790
5626
  "component:ds-shell-app",
5791
- "component:ds-panel-nav",
5792
- "component:ds-bar-nav"
5627
+ "component:ds-bar-nav",
5628
+ "component:ds-panel-tools",
5629
+ "component:ds-menu"
5793
5630
  ],
5794
5631
  "patterns": [
5795
5632
  "pattern:application-shell"
5796
5633
  ],
5797
5634
  "accessibility": [
5798
- "Provide localized accessible labels for the rail, shortcut group, and every rendered tool.",
5799
- "Keep Search first in the rail header and Help last in the rail footer so keyboard and visual order remain predictable.",
5800
- "Keep focus on the selected rail action when opening a drawer and allow normal Tab navigation into its content.",
5801
- "Do not trigger global shortcuts while focus is in an editable control.",
5802
- "Use notification dots only as supplemental unread or new-content status and never as the sole status indication.",
5803
- "Explain temporarily inactive tools through an accessible label or adjacent product guidance; omit unauthorized tools entirely."
5635
+ "Give every primary destination a concise visible label and an icon that supports rather than replaces that label.",
5636
+ "Provide localized dashboard, settings, account, navigation, collapse, and expand labels.",
5637
+ "Preserve accessible destination names when the panel is collapsed to icon-only presentation.",
5638
+ "Use notification dots as supplemental status and never as the only indication of important information.",
5639
+ "When the destination body overflows, it becomes a localized keyboard-focusable scroll region in addition to the roving destination controls.",
5640
+ "Keep the standard dashboard/settings switch and user/account entry available in the footer."
5804
5641
  ],
5805
5642
  "states": [
5806
- "Search and Help are required; optional Agents, Messages, Stacks, and Activity tools are filtered by the application for authorization and entitlement.",
5807
- "Use only the fixed semantic tool ids and canonical order: Search, Agents, Messages, Stacks, Activity, Help; do not reorder, duplicate, or repurpose them.",
5808
- "Search is application-wide; Agents is user-to-AI chat; Messages is user-to-user chat; Stacks is a specialized inbox of grouped application events for review; Activity is the notification center; Help is drawer content that may link to external resources.",
5809
- "Only one drawer is open at a time; selecting another tool switches directly and selecting the active tool closes to rail-only mode.",
5810
- "The drawer starts closed, remains open across ordinary route changes, and retains every mounted tool's independent conversation, query, scroll, and work state.",
5811
- "When storageKey is set, persist only the last active tool in this browser and still restore the drawer closed after reload.",
5812
- "The application owns unread state; opening Messages, Agents, Stacks, or Activity does not automatically clear its notification dot.",
5813
- "PanelTools owns the one visible header above every drawer tool view and above fullscreen views using the default shared header mode. Slotted tool content must not render a second header unless the conversation product explicitly opts into split fullscreen headers.",
5814
- "PanelTools composes ds-panel-tool-header as its canonical left-aligned header implementation so standalone header stories and shell rendering cannot diverge.",
5815
- "Each tool supplies its current header title, base-versus-detail Back state, and right-side actions through the headers property. Base views omit Back; deeper views expose Back and update the same header in place.",
5816
- "Header Back and action events express intent only; the owning tool changes product navigation, menus, and data state. PanelTools keeps the final header action exactly 8px from the drawer edge.",
5817
- "Menus opened from a right-side header action use PANEL_TOOLS_HEADER_MENU_PLACEMENT: bottom/end choice-cell alignment and a 12px side offset, placing the popup 4px below the 48px header while aligning the final menu item edge with the trigger.",
5818
- "Tool view roots stay transparent so ShellApp's chrome wash remains visible; only explicitly designed child surfaces introduce a fill.",
5819
- "Tools with search compose ds-panel-tool-search immediately below the shared header. Its 48px row always contains the md search control and must not be reduced to sm or xs.",
5820
- "If an active optional tool becomes unavailable, PanelTools closes the drawer, clears activeTool, and emits its deselection.",
5821
- "Use isInactive only for a temporarily unavailable visible tool; omit tools the user is not authorized to access.",
5822
- "The application owns slotted tool products and data while PanelTools owns rail ordering, drawer selection, open state, motion, and shell events.",
5823
- "Opening and closing clip an already-rendered fixed-width surface. Header and tool content remain fully opaque and retained during width motion; transition completion is accepted only at the measured terminal clip width, after which the closed surface becomes inert and paint-skipped.",
5824
- "Entering and exiting fullscreen snaps without borrowing the drawer open or close animation.",
5825
- "When fullscreenHeaderMode is split, PanelTools suppresses only its fullscreen shared header. The application renders exactly two canonical ds-panel-tool-header instances: a tool-title/list-actions header over the 300px history pane and a chat-title/Exit-fullscreen/chat-actions header over the detail pane. The detail header omits Back because the list remains visible."
5643
+ "Render exactly one PanelNav per application; it owns primary application destinations and no other navigation role.",
5644
+ "The host router owns the current route; prefer currentUrl for active destination matching and use activeId only when route matching is unavailable.",
5645
+ "Use anchor mode for native links or routers that intercept anchors; use event mode when the host performs navigation from dsNavSelect.",
5646
+ "Groups visually organize top-level destinations only and must not be interpreted as nested or expandable navigation.",
5647
+ "Dashboard presents day-to-day operational destinations; Settings presents administrative and configuration destinations.",
5648
+ "The standard footer switches the entire destination collection and navStyle between Dashboard and Settings and exposes the user/account entry.",
5649
+ "The host owns the external user menu opened from dsNavUserAction.",
5650
+ "Item and header controls inherit the shared md control radius while local shell geometry continues to own collapsed layout and footer animation positioning.",
5651
+ "On desktop, allow user-controlled expand and collapse and persist the preference with storageKey when cross-session persistence is appropriate."
5826
5652
  ],
5827
5653
  "responsiveBehavior": [
5828
- "The open drawer reduces main-content width and uses --dimension-panel-width-xs (300px) on every supported desktop and tablet viewport.",
5829
- "ShellApp owns the fixed drawer-width variable; consumers must not hardcode alternate drawer widths.",
5830
- "Below 768px, do not reuse desktop PanelTools: future ShellApp mobile composition uses a bottom bar for Search, Agents, Notifications, and Stacks, while Help moves into mobile primary navigation.",
5831
- "Keep named-slot content mounted while tools switch or the drawer closes so users can return to in-progress global work.",
5832
- "Conversation products may use fullscreenHeaderMode split for a 300px history rail beside a flexible detail pane, each with its own canonical header; the application owns that internal split layout.",
5833
- "Use fixed drawer widths for now; do not add user resizing or width persistence."
5654
+ "At 1200px and wider, default to expanded, allow the user to expand or collapse, and restore the locally persisted desktop preference when available.",
5655
+ "From 768px through 1199px, present PanelNav permanently collapsed and do not allow user expansion.",
5656
+ "Below 768px, the consuming application replaces PanelNav with a dedicated mobile navigation component; PanelNav does not own mobile navigation.",
5657
+ "ShellApp permanently owns responsive composition: it determines shell mode, enforces tablet collapse, and replaces PanelNav with future mobile navigation below 768px.",
5658
+ "When the viewport is below breakpoint, PanelNav locks collapsed, disables its header toggle affordance, and preserves the persisted desktop collapse preference.",
5659
+ "Collapsed presentation must preserve destination ordering, active state, notification status, and accessible names."
5834
5660
  ],
5835
5661
  "frameworkCaveats": {
5836
5662
  "customElements": [
5837
- "Assign items as a JavaScript property for structured data; items-json is the string fallback.",
5838
- "Assign headers as a JavaScript property and replace its object identity whenever an active tool changes title, depth, or actions.",
5839
- "Keep PanelTools mounted at ShellApp scope across route changes and provide each product through its matching named slot."
5663
+ "Assign groups as a JavaScript property for structured data; a JSON string attribute is also supported.",
5664
+ "Set nav-style before the element connects when first-paint style must match the current route."
5840
5665
  ],
5841
5666
  "react": [
5842
- "Pass the fixed item collection through the generated React wrapper and keep named-slot product content mounted at ShellApp scope.",
5843
- "Use storageKey only for same-browser last-tool continuity; do not persist the open drawer."
5667
+ "Pass groups as an array through the generated React wrapper and synchronize currentUrl with the host router.",
5668
+ "ShellApp owns mobile replacement; PanelNav enforces its configured breakpoint expansion lock."
5844
5669
  ],
5845
5670
  "angular": [
5846
- "Import DsPanelTools from @ds-mo/ui/angular/ds-panel-tools and bind items as a property.",
5847
- "Bind headers as a replaced object and route dsHeaderBack and dsHeaderAction to the active tool owner.",
5848
- "Keep the component in the persistent shell layout rather than recreating it in routed page components."
5671
+ "Import DsPanelNav from @ds-mo/ui/angular/ds-panel-nav and bind groups as a property.",
5672
+ "Bind both the nav-style attribute and navStyle property when first-paint route styling must be deterministic.",
5673
+ "ShellApp owns mobile replacement; PanelNav enforces its configured breakpoint expansion lock."
5849
5674
  ]
5850
5675
  },
5851
5676
  "references": [
5852
5677
  {
5853
5678
  "label": "Executable Storybook examples",
5854
- "path": "src/wc/components/PanelTools/PanelTools.stories.ts"
5679
+ "path": "src/wc/components/PanelNav/PanelNav.stories.ts"
5855
5680
  },
5856
5681
  {
5857
- "label": "Framework and shell integration",
5682
+ "label": "Framework and routing integration",
5858
5683
  "path": "docs/framework-integration.md"
5859
5684
  },
5860
5685
  {
@@ -5864,47 +5689,83 @@
5864
5689
  ]
5865
5690
  },
5866
5691
  "props": {
5867
- "activeTool": {
5868
- "type": "PanelToolsToolId | ''",
5692
+ "accountLabel": {
5693
+ "type": "string",
5869
5694
  "required": false
5870
5695
  },
5871
- "fullscreenHeaderMode": {
5872
- "type": "'shared' | 'split'",
5696
+ "accountMenuExpanded": {
5697
+ "type": "boolean",
5873
5698
  "required": false
5874
5699
  },
5875
- "headers": {
5876
- "type": "PanelToolsHeaders",
5700
+ "activeId": {
5701
+ "type": "string",
5877
5702
  "required": false
5878
5703
  },
5879
- "headersJson": {
5704
+ "breakpoint": {
5705
+ "type": "number",
5706
+ "required": false
5707
+ },
5708
+ "collapseNavigationLabel": {
5880
5709
  "type": "string",
5881
5710
  "required": false
5882
5711
  },
5883
- "items": {
5884
- "type": "PanelToolsItem[]",
5712
+ "collapsed": {
5713
+ "type": "boolean",
5885
5714
  "required": false
5886
5715
  },
5887
- "itemsJson": {
5716
+ "currentUrl": {
5888
5717
  "type": "string",
5889
5718
  "required": false
5890
5719
  },
5891
- "open": {
5720
+ "dashboardLabel": {
5721
+ "type": "string",
5722
+ "required": false
5723
+ },
5724
+ "dashboardNavigationLabel": {
5725
+ "type": "string",
5726
+ "required": false
5727
+ },
5728
+ "disableViewTransition": {
5892
5729
  "type": "boolean",
5893
5730
  "required": false
5894
5731
  },
5895
- "presentation": {
5896
- "type": "'drawer' | 'fullscreen'",
5732
+ "expandNavigationLabel": {
5733
+ "type": "string",
5734
+ "required": false
5735
+ },
5736
+ "groups": {
5737
+ "type": "string | PanelNavGroup[]",
5738
+ "required": false
5739
+ },
5740
+ "navStyle": {
5741
+ "type": "NavChromeStyle",
5742
+ "required": false
5743
+ },
5744
+ "navigationItemsLabel": {
5745
+ "type": "string",
5746
+ "required": false
5747
+ },
5748
+ "routerMode": {
5749
+ "type": "PanelNavRouterMode",
5750
+ "required": false
5751
+ },
5752
+ "settingsLabel": {
5753
+ "type": "string",
5754
+ "required": false
5755
+ },
5756
+ "settingsNavigationLabel": {
5757
+ "type": "string",
5897
5758
  "required": false
5898
5759
  },
5899
5760
  "storageKey": {
5900
5761
  "type": "string",
5901
5762
  "required": false
5902
5763
  },
5903
- "toolShortcutsLabel": {
5764
+ "userInitial": {
5904
5765
  "type": "string",
5905
5766
  "required": false
5906
5767
  },
5907
- "toolsLabel": {
5768
+ "userName": {
5908
5769
  "type": "string",
5909
5770
  "required": false
5910
5771
  }
@@ -5919,123 +5780,126 @@
5919
5780
  "detail": "ChromeTransitionDetail"
5920
5781
  },
5921
5782
  {
5922
- "name": "dsHeaderAction",
5923
- "detail": "{\n tool: PanelToolsToolId;\n id: string;\n }"
5783
+ "name": "dsNavFooterAction",
5784
+ "detail": "void"
5924
5785
  },
5925
5786
  {
5926
- "name": "dsHeaderBack",
5927
- "detail": "{\n tool: PanelToolsToolId;\n }"
5787
+ "name": "dsNavSelect",
5788
+ "detail": "string"
5928
5789
  },
5929
5790
  {
5930
- "name": "dsPresentationChange",
5931
- "detail": "{\n presentation: 'drawer' | 'fullscreen';\n }"
5791
+ "name": "dsNavToggle",
5792
+ "detail": "boolean"
5932
5793
  },
5933
5794
  {
5934
- "name": "dsToolChange",
5935
- "detail": "{\n id: PanelToolsToolId;\n selected: boolean;\n }"
5795
+ "name": "dsNavUserAction",
5796
+ "detail": "PanelNavUserActionDetail"
5936
5797
  }
5937
5798
  ],
5938
5799
  "slots": [],
5939
5800
  "exports": {
5940
- "customElement": "ds-panel-tools",
5941
- "react": "DsPanelTools",
5942
- "angular": "DsPanelTools"
5801
+ "customElement": "ds-panel-nav",
5802
+ "react": "DsPanelNav",
5803
+ "angular": "DsPanelNav"
5943
5804
  }
5944
5805
  },
5945
5806
  "dependencies": [
5946
5807
  "@ds-mo/ui",
5947
- "@ds-mo/tokens"
5808
+ "@ds-mo/tokens",
5809
+ "@ds-mo/icons"
5948
5810
  ],
5949
5811
  "registryDependencies": [
5812
+ "badge",
5950
5813
  "button-unfilled",
5951
- "panel-tool-header",
5814
+ "icon",
5815
+ "text",
5952
5816
  "tooltip"
5953
5817
  ]
5954
5818
  },
5955
5819
  {
5956
- "name": "radio",
5957
- "title": "Radio",
5958
- "description": "Form-associated one-of-many radio selection set with vertical or horizontal layout, three densities, per-option inactive state, and roving keyboard focus.",
5820
+ "name": "panel-sub-nav",
5821
+ "title": "PanelSubNav",
5822
+ "description": "Persistent vertical tab navigation for a panel or card side rail, switching adjacent local content with menu-like selected fill and stable text weight.",
5959
5823
  "type": "registry:ui",
5960
5824
  "meta": {
5961
5825
  "library": "@ds-mo/ui",
5962
5826
  "distribution": "npm",
5963
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/radio",
5964
- "source": "src/wc/components/Radio/Radio.tsx",
5827
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-sub-nav",
5828
+ "source": "src/wc/components/PanelSubNav/PanelSubNav.tsx",
5965
5829
  "intentStatus": "complete",
5966
5830
  "intent": {
5967
5831
  "audience": "general",
5968
5832
  "status": "stable",
5969
- "summary": "Form-associated one-of-many radio selection set with vertical or horizontal layout, three densities, per-option inactive state, and roving keyboard focus.",
5833
+ "summary": "Persistent vertical tab navigation for a panel or card side rail, switching adjacent local content with menu-like selected fill and stable text weight.",
5970
5834
  "useWhen": [
5971
- "A user must select exactly one visible option from a small set.",
5972
- "All available choices should remain visible for comparison.",
5973
- "A form needs one selected string value with native validation, reset, or external form association."
5835
+ "A panel or card side rail needs a persistent vertical list that switches adjacent local content.",
5836
+ "Each concise text label controls an immediately available tabpanel without changing application routes."
5974
5837
  ],
5975
5838
  "avoidWhen": [
5976
- "A user may select zero or multiple independent choices.",
5977
- "A binary setting applies immediately rather than selecting from a set.",
5978
- "The option list is too long or space-constrained to remain visible."
5839
+ "The navigation is not contained in a panel or card side rail.",
5840
+ "Local views should be arranged horizontally; use TabGroup instead.",
5841
+ "The choices navigate routes in application shell chrome; use PanelNav or BarNav instead.",
5842
+ "The choices are temporary commands or contextual options; use Menu instead.",
5843
+ "Rows need icons, subtext, notification dots, nested levels, or section headers."
5979
5844
  ],
5980
5845
  "alternatives": [
5981
5846
  {
5982
- "when": "A user may select zero or multiple independent choices.",
5983
- "component": "component:ds-checkbox",
5984
- "reason": "Checkbox communicates independent selection rather than one-of-many choice."
5847
+ "when": "Local panel choices fit a horizontal tab row.",
5848
+ "component": "component:ds-tab-group",
5849
+ "reason": "TabGroup is the horizontal local-view counterpart."
5985
5850
  },
5986
5851
  {
5987
- "when": "A binary setting applies immediately.",
5988
- "component": "component:ds-switch",
5989
- "reason": "Switch communicates an immediately applied on/off setting."
5852
+ "when": "The choices are primary application destinations.",
5853
+ "component": "component:ds-panel-nav",
5854
+ "reason": "PanelNav owns primary application navigation."
5990
5855
  },
5991
5856
  {
5992
- "when": "The option list is long or the available space is constrained.",
5993
- "component": "component:ds-select",
5994
- "reason": "Select keeps a larger one-of-many choice set compact."
5857
+ "when": "The choices are secondary application routes.",
5858
+ "component": "component:ds-bar-nav",
5859
+ "reason": "BarNav owns route sections inside ShellApp."
5860
+ },
5861
+ {
5862
+ "when": "The choices are transient actions or options.",
5863
+ "component": "component:ds-menu",
5864
+ "reason": "Menu owns temporary popup collections."
5995
5865
  }
5996
5866
  ],
5997
5867
  "commonlyComposedWith": [
5998
- "component:ds-field",
5868
+ "component:ds-card-setting",
5999
5869
  "component:ds-text"
6000
5870
  ],
6001
5871
  "accessibility": [
6002
- "The host exposes radiogroup semantics and requires an accessible group name from aria-label or aria-labelledby.",
6003
- "Each visible option exposes radio semantics, its checked state, its label text, and any inactive state.",
6004
- "Arrow keys move and select through active options; Home and End select the first and last active options; Space and Enter select the focused option.",
6005
- "Roving tabindex keeps one active option in the tab order, preferring the selected option."
5872
+ "Provide an accessible name with aria-label or aria-labelledby.",
5873
+ "Give every item a unique id and the id of its controlled tabpanel.",
5874
+ "Keep each controlled tabpanel labelled by its matching item id.",
5875
+ "Always provide a valid selected item when enabled items exist so exactly one tab and panel are active.",
5876
+ "ArrowUp and ArrowDown move and activate selection; Home and End select the first and last available items.",
5877
+ "Do not use selected text weight as the selection cue; active fill and primary foreground communicate selection."
6006
5878
  ],
6007
5879
  "states": [
6008
- "Unchecked circles use a tertiary-foreground inset stroke: 1.25px at md, 1px at sm, and 0.75px at xs.",
6009
- "Selected circles remove the border, use a brand fill, and draw a centered on-bold foreground dot sized 8px at md, 6px at sm, and 4px at xs.",
6010
- "Sizes are md with a 16px circle in a 20px placement, sm with a 12px circle in a 16px placement, and xs with an 8px circle in a 12px placement.",
6011
- "The initial value is restored by native form reset; the selected value submits under name and a required set is invalid until one active option is selected."
5880
+ "The parent owns the canonical selected value and panel visibility, and should update both from dsChange.",
5881
+ "A missing, empty, or unknown selected value is invalid when enabled items exist; the component does not choose a fallback selection.",
5882
+ "Inactive items remain visible but cannot be focused or selected.",
5883
+ "Selection is singular and follows keyboard focus.",
5884
+ "The omitted default surface treatment is for primary and secondary parent surfaces and uses the brand-active selected fill; pass faint explicitly on faint surfaces to use the neutral active fill.",
5885
+ "Rows contain one text label only and do not express nested navigation or grouped hierarchy."
6012
5886
  ],
6013
5887
  "responsiveBehavior": [
6014
- "Choose size from the density of the containing form or settings row.",
6015
- "Prefer vertical layout when labels may wrap or horizontal space is constrained; horizontal layout is appropriate for short labels in a small set."
5888
+ "The component remains vertical at every width.",
5889
+ "The consuming panel owns responsive adaptation and decides whether to reposition or replace the side rail."
6016
5890
  ],
6017
5891
  "frameworkCaveats": {
6018
5892
  "customElements": [
6019
- "Assign options as a JavaScript property, set value as a property for application state updates, and listen for dsChange.",
6020
- "Use the form attribute on the host when associating a radio set rendered outside its owning form."
5893
+ "Assign items as a JavaScript property because structured arrays are not represented by HTML attributes.",
5894
+ "Keep value synchronized to a valid enabled item and update the controlled panel from dsChange."
6021
5895
  ],
6022
5896
  "react": [
6023
- "Use DsRadio, pass options as an array, and handle onDsChange; value is mutable and updates after user selection."
5897
+ "Pass items as an array through the generated wrapper, keep value controlled, and use onDsChange to synchronize the visible panel."
6024
5898
  ],
6025
5899
  "angular": [
6026
- "Use DsRadio with options and value bindings plus dsChange, or import the generated radio value accessor with the component adapter."
5900
+ "Bind items and a valid value as properties, and handle dsChange to synchronize the visible panel."
6027
5901
  ]
6028
- },
6029
- "references": [
6030
- {
6031
- "label": "Storybook examples",
6032
- "path": "src/wc/components/Radio/Radio.stories.ts"
6033
- },
6034
- {
6035
- "label": "Cross-browser form and accessibility coverage",
6036
- "path": "tests/e2e/forms.spec.ts"
6037
- }
6038
- ]
5902
+ }
6039
5903
  },
6040
5904
  "props": {
6041
5905
  "ariaLabel": {
@@ -6046,40 +5910,12 @@
6046
5910
  "type": "string | undefined",
6047
5911
  "required": false
6048
5912
  },
6049
- "direction": {
6050
- "type": "'vertical' | 'horizontal'",
6051
- "required": false
6052
- },
6053
- "disabled": {
6054
- "type": "boolean",
6055
- "required": false
6056
- },
6057
- "form": {
6058
- "type": "string | undefined",
6059
- "required": false
6060
- },
6061
- "isInactive": {
6062
- "type": "boolean",
6063
- "required": false
6064
- },
6065
- "name": {
6066
- "type": "string | undefined",
6067
- "required": false
6068
- },
6069
- "options": {
6070
- "type": "RadioOption[]",
6071
- "required": false
6072
- },
6073
- "required": {
6074
- "type": "boolean",
6075
- "required": false
6076
- },
6077
- "requiredMessage": {
6078
- "type": "string",
5913
+ "background": {
5914
+ "type": "PanelSubNavBackground | undefined",
6079
5915
  "required": false
6080
5916
  },
6081
- "size": {
6082
- "type": "RadioSize",
5917
+ "items": {
5918
+ "type": "PanelSubNavItem[]",
6083
5919
  "required": false
6084
5920
  },
6085
5921
  "value": {
@@ -6095,9 +5931,9 @@
6095
5931
  ],
6096
5932
  "slots": [],
6097
5933
  "exports": {
6098
- "customElement": "ds-radio",
6099
- "react": "DsRadio",
6100
- "angular": "DsRadio"
5934
+ "customElement": "ds-panel-sub-nav",
5935
+ "react": "DsPanelSubNav",
5936
+ "angular": "DsPanelSubNav"
6101
5937
  }
6102
5938
  },
6103
5939
  "dependencies": [
@@ -6109,311 +5945,235 @@
6109
5945
  ]
6110
5946
  },
6111
5947
  {
6112
- "name": "scroll-overlay",
6113
- "title": "ScrollOverlay",
6114
- "description": "Generic scroll owner for content that moves behind a persistent footer action or composer with an always-active alpha fade.",
5948
+ "name": "panel-tool-header",
5949
+ "title": "PanelToolHeader",
5950
+ "description": "Canonical left-aligned PanelTools header with an optional leading navigation or dismiss action and application-owned trailing icon actions.",
6115
5951
  "type": "registry:ui",
6116
5952
  "meta": {
6117
5953
  "library": "@ds-mo/ui",
6118
5954
  "distribution": "npm",
6119
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/scroll-overlay",
6120
- "source": "src/wc/components/ScrollOverlay/ScrollOverlay.tsx",
5955
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tool-header",
5956
+ "source": "src/wc/components/PanelToolHeader/PanelToolHeader.tsx",
6121
5957
  "intentStatus": "complete",
6122
5958
  "intent": {
6123
5959
  "audience": "general",
6124
5960
  "status": "experimental",
6125
- "summary": "Generic scroll owner for content that moves behind a persistent footer action or composer with an always-active alpha fade.",
5961
+ "summary": "Canonical left-aligned PanelTools header with an optional leading navigation or dismiss action and application-owned trailing icon actions.",
6126
5962
  "useWhen": [
6127
- "A bounded region owns scrolling while footer actions remain overlaid and continuously visible.",
6128
- "The final content must clear a live-height footer while earlier content can move behind it."
5963
+ "PanelTools needs its one shared root or detail header.",
5964
+ "A tool header needs a title with optional Back or Close navigation, menu, fullscreen, or other compact icon actions."
6129
5965
  ],
6130
5966
  "avoidWhen": [
6131
- "The footer belongs in normal document flow rather than overlaying content.",
6132
- "Another component already owns scrolling and cannot delegate its scrollport to this component."
5967
+ "Rendering inside a PanelTools tool body; PanelTools already composes this canonical header above the body.",
5968
+ "The header belongs to page content."
6133
5969
  ],
6134
5970
  "commonlyComposedWith": [
6135
- "component:ds-button-filled",
6136
- "component:ds-message-composer"
5971
+ "component:ds-button-unfilled"
6137
5972
  ],
6138
5973
  "accessibility": [
6139
- "Provide scrollLabel when the scrollport needs its own named, keyboard-focusable region.",
6140
- "Keep footer actions keyboard accessible and explicitly named; the fade is decorative and never intercepts pointer input."
5974
+ "Leading navigation or dismiss actions and trailing icon actions require concise localized names; the header reuses each name as the action tooltip.",
5975
+ "The visible heading names the active panel or subview."
6141
5976
  ],
6142
5977
  "states": [
6143
- "The alpha mask remains active at every scroll position and moves in content coordinates so it stays pinned behind the footer without masking native scrollbars.",
6144
- "The component measures the complete overlay for end clearance, measures its visible child for fade depth, and begins the fade 8px before that visible content.",
6145
- "An md 32px footer action with 8px bottom inset therefore produces a 48px fade; variable-height composers produce a correspondingly taller measured fade."
5978
+ "The title remains left aligned whether the header has no actions, Back, one trailing action, or several trailing actions.",
5979
+ "Leading and trailing control zones never shrink; only the title consumes and truncates within the remaining width, with a fixed 4px gap between zones.",
5980
+ "Header chrome text is not selectable; actions remain keyboard focusable and interactive.",
5981
+ "Adjacent trailing actions keep the shared 4px control gap in drawer and fullscreen presentations.",
5982
+ "When fullscreen and overflow actions appear together, author fullscreen before overflow so Ellipses remains the rightmost action.",
5983
+ "PanelTools supplies application-owned actions and relays their ids through its shared dsHeaderAction event."
6146
5984
  ],
6147
5985
  "responsiveBehavior": [
6148
- "The scrollport and overlay fill the available width and height; the owner supplies responsive sizing and overlay insets."
5986
+ "The title truncates between optional leading navigation and trailing action zones."
6149
5987
  ],
6150
- "frameworkCaveats": {
6151
- "customElements": [
6152
- "Place scrollable content in the default slot and one footer wrapper in the overlay slot; use dsScroll only when the application needs position data."
6153
- ],
6154
- "react": [
6155
- "Use DsScrollOverlay with ordinary children plus an element carrying slot=\"overlay\"."
6156
- ],
6157
- "angular": [
6158
- "Import DsScrollOverlay and project the persistent footer wrapper with slot=\"overlay\"."
6159
- ]
6160
- },
6161
5988
  "references": [
6162
5989
  {
6163
- "label": "Storybook examples",
6164
- "path": "src/wc/components/ScrollOverlay/ScrollOverlay.stories.ts"
5990
+ "label": "Standalone examples",
5991
+ "path": "src/wc/components/PanelToolHeader/PanelToolHeader.stories.ts"
6165
5992
  }
6166
5993
  ]
6167
5994
  },
6168
5995
  "props": {
6169
- "scrollLabel": {
5996
+ "actions": {
5997
+ "type": "PanelToolsHeaderAction[]",
5998
+ "required": false
5999
+ },
6000
+ "backAriaLabel": {
6001
+ "type": "string",
6002
+ "required": false
6003
+ },
6004
+ "backIcon": {
6005
+ "type": "string",
6006
+ "required": false
6007
+ },
6008
+ "heading": {
6009
+ "type": "string",
6010
+ "required": false
6011
+ },
6012
+ "menuAriaLabel": {
6013
+ "type": "string",
6014
+ "required": false
6015
+ },
6016
+ "menuControls": {
6170
6017
  "type": "string | undefined",
6171
6018
  "required": false
6019
+ },
6020
+ "menuExpanded": {
6021
+ "type": "boolean",
6022
+ "required": false
6023
+ },
6024
+ "menuTriggerId": {
6025
+ "type": "string",
6026
+ "required": false
6027
+ },
6028
+ "showBack": {
6029
+ "type": "boolean",
6030
+ "required": false
6031
+ },
6032
+ "showMenu": {
6033
+ "type": "boolean",
6034
+ "required": false
6172
6035
  }
6173
6036
  },
6174
6037
  "events": [
6175
6038
  {
6176
- "name": "dsScroll",
6177
- "detail": "ScrollOverlayScrollDetail"
6039
+ "name": "dsAction",
6040
+ "detail": "{ id: string; originalEvent: MouseEvent }"
6041
+ },
6042
+ {
6043
+ "name": "dsBack",
6044
+ "detail": "MouseEvent"
6045
+ },
6046
+ {
6047
+ "name": "dsMenuToggle",
6048
+ "detail": "MouseEvent"
6178
6049
  }
6179
6050
  ],
6180
6051
  "slots": [],
6181
6052
  "exports": {
6182
- "customElement": "ds-scroll-overlay",
6183
- "react": "DsScrollOverlay",
6184
- "angular": "DsScrollOverlay"
6053
+ "customElement": "ds-panel-tool-header",
6054
+ "react": "DsPanelToolHeader",
6055
+ "angular": "DsPanelToolHeader"
6185
6056
  }
6186
6057
  },
6187
6058
  "dependencies": [
6188
6059
  "@ds-mo/ui",
6189
6060
  "@ds-mo/tokens"
6190
6061
  ],
6191
- "registryDependencies": []
6062
+ "registryDependencies": [
6063
+ "button-unfilled",
6064
+ "text",
6065
+ "tooltip"
6066
+ ]
6192
6067
  },
6193
6068
  {
6194
- "name": "select",
6195
- "title": "Select",
6196
- "description": "Form-associated single-value select with listbox semantics, local search, rich flat options, grouped sections, loading, clearing, and surface-aware trigger chrome.",
6069
+ "name": "panel-tool-search",
6070
+ "title": "PanelToolSearch",
6071
+ "description": "Transparent search row for the top of a PanelTools product view, with a fixed 48px allocation around the standard md search control and an optional filter-menu trigger.",
6197
6072
  "type": "registry:ui",
6198
6073
  "meta": {
6199
6074
  "library": "@ds-mo/ui",
6200
6075
  "distribution": "npm",
6201
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/select",
6202
- "source": "src/wc/components/Select/Select.tsx",
6076
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tool-search",
6077
+ "source": "src/wc/components/PanelToolSearch/PanelToolSearch.tsx",
6203
6078
  "intentStatus": "complete",
6204
6079
  "intent": {
6205
6080
  "audience": "general",
6206
- "status": "stable",
6207
- "summary": "Form-associated single-value select with listbox semantics, local search, rich flat options, grouped sections, loading, clearing, and surface-aware trigger chrome.",
6081
+ "status": "experimental",
6082
+ "summary": "Transparent search row for the top of a PanelTools product view, with a fixed 48px allocation around the standard md search control and an optional filter-menu trigger.",
6208
6083
  "useWhen": [
6209
- "The user must choose one value from a finite set.",
6210
- "The option set benefits from local search, subtext, prefix icons, grouping, or disabled choices.",
6211
- "The choice set has more than roughly 20 options, comes from a user-managed listing, or represents a large domain such as addresses where search materially improves retrieval.",
6212
- "The selected value must participate in native, Angular, or React form state."
6084
+ "A PanelTools base view filters or searches the tool's own content.",
6085
+ "Several tool products need the same search-row geometry directly below the shared PanelTools header.",
6086
+ "The product needs a compact filter menu next to search while keeping its filter choices and matching policy application-owned."
6213
6087
  ],
6214
6088
  "avoidWhen": [
6215
- "Several values may be selected at once.",
6216
- "The rows perform commands rather than choosing a form value.",
6217
- "The choices form a hierarchy with expandable parents."
6218
- ],
6219
- "alternatives": [
6220
- {
6221
- "when": "Several independent values may be selected.",
6222
- "component": "component:ds-select-multi",
6223
- "reason": "SelectMulti owns array values, multi-selection semantics, and count presentation."
6224
- },
6225
- {
6226
- "when": "The popup contains commands or state-changing actions.",
6227
- "component": "component:ds-menu",
6228
- "reason": "Menu uses action-menu roles and command-focused keyboard behavior."
6229
- },
6230
- {
6231
- "when": "A small set of choices should remain visible.",
6232
- "component": "component:ds-radio",
6233
- "reason": "Prefer Radio for roughly two to five mutually exclusive choices when the available space allows all choices to remain visible."
6234
- }
6089
+ "The search belongs inside a Select or SelectMulti popup; use that component's searchable behavior.",
6090
+ "A form needs a labelled standalone field; compose ds-input inside ds-field instead."
6235
6091
  ],
6236
6092
  "commonlyComposedWith": [
6237
- "component:ds-text",
6238
- "component:ds-icon",
6239
- "component:ds-empty-state",
6240
- "component:ds-loader"
6093
+ "component:ds-panel-tools",
6094
+ "component:ds-conversation-list",
6095
+ "component:ds-input"
6241
6096
  ],
6242
6097
  "accessibility": [
6243
- "In forms, provide a persistent visible external field label; placeholder text is guidance and must not be the field's only label. In a compact filter bar, the trigger's visible text may supply the accessible name.",
6244
- "The trigger uses combobox semantics and the popup uses listbox and option semantics; do not replace them with menu roles.",
6245
- "Disabled options remain visible, expose aria-disabled, and are skipped by keyboard navigation and typeahead.",
6246
- "Keyboard navigation keeps the aria-activedescendant option scrolled into the visible listbox viewport.",
6247
- "Selected options rely on active fill and foreground treatment without a redundant trailing check icon.",
6248
- "Local search moves focus into the search field while preserving the active option through aria-activedescendant.",
6249
- "Use errorMessage with error so the trigger is described by the rendered alert."
6098
+ "Provide an aria-label that names the searched domain, such as Search agent chats or Search messages.",
6099
+ "The standard search clear action restores focus, uses the concise localized clearLabel by itself for both its tooltip and accessible name, and emits both the empty query and dsClear.",
6100
+ "When showFilter is enabled, provide stable filterTriggerId and filterControls values, synchronize filterExpanded with the controlled menu, and restore focus after selection; filterAriaLabel also labels its tooltip."
6250
6101
  ],
6251
6102
  "states": [
6252
- "Value is controlled through the mutable value property; dsChange reports user selection and clearing.",
6253
- "Required Selects begin without an automatic selection and require the user to make an explicit choice; do not preselect the first option merely to satisfy validity.",
6254
- "When allowClear is enabled, the clear affordance appears only after a value exists. Clearing is valid for optional and required fields; a required field becomes invalid until the user selects again.",
6255
- "Clearing emits dsChange with an empty string and dsClear, keeps the popup open, and restores useful focus.",
6256
- "Loading keeps the trigger visible, replaces its prefix icon, marks the control busy, and makes selection interaction temporarily unavailable without presenting the control as inactive.",
6257
- "The trigger label stays left-aligned at every width. The default size is md in both forms and filter bars; smaller sizes require an explicit density need.",
6258
- "Use option icons only when they help users differentiate choices. Icons render only when every option in the complete list provides one; mixed icon data falls back to the text-only row layout.",
6259
- "Create sections only for categories that are meaningful to customers, not merely to break a long list into arbitrary chunks.",
6260
- "When any option supplies subtext, every row uses the same subtext structure and missing values render an em dash. Subtext should disambiguate or add decision-helpful information.",
6261
- "Option labels and the selected trigger label stay on one line and truncate when constrained. Option subtext may wrap to at most two lines.",
6262
- "The optional prefix icon and chevron always use the parent surface's secondary foreground color, including when a selected value promotes the label to primary.",
6263
- "The shared popup search control stays md at every trigger size, using body-medium text, a 20px icon, and the same internal spacing as a borderless Select trigger. Its container uses menu-item padding on every side and owns a 1px bottom divider that becomes a 1.5px bold-brand stroke while search has focus. Search placeholder text is secondary at rest and quaternary while focused because it becomes decorative once the editable field is active.",
6264
- "When search contains text, the shared control shows a rounded sm icon-only ButtonUnfilled with the CrossCircle icon and no border. It clears the local term, stays hidden for an empty term, and returns focus to search.",
6265
- "The shared clear footer mirrors the search region's sizing: menu-item padding surrounds an md-height borderless row, and the Clear label uses the same row and label insets as option text. The outer footer owns a 1px top divider.",
6266
- "An empty filtered list composes the message-only body variant of EmptyState. Keep the default neutral no-results message unless localized product guidance makes the outcome clearer.",
6267
- "Enable searchable for more than roughly 20 options, user-managed listings, large domains such as addresses, or sets users cannot efficiently scan. Local matching includes option labels, subtext, and section headings; the owner resolves remote data before assigning options.",
6268
- "Validation timing belongs to the form owner and may be immediate or deferred until blur or submit; the Select exposes validity and error presentation without imposing that policy.",
6269
- "The error trigger uses a 1.5px bold-negative inset stroke so invalid state remains distinguishable from the normal 1px border without changing control geometry.",
6270
- "An initially empty option set is not an expected Select use case. The no-results state describes a search with no matches, not a source with no choices.",
6271
- "Use options for a flat list or sections for grouped choices; when sections are present they take precedence.",
6272
- "The background prop describes the actual parent surface and uses the same surface set as ButtonUnfilled."
6103
+ "The row is always 48px high with 8px outer padding and a complete md search recipe: 32px control, text-body-medium at 14px/20px, and a 20px md search icon.",
6104
+ "The search icon stays foreground-secondary at rest, hover, focus, active, and while the query is filled.",
6105
+ "The row and control surface remain transparent so the ShellApp chrome wash is visible behind them.",
6106
+ "The row divider remains the same tertiary 1px boundary while the input is focused because it belongs to the 48px container rather than the input control.",
6107
+ "With filtering enabled, the md search control, decorative vertical divider, and borderless md Filter action are separated by 8px; filterActive promotes only the trigger foreground without adding a selected fill."
6273
6108
  ],
6274
6109
  "responsiveBehavior": [
6275
- "Use width fill for form fields and width hug for compact filter bars. Override those defaults only when the owning layout has a clear constraint.",
6276
- "The popup matches the trigger minimum width, may grow for content, and clamps to the viewport.",
6277
- "Long option collections scroll inside the popup; virtualization and remote search are not part of this component."
6110
+ "The row fills the available drawer or fullscreen width, allows its search region to shrink inside a 300px drawer without pushing the filter trigger under the tool rail, and does not reduce its control below md density."
6278
6111
  ],
6279
6112
  "frameworkCaveats": {
6280
6113
  "customElements": [
6281
- "Assign options and sections through JavaScript properties because arrays and objects cannot be represented safely as attributes."
6114
+ "Listen for dsChange to receive the current string query and dsClear when the clear action is used.",
6115
+ "Listen for dsFilterToggle and pair the trigger with an externally controlled ds-menu; product-specific filter labels and filtering remain outside this component."
6282
6116
  ],
6283
6117
  "react": [
6284
- "Pass options or sections as wrapper props and handle onDsChange, onDsClear, and onDsOpenChange."
6118
+ "Use DsPanelToolSearch, bind value for controlled state, and handle onDsChange.",
6119
+ "Bind the optional filter trigger state and connect onDsFilterToggle to a controlled DsMenu."
6285
6120
  ],
6286
6121
  "angular": [
6287
- "Import DsSelect and SelectValueAccessor when integrating with Angular Forms; bind options and sections as properties."
6122
+ "Import DsPanelToolSearch and bind value as a property; this search composition is not a form value accessor.",
6123
+ "Bind showFilter, filterExpanded, and filterActive, then connect dsFilterToggle to a product-owned ds-menu."
6288
6124
  ]
6289
6125
  },
6290
6126
  "references": [
6291
6127
  {
6292
6128
  "label": "Storybook examples",
6293
- "path": "src/wc/components/Select/Select.stories.ts"
6294
- },
6295
- {
6296
- "label": "Selection patterns",
6297
- "path": "src/docs/SelectionPatterns.mdx"
6129
+ "path": "src/wc/components/PanelToolSearch/PanelToolSearch.stories.ts"
6298
6130
  }
6299
6131
  ]
6300
6132
  },
6301
6133
  "props": {
6302
- "activeFill": {
6303
- "type": "boolean",
6134
+ "ariaLabel": {
6135
+ "type": "string",
6304
6136
  "required": false
6305
6137
  },
6306
- "allowClear": {
6307
- "type": "boolean",
6138
+ "controls": {
6139
+ "type": "string | undefined",
6308
6140
  "required": false
6309
6141
  },
6310
- "ariaDescribedby": {
6311
- "type": "string | undefined",
6142
+ "filterActive": {
6143
+ "type": "boolean",
6312
6144
  "required": false
6313
6145
  },
6314
- "ariaLabel": {
6315
- "type": "string | null",
6146
+ "filterAriaLabel": {
6147
+ "type": "string",
6316
6148
  "required": false
6317
6149
  },
6318
- "ariaLabelledby": {
6150
+ "filterControls": {
6319
6151
  "type": "string | undefined",
6320
6152
  "required": false
6321
6153
  },
6322
- "background": {
6323
- "type": "SelectBackground | undefined",
6154
+ "filterExpanded": {
6155
+ "type": "boolean",
6324
6156
  "required": false
6325
6157
  },
6326
- "clearLabel": {
6158
+ "filterTriggerId": {
6327
6159
  "type": "string",
6328
6160
  "required": false
6329
6161
  },
6330
- "disabled": {
6162
+ "isInactive": {
6331
6163
  "type": "boolean",
6332
6164
  "required": false
6333
6165
  },
6334
- "error": {
6335
- "type": "boolean",
6166
+ "placeholder": {
6167
+ "type": "string",
6336
6168
  "required": false
6337
6169
  },
6338
- "errorMessage": {
6339
- "type": "string | undefined",
6340
- "required": false
6341
- },
6342
- "hasBorder": {
6343
- "type": "boolean",
6344
- "required": false
6345
- },
6346
- "icon": {
6347
- "type": "string | undefined",
6348
- "required": false
6349
- },
6350
- "inputId": {
6351
- "type": "string | undefined",
6352
- "required": false
6353
- },
6354
- "isInactive": {
6355
- "type": "boolean",
6356
- "required": false
6357
- },
6358
- "isLoading": {
6359
- "type": "boolean",
6360
- "required": false
6361
- },
6362
- "loadingLabel": {
6363
- "type": "string",
6364
- "required": false
6365
- },
6366
- "name": {
6367
- "type": "string | undefined",
6368
- "required": false
6369
- },
6370
- "noResultsText": {
6371
- "type": "string",
6372
- "required": false
6373
- },
6374
- "open": {
6375
- "type": "boolean",
6376
- "required": false
6377
- },
6378
- "options": {
6379
- "type": "SelectOption[]",
6380
- "required": false
6381
- },
6382
- "placeholder": {
6383
- "type": "string",
6384
- "required": false
6385
- },
6386
- "required": {
6387
- "type": "boolean",
6388
- "required": false
6389
- },
6390
- "requiredMessage": {
6391
- "type": "string",
6392
- "required": false
6393
- },
6394
- "searchPlaceholder": {
6395
- "type": "string",
6396
- "required": false
6397
- },
6398
- "searchable": {
6170
+ "showFilter": {
6399
6171
  "type": "boolean",
6400
6172
  "required": false
6401
6173
  },
6402
- "sections": {
6403
- "type": "SelectSection[]",
6404
- "required": false
6405
- },
6406
- "size": {
6407
- "type": "SelectSize",
6408
- "required": false
6409
- },
6410
6174
  "value": {
6411
6175
  "type": "string",
6412
6176
  "required": false
6413
- },
6414
- "width": {
6415
- "type": "SelectWidth",
6416
- "required": false
6417
6177
  }
6418
6178
  },
6419
6179
  "events": [
@@ -6426,15 +6186,15 @@
6426
6186
  "detail": "void"
6427
6187
  },
6428
6188
  {
6429
- "name": "dsOpenChange",
6430
- "detail": "boolean"
6189
+ "name": "dsFilterToggle",
6190
+ "detail": "MouseEvent"
6431
6191
  }
6432
6192
  ],
6433
6193
  "slots": [],
6434
6194
  "exports": {
6435
- "customElement": "ds-select",
6436
- "react": "DsSelect",
6437
- "angular": "DsSelect"
6195
+ "customElement": "ds-panel-tool-search",
6196
+ "react": "DsPanelToolSearch",
6197
+ "angular": "DsPanelToolSearch"
6438
6198
  }
6439
6199
  },
6440
6200
  "dependencies": [
@@ -6444,189 +6204,155 @@
6444
6204
  ],
6445
6205
  "registryDependencies": [
6446
6206
  "button-unfilled",
6447
- "empty-state",
6207
+ "divider",
6448
6208
  "icon",
6449
- "loader",
6450
6209
  "text",
6451
6210
  "tooltip"
6452
6211
  ]
6453
6212
  },
6454
6213
  {
6455
- "name": "select-multi",
6456
- "title": "SelectMulti",
6457
- "description": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
6214
+ "name": "panel-tools",
6215
+ "title": "PanelTools",
6216
+ "description": "Required ShellApp utility rail and persistent drawer host for the fixed set of global Search, Agents, Messages, Stacks, Activity, and Help products.",
6458
6217
  "type": "registry:ui",
6459
6218
  "meta": {
6460
6219
  "library": "@ds-mo/ui",
6461
6220
  "distribution": "npm",
6462
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/select-multi",
6463
- "source": "src/wc/components/SelectMulti/SelectMulti.tsx",
6221
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/panel-tools",
6222
+ "source": "src/wc/components/PanelTools/PanelTools.tsx",
6464
6223
  "intentStatus": "complete",
6465
6224
  "intent": {
6466
- "audience": "general",
6225
+ "audience": "specialized",
6467
6226
  "status": "stable",
6468
- "summary": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
6227
+ "summary": "Required ShellApp utility rail and persistent drawer host for the fixed set of global Search, Agents, Messages, Stacks, Activity, and Help products.",
6469
6228
  "useWhen": [
6470
- "The user may choose several independent values from one finite set.",
6471
- "A compact trigger should summarize selection with the field label and a count.",
6472
- "The option set benefits from local search, subtext, grouping, or disabled choices.",
6473
- "The choice set has more than roughly 20 options, comes from a user-managed listing, or represents a large domain where search materially improves retrieval."
6229
+ "Composing the required global tools region inside the application's single ShellApp.",
6230
+ "Users need to move between application-wide utilities without losing each tool's in-progress state.",
6231
+ "Search, AI conversations, user messages, review stacks, notifications, or help content must remain available alongside route content."
6474
6232
  ],
6475
6233
  "avoidWhen": [
6476
- "Exactly one value may be selected.",
6477
- "Selected values must remain individually removable as persistent tags outside the popup.",
6478
- "The choices form a hierarchy with cascading parent selection.",
6479
- "The customer task benefits more from keeping every choice and checkbox directly visible; choose between SelectMulti and a visible checkbox list from the use-case context rather than a fixed option-count threshold."
6234
+ "The action is specific to the current page or selected content rather than globally available across the application.",
6235
+ "The item navigates to a primary or secondary route; use PanelNav or BarNav instead.",
6236
+ "A consumer wants to add arbitrary tools, reorder fixed tools, or repurpose a semantic tool id.",
6237
+ "Building the mobile tools experience; future mobile ShellApp composition uses a different bottom-bar and panel pattern.",
6238
+ "PanelTools would be mounted outside the application's single ShellApp."
6480
6239
  ],
6481
6240
  "alternatives": [
6482
6241
  {
6483
- "when": "Exactly one value may be selected.",
6484
- "component": "component:ds-select",
6485
- "reason": "Select owns scalar form value and single-select listbox behavior."
6242
+ "when": "The action navigates to a top-level application destination.",
6243
+ "component": "component:ds-panel-nav",
6244
+ "reason": "PanelNav exclusively owns primary application navigation."
6486
6245
  },
6487
6246
  {
6488
- "when": "The popup contains actions rather than values.",
6247
+ "when": "The action navigates between route sections of the active destination.",
6248
+ "component": "component:ds-bar-nav",
6249
+ "reason": "BarNav exclusively owns secondary route navigation."
6250
+ },
6251
+ {
6252
+ "when": "Temporary contextual actions or options are needed.",
6489
6253
  "component": "component:ds-menu",
6490
- "reason": "Menu uses command semantics and closes according to action-menu expectations."
6254
+ "reason": "Menu owns transient contextual choices rather than persistent global products."
6491
6255
  }
6492
6256
  ],
6493
6257
  "commonlyComposedWith": [
6494
- "component:ds-text",
6495
- "component:ds-checkbox",
6496
- "component:ds-empty-state",
6497
- "component:ds-loader"
6258
+ "component:ds-shell-app",
6259
+ "component:ds-panel-nav",
6260
+ "component:ds-bar-nav"
6261
+ ],
6262
+ "patterns": [
6263
+ "pattern:application-shell"
6498
6264
  ],
6499
6265
  "accessibility": [
6500
- "In forms, provide a persistent visible external field label. In a compact filter bar, the trigger's visible persistent label and count may supply the accessible name.",
6501
- "The popup is a listbox with aria-multiselectable and every option exposes its independent aria-selected state.",
6502
- "Disabled options expose aria-disabled and are skipped by keyboard navigation and typeahead.",
6503
- "Keyboard navigation keeps the aria-activedescendant option scrolled into the visible listbox viewport.",
6504
- "Each row uses a medium-size presentation-only ds-checkbox indicator; multi-select option rows never add a prefix icon alongside it, and the option remains the sole selection semantic and interaction target.",
6505
- "The trigger keeps its field label visible and appends the current selected count; an explicit aria-label or aria-labelledby remains the authoritative accessible name when supplied.",
6506
- "Use errorMessage with error so the trigger is described by the rendered alert."
6266
+ "Provide localized accessible labels for the rail, shortcut group, and every rendered tool.",
6267
+ "Keep Search first in the rail header and Help last in the rail footer so keyboard and visual order remain predictable.",
6268
+ "Keep focus on the selected rail action when opening a drawer and allow normal Tab navigation into its content.",
6269
+ "Do not trigger global shortcuts while focus is in an editable control.",
6270
+ "Use notification dots only as supplemental unread or new-content status and never as the sole status indication.",
6271
+ "Explain temporarily inactive tools through an accessible label or adjacent product guidance; omit unauthorized tools entirely."
6507
6272
  ],
6508
6273
  "states": [
6509
- "Values is a controlled JavaScript array; dsChange emits a new array after each user toggle.",
6510
- "Required SelectMulti controls begin without an automatic selection and require the user to make an explicit choice.",
6511
- "Selecting an option keeps the popup open so additional values can be toggled.",
6512
- "The trigger label stays left-aligned at every width; every option row uses the same leading medium Checkbox indicator. The default control size is md in both forms and filter bars.",
6513
- "The selected count always follows the persistent label as plain text separated by a centered dot, including for one selection, and counts every selected value even when search or grouping hides it. Never replace the count with selected option names.",
6514
- "Create sections only for categories that are meaningful to customers, not merely to break a long list into arbitrary chunks.",
6515
- "When any option supplies subtext, every row uses the same subtext structure and missing values render an em dash. Subtext should disambiguate or add decision-helpful information.",
6516
- "Option labels stay on one line and truncate when constrained. Option subtext may wrap to at most two lines.",
6517
- "The optional prefix icon and chevron always use the parent surface's secondary foreground color, including when selection promotes the label and count to primary.",
6518
- "The shared popup search control stays md at every trigger size, using body-medium text, a 20px icon, and the same internal spacing as a borderless Select trigger. Its container uses menu-item padding on every side and owns a 1px bottom divider that becomes a 1.5px bold-brand stroke while search has focus. Search placeholder text is secondary at rest and quaternary while focused because it becomes decorative once the editable field is active.",
6519
- "When search contains text, the shared control shows a rounded sm icon-only ButtonUnfilled with the Cross icon and no border. It clears the local term, stays hidden for an empty term, and returns focus to search.",
6520
- "The shared summary-and-clear footer mirrors the search region's sizing: menu-item padding surrounds an md-height borderless row, and both texts use the same row and label insets as option text. The outer footer owns a 1px top divider.",
6521
- "An empty filtered list composes the message-only body variant of EmptyState. Keep the default neutral no-results message unless localized product guidance makes the outcome clearer.",
6522
- "Enable searchable for more than roughly 20 options, user-managed listings, large domains such as addresses, or sets users cannot efficiently scan. Local matching includes option labels, subtext, and section headings; the owner resolves remote data before assigning options.",
6523
- "When allowClear is enabled, clear-all appears only after at least one value exists. Clearing is valid for optional and required fields; a required field becomes invalid until the user selects again.",
6524
- "Clear-all emits an empty dsChange and dsClear while preserving useful popup or search focus.",
6525
- "Loading keeps the trigger visible, marks the control busy, and makes selection interaction temporarily unavailable without presenting the control as inactive.",
6526
- "SelectMulti has no maximum-selection behavior; every available non-inactive option may be selected.",
6527
- "Validation timing belongs to the form owner and may be immediate or deferred until blur or submit; the component exposes validity and error presentation without imposing that policy.",
6528
- "The error trigger uses a 1.5px bold-negative inset stroke so invalid state remains distinguishable from the normal 1px border without changing control geometry.",
6529
- "An initially empty option set is not an expected SelectMulti use case. The no-results state describes a search with no matches, not a source with no choices.",
6530
- "Native form submission emits one entry per selected value under the component name.",
6531
- "Use options for a flat list or sections for grouped choices. Multi-select option contracts intentionally exclude icons because the leading checkbox owns that row zone; hierarchical parent selection is deferred."
6274
+ "Search and Help are required; optional Agents, Messages, Stacks, and Activity tools are filtered by the application for authorization and entitlement.",
6275
+ "Use only the fixed semantic tool ids and canonical order: Search, Agents, Messages, Stacks, Activity, Help; do not reorder, duplicate, or repurpose them.",
6276
+ "Search is application-wide; Agents is user-to-AI chat; Messages is user-to-user chat; Stacks is a specialized inbox of grouped application events for review; Activity is the notification center; Help is drawer content that may link to external resources.",
6277
+ "Only one drawer is open at a time; selecting another tool switches directly and selecting the active tool closes to rail-only mode.",
6278
+ "The drawer starts closed, remains open across ordinary route changes, and retains every mounted tool's independent conversation, query, scroll, and work state.",
6279
+ "When storageKey is set, persist only the last active tool in this browser and still restore the drawer closed after reload.",
6280
+ "The application owns unread state; opening Messages, Agents, Stacks, or Activity does not automatically clear its notification dot.",
6281
+ "PanelTools owns the one visible header above every drawer tool view and above fullscreen views using the default shared header mode. Slotted tool content must not render a second header unless the conversation product explicitly opts into split fullscreen headers.",
6282
+ "PanelTools composes ds-panel-tool-header as its canonical left-aligned header implementation so standalone header stories and shell rendering cannot diverge.",
6283
+ "Each tool supplies its current header title, base-versus-detail Back state, and right-side actions through the headers property. Base views omit Back; deeper views expose Back and update the same header in place.",
6284
+ "Header Back and action events express intent only; the owning tool changes product navigation, menus, and data state. PanelTools keeps the final header action exactly 8px from the drawer edge.",
6285
+ "Menus opened from a right-side header action use PANEL_TOOLS_HEADER_MENU_PLACEMENT: bottom/end choice-cell alignment and a 12px side offset, placing the popup 4px below the 48px header while aligning the final menu item edge with the trigger.",
6286
+ "Tool view roots stay transparent so ShellApp's chrome wash remains visible; only explicitly designed child surfaces introduce a fill.",
6287
+ "Tools with search compose ds-panel-tool-search immediately below the shared header. Its 48px row always contains the md search control and must not be reduced to sm or xs.",
6288
+ "If an active optional tool becomes unavailable, PanelTools closes the drawer, clears activeTool, and emits its deselection.",
6289
+ "Use isInactive only for a temporarily unavailable visible tool; omit tools the user is not authorized to access.",
6290
+ "The application owns slotted tool products and data while PanelTools owns rail ordering, drawer selection, open state, motion, and shell events.",
6291
+ "Opening and closing clip an already-rendered fixed-width surface. Header and tool content remain fully opaque and retained during width motion; transition completion is accepted only at the measured terminal clip width, after which the closed surface becomes inert and paint-skipped.",
6292
+ "Entering and exiting fullscreen snaps without borrowing the drawer open or close animation.",
6293
+ "When fullscreenHeaderMode is split, PanelTools suppresses only its fullscreen shared header. The application renders exactly two canonical ds-panel-tool-header instances: a tool-title/list-actions header over the 300px history pane and a chat-title/Exit-fullscreen/chat-actions header over the detail pane. The detail header omits Back because the list remains visible."
6532
6294
  ],
6533
6295
  "responsiveBehavior": [
6534
- "Use width fill for form fields and width hug for compact filter bars; the persistent trigger label avoids variable-width selected labels.",
6535
- "The popup matches the trigger minimum width, may grow for content, and clamps to the viewport.",
6536
- "Long option collections scroll inside the popup; virtualization and remote search are not part of this version."
6296
+ "The open drawer reduces main-content width and uses --dimension-panel-width-xs (300px) on every supported desktop and tablet viewport.",
6297
+ "ShellApp owns the fixed drawer-width variable; consumers must not hardcode alternate drawer widths.",
6298
+ "Below 768px, do not reuse desktop PanelTools: future ShellApp mobile composition uses a bottom bar for Search, Agents, Notifications, and Stacks, while Help moves into mobile primary navigation.",
6299
+ "Keep named-slot content mounted while tools switch or the drawer closes so users can return to in-progress global work.",
6300
+ "Conversation products may use fullscreenHeaderMode split for a 300px history rail beside a flexible detail pane, each with its own canonical header; the application owns that internal split layout.",
6301
+ "Use fixed drawer widths for now; do not add user resizing or width persistence."
6537
6302
  ],
6538
6303
  "frameworkCaveats": {
6539
6304
  "customElements": [
6540
- "Assign values, options, and sections through JavaScript properties; array values cannot be represented safely as attributes."
6305
+ "Assign items as a JavaScript property for structured data; items-json is the string fallback.",
6306
+ "Assign headers as a JavaScript property and replace its object identity whenever an active tool changes title, depth, or actions.",
6307
+ "Keep PanelTools mounted at ShellApp scope across route changes and provide each product through its matching named slot."
6541
6308
  ],
6542
6309
  "react": [
6543
- "Pass values, options, and sections as wrapper props and handle onDsChange, onDsClear, and onDsOpenChange."
6310
+ "Pass the fixed item collection through the generated React wrapper and keep named-slot product content mounted at ShellApp scope.",
6311
+ "Use storageKey only for same-browser last-tool continuity; do not persist the open drawer."
6544
6312
  ],
6545
6313
  "angular": [
6546
- "Import DsSelectMulti and SelectMultiValueAccessor when integrating with Angular Forms."
6314
+ "Import DsPanelTools from @ds-mo/ui/angular/ds-panel-tools and bind items as a property.",
6315
+ "Bind headers as a replaced object and route dsHeaderBack and dsHeaderAction to the active tool owner.",
6316
+ "Keep the component in the persistent shell layout rather than recreating it in routed page components."
6547
6317
  ]
6548
6318
  },
6549
6319
  "references": [
6550
6320
  {
6551
- "label": "Storybook examples",
6552
- "path": "src/wc/components/SelectMulti/SelectMulti.stories.ts"
6321
+ "label": "Executable Storybook examples",
6322
+ "path": "src/wc/components/PanelTools/PanelTools.stories.ts"
6553
6323
  },
6554
6324
  {
6555
- "label": "Selection patterns",
6556
- "path": "src/docs/SelectionPatterns.mdx"
6325
+ "label": "Framework and shell integration",
6326
+ "path": "docs/framework-integration.md"
6327
+ },
6328
+ {
6329
+ "label": "Application shell composition",
6330
+ "path": "agent/patterns/application-shell/pattern.agent.json"
6557
6331
  }
6558
6332
  ]
6559
6333
  },
6560
6334
  "props": {
6561
- "activeFill": {
6562
- "type": "boolean",
6563
- "required": false
6564
- },
6565
- "allowClear": {
6566
- "type": "boolean",
6335
+ "activeTool": {
6336
+ "type": "PanelToolsToolId | ''",
6567
6337
  "required": false
6568
6338
  },
6569
- "ariaDescribedby": {
6570
- "type": "string | undefined",
6339
+ "fullscreenHeaderMode": {
6340
+ "type": "'shared' | 'split'",
6571
6341
  "required": false
6572
6342
  },
6573
- "ariaLabel": {
6574
- "type": "string | null",
6343
+ "headers": {
6344
+ "type": "PanelToolsHeaders",
6575
6345
  "required": false
6576
6346
  },
6577
- "ariaLabelledby": {
6578
- "type": "string | undefined",
6347
+ "headersJson": {
6348
+ "type": "string",
6579
6349
  "required": false
6580
6350
  },
6581
- "background": {
6582
- "type": "SelectMultiBackground | undefined",
6351
+ "items": {
6352
+ "type": "PanelToolsItem[]",
6583
6353
  "required": false
6584
6354
  },
6585
- "clearLabel": {
6586
- "type": "string",
6587
- "required": false
6588
- },
6589
- "disabled": {
6590
- "type": "boolean",
6591
- "required": false
6592
- },
6593
- "error": {
6594
- "type": "boolean",
6595
- "required": false
6596
- },
6597
- "errorMessage": {
6598
- "type": "string | undefined",
6599
- "required": false
6600
- },
6601
- "hasBorder": {
6602
- "type": "boolean",
6603
- "required": false
6604
- },
6605
- "icon": {
6606
- "type": "string | undefined",
6607
- "required": false
6608
- },
6609
- "inputId": {
6610
- "type": "string | undefined",
6611
- "required": false
6612
- },
6613
- "isInactive": {
6614
- "type": "boolean",
6615
- "required": false
6616
- },
6617
- "isLoading": {
6618
- "type": "boolean",
6619
- "required": false
6620
- },
6621
- "loadingLabel": {
6622
- "type": "string",
6623
- "required": false
6624
- },
6625
- "name": {
6626
- "type": "string | undefined",
6627
- "required": false
6628
- },
6629
- "noResultsText": {
6355
+ "itemsJson": {
6630
6356
  "type": "string",
6631
6357
  "required": false
6632
6358
  },
@@ -6634,810 +6360,1191 @@
6634
6360
  "type": "boolean",
6635
6361
  "required": false
6636
6362
  },
6637
- "options": {
6638
- "type": "SelectMultiOption[]",
6639
- "required": false
6640
- },
6641
- "placeholder": {
6642
- "type": "string",
6643
- "required": false
6644
- },
6645
- "required": {
6646
- "type": "boolean",
6363
+ "presentation": {
6364
+ "type": "'drawer' | 'fullscreen'",
6647
6365
  "required": false
6648
6366
  },
6649
- "requiredMessage": {
6367
+ "storageKey": {
6650
6368
  "type": "string",
6651
6369
  "required": false
6652
6370
  },
6653
- "searchPlaceholder": {
6371
+ "toolShortcutsLabel": {
6654
6372
  "type": "string",
6655
6373
  "required": false
6656
6374
  },
6657
- "searchable": {
6658
- "type": "boolean",
6659
- "required": false
6660
- },
6661
- "sections": {
6662
- "type": "SelectMultiSection[]",
6663
- "required": false
6664
- },
6665
- "selectedLabel": {
6375
+ "toolsLabel": {
6666
6376
  "type": "string",
6667
6377
  "required": false
6668
- },
6669
- "size": {
6670
- "type": "SelectMultiSize",
6671
- "required": false
6672
- },
6673
- "values": {
6674
- "type": "string[]",
6675
- "required": false
6676
- },
6677
- "width": {
6678
- "type": "SelectMultiWidth",
6679
- "required": false
6680
6378
  }
6681
6379
  },
6682
6380
  "events": [
6683
6381
  {
6684
- "name": "dsChange",
6685
- "detail": "string[]"
6382
+ "name": "dsChromeTransitionEnd",
6383
+ "detail": "ChromeTransitionDetail"
6686
6384
  },
6687
6385
  {
6688
- "name": "dsClear",
6689
- "detail": "void"
6386
+ "name": "dsChromeTransitionStart",
6387
+ "detail": "ChromeTransitionDetail"
6690
6388
  },
6691
6389
  {
6692
- "name": "dsOpenChange",
6693
- "detail": "boolean"
6390
+ "name": "dsHeaderAction",
6391
+ "detail": "{\n tool: PanelToolsToolId;\n id: string;\n }"
6392
+ },
6393
+ {
6394
+ "name": "dsHeaderBack",
6395
+ "detail": "{\n tool: PanelToolsToolId;\n }"
6396
+ },
6397
+ {
6398
+ "name": "dsPresentationChange",
6399
+ "detail": "{\n presentation: 'drawer' | 'fullscreen';\n }"
6400
+ },
6401
+ {
6402
+ "name": "dsToolChange",
6403
+ "detail": "{\n id: PanelToolsToolId;\n selected: boolean;\n }"
6694
6404
  }
6695
6405
  ],
6696
6406
  "slots": [],
6697
6407
  "exports": {
6698
- "customElement": "ds-select-multi",
6699
- "react": "DsSelectMulti",
6700
- "angular": "DsSelectMulti"
6408
+ "customElement": "ds-panel-tools",
6409
+ "react": "DsPanelTools",
6410
+ "angular": "DsPanelTools"
6701
6411
  }
6702
6412
  },
6703
6413
  "dependencies": [
6704
6414
  "@ds-mo/ui",
6705
- "@ds-mo/tokens",
6706
- "@ds-mo/icons"
6415
+ "@ds-mo/tokens"
6707
6416
  ],
6708
6417
  "registryDependencies": [
6709
6418
  "button-unfilled",
6710
- "checkbox",
6711
- "empty-state",
6712
- "icon",
6713
- "loader",
6714
- "text",
6419
+ "panel-tool-header",
6715
6420
  "tooltip"
6716
6421
  ]
6717
6422
  },
6718
6423
  {
6719
- "name": "shell-app",
6720
- "title": "ShellApp",
6721
- "description": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
6424
+ "name": "radio",
6425
+ "title": "Radio",
6426
+ "description": "Form-associated one-of-many radio selection set with vertical or horizontal layout, three densities, per-option inactive state, and roving keyboard focus.",
6722
6427
  "type": "registry:ui",
6723
6428
  "meta": {
6724
6429
  "library": "@ds-mo/ui",
6725
6430
  "distribution": "npm",
6726
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-app",
6727
- "source": "src/wc/components/ShellApp/ShellApp.tsx",
6431
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/radio",
6432
+ "source": "src/wc/components/Radio/Radio.tsx",
6728
6433
  "intentStatus": "complete",
6729
6434
  "intent": {
6730
- "audience": "specialized",
6435
+ "audience": "general",
6731
6436
  "status": "stable",
6732
- "summary": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
6437
+ "summary": "Form-associated one-of-many radio selection set with vertical or horizontal layout, three densities, per-option inactive state, and roving keyboard focus.",
6733
6438
  "useWhen": [
6734
- "Building any standard authenticated product or workspace page with CompoMo.",
6735
- "PanelNav, BarNav, ShellTools, mobile navigation, page content, shared chrome, responsive behavior, and shell shortcuts must be composed as one application frame.",
6736
- "Future application templates need the supported base-page composition boundary."
6439
+ "A user must select exactly one visible option from a small set.",
6440
+ "All available choices should remain visible for comparison.",
6441
+ "A form needs one selected string value with native validation, reset, or external form association."
6737
6442
  ],
6738
6443
  "avoidWhen": [
6739
- "Building authentication, onboarding, public, marketing, print, error, or intentionally focused full-screen experiences that require a different layout.",
6740
- "Another ShellApp already exists in the page; applications must render exactly one and must never nest ShellApps.",
6741
- "Building content inside an existing ShellApp; render the page content rather than another shell."
6444
+ "A user may select zero or multiple independent choices.",
6445
+ "A binary setting applies immediately rather than selecting from a set.",
6446
+ "The option list is too long or space-constrained to remain visible."
6742
6447
  ],
6743
- "commonlyComposedWith": [
6744
- "component:ds-panel-nav",
6745
- "component:ds-bar-nav",
6746
- "component:ds-panel-tools",
6747
- "component:ds-shell-tools",
6748
- "component:ds-shell-mobile-nav",
6749
- "component:ds-shell-mobile-section-nav",
6750
- "component:ds-shell-mobile-bar",
6751
- "component:ds-shell-page",
6752
- "component:ds-swatch-picker"
6448
+ "alternatives": [
6449
+ {
6450
+ "when": "A user may select zero or multiple independent choices.",
6451
+ "component": "component:ds-checkbox",
6452
+ "reason": "Checkbox communicates independent selection rather than one-of-many choice."
6453
+ },
6454
+ {
6455
+ "when": "A binary setting applies immediately.",
6456
+ "component": "component:ds-switch",
6457
+ "reason": "Switch communicates an immediately applied on/off setting."
6458
+ },
6459
+ {
6460
+ "when": "The option list is long or the available space is constrained.",
6461
+ "component": "component:ds-select",
6462
+ "reason": "Select keeps a larger one-of-many choice set compact."
6463
+ }
6753
6464
  ],
6754
- "patterns": [
6755
- "pattern:application-shell",
6756
- "pattern:shell-page"
6465
+ "commonlyComposedWith": [
6466
+ "component:ds-field",
6467
+ "component:ds-text"
6757
6468
  ],
6758
6469
  "accessibility": [
6759
- "Keep primary destinations in PanelNav and secondary route sections in BarNav.",
6760
- "Ensure the default content region contains the page's single main landmark.",
6761
- "Keep PanelNav, BarNav, and PanelTools-compatible chrome available in desktop and tablet compositions and the persistent mobile bar available below 768px.",
6762
- "Do not override browser keyboard chords when enabling shell shortcuts.",
6763
- "Require Search and Help as the minimum PanelTools actions and provide accessible labels for every tool.",
6764
- "Preserve focus and accessible names across navigation, collapse, overflow, and responsive presentation changes."
6470
+ "The host exposes radiogroup semantics and requires an accessible group name from aria-label or aria-labelledby.",
6471
+ "Each visible option exposes radio semantics, its checked state, its label text, and any inactive state.",
6472
+ "Arrow keys move and select through active options; Home and End select the first and last active options; Space and Enter select the focused option.",
6473
+ "Roving tabindex keeps one active option in the tab order, preferring the selected option."
6765
6474
  ],
6766
6475
  "states": [
6767
- "Render exactly one ShellApp as the workspace root and never nest it.",
6768
- "PanelNav, BarNav, and ShellTools are the responsive shell regions; ShellTools contains at least Search and Help even when no additional product tools apply.",
6769
- "The application router owns the current route, authorization filtering, Dashboard or Settings context, destination collections, section collections, and localized content labels.",
6770
- "ShellApp propagates navStyle and resolved responsive mode and coordinates layout, gradient alignment, transitions, metrics, shortcuts, and mobile-stage visibility.",
6771
- "The application controls mobileDestination and mobileNavigationOpen and keeps router state independent from global tool-surface changes.",
6772
- "Set gradientPreset to the single resolved global chrome preference: neutral by default, none for solid chrome, or cool, neutral, warm, and fresh for token-based washes.",
6773
- "The application owns gradient preference persistence, cross-tab synchronization, and server or account precedence; ShellApp owns rendering the resolved preset across authenticated routes.",
6774
- "Dashboard represents day-to-day operational work while Settings represents administrative and configuration work; route state selects the context.",
6775
- "Update PanelNav groups, BarNav tabs and heading, navStyle, basePath, and currentUrl atomically from one resolved route state.",
6776
- "BarNav remains present: it shows route-section tabs when available and the active PanelNav destination label as heading otherwise.",
6777
- "Render one ShellPage as the default-slot child for each standard routed page; ShellApp owns the content scroller while ShellPage owns page header stickiness and content inset.",
6778
- "The application filters unauthorized destinations, sections, and tools before passing them into shell components."
6476
+ "Unchecked circles use a tertiary-foreground inset stroke: 1.25px at md, 1px at sm, and 0.75px at xs.",
6477
+ "Selected circles remove the border, use a brand fill, and draw a centered on-bold foreground dot sized 8px at md, 6px at sm, and 4px at xs.",
6478
+ "Sizes are md with a 16px circle in a 20px placement, sm with a 12px circle in a 16px placement, and xs with an 8px circle in a 12px placement.",
6479
+ "The initial value is restored by native form reset; the selected value submits under name and a required set is invalid until one active option is selected."
6779
6480
  ],
6780
6481
  "responsiveBehavior": [
6781
- "ShellApp owns the fixed system breakpoints and resolves desktop at 1200px and wider, tablet from 768px through 1199px, and mobile below 768px.",
6782
- "On desktop, PanelNav defaults expanded, permits user collapse or expansion, and respects the locally persisted desktop preference.",
6783
- "On tablet, ShellApp keeps PanelNav permanently collapsed and prevents user expansion without overwriting the desktop preference.",
6784
- "On mobile, ShellApp hides and inerts PanelNav and BarNav, uses a solid primary stage, and composes MobileNav, MobileSectionNav, ShellTools, and the persistent five-item MobileBar.",
6785
- "Mobile global surfaces conceal and inert the routed workspace without unmounting it, preserving nested routes and scroll state.",
6786
- "Keep PanelNav width, BarNav height, PanelTools chrome, and main-content origin stable except during intentional responsive or collapse transitions.",
6787
- "The bottom bar remains visible at all route and tool depths in the foundation release."
6482
+ "Choose size from the density of the containing form or settings row.",
6483
+ "Prefer vertical layout when labels may wrap or horizontal space is constrained; horizontal layout is appropriate for short labels in a small set."
6788
6484
  ],
6789
6485
  "frameworkCaveats": {
6790
6486
  "customElements": [
6791
- "Assign complex navigation and tool collections as JavaScript properties on the slotted components.",
6792
- "Stamp route-derived nav-style before components connect when deterministic first paint is required."
6487
+ "Assign options as a JavaScript property, set value as a property for application state updates, and listen for dsChange.",
6488
+ "Use the form attribute on the host when associating a radio set rendered outside its owning form."
6793
6489
  ],
6794
6490
  "react": [
6795
- "Use generated wrappers and preserve native slot names for desktop navigation, responsive tools, mobile navigation, and main content.",
6796
- "Resolve all shell inputs from one router state before rendering the composition."
6491
+ "Use DsRadio, pass options as an array, and handle onDsChange; value is mutable and updates after user selection."
6797
6492
  ],
6798
6493
  "angular": [
6799
- "Use generated standalone adapters and preserve slot attributes in templates.",
6800
- "Bind complex inputs as properties and update navigation inputs atomically from one resolved router state.",
6801
- "Bind both nav-style attributes and properties when deterministic first paint is required."
6494
+ "Use DsRadio with options and value bindings plus dsChange, or import the generated radio value accessor with the component adapter."
6802
6495
  ]
6803
6496
  },
6804
6497
  "references": [
6805
6498
  {
6806
- "label": "Component guide",
6807
- "path": "src/wc/components/ShellApp/ShellApp.mdx"
6808
- },
6809
- {
6810
- "label": "Executable Storybook composition",
6811
- "path": "src/wc/components/ShellApp/ShellApp.stories.ts"
6812
- },
6813
- {
6814
- "label": "Framework integration",
6815
- "path": "docs/framework-integration.md"
6499
+ "label": "Storybook examples",
6500
+ "path": "src/wc/components/Radio/Radio.stories.ts"
6816
6501
  },
6817
6502
  {
6818
- "label": "Application shell contract",
6819
- "path": "agent/patterns/application-shell/pattern.agent.json"
6503
+ "label": "Cross-browser form and accessibility coverage",
6504
+ "path": "tests/e2e/forms.spec.ts"
6820
6505
  }
6821
6506
  ]
6822
6507
  },
6823
6508
  "props": {
6824
- "gradientPreset": {
6825
- "type": "ShellGradientPreset",
6509
+ "ariaLabel": {
6510
+ "type": "string | null",
6826
6511
  "required": false
6827
6512
  },
6828
- "mobileDestination": {
6829
- "type": "ShellMobileDestination",
6513
+ "ariaLabelledby": {
6514
+ "type": "string | undefined",
6515
+ "required": false
6516
+ },
6517
+ "direction": {
6518
+ "type": "'vertical' | 'horizontal'",
6830
6519
  "required": false
6831
6520
  },
6832
- "mobileNavigationOpen": {
6521
+ "disabled": {
6833
6522
  "type": "boolean",
6834
6523
  "required": false
6835
6524
  },
6836
- "navStyle": {
6837
- "type": "NavChromeStyle",
6525
+ "form": {
6526
+ "type": "string | undefined",
6838
6527
  "required": false
6839
6528
  },
6840
- "shortcutsEnabled": {
6529
+ "isInactive": {
6841
6530
  "type": "boolean",
6842
6531
  "required": false
6843
- }
6844
- },
6845
- "events": [
6532
+ },
6533
+ "name": {
6534
+ "type": "string | undefined",
6535
+ "required": false
6536
+ },
6537
+ "options": {
6538
+ "type": "RadioOption[]",
6539
+ "required": false
6540
+ },
6541
+ "required": {
6542
+ "type": "boolean",
6543
+ "required": false
6544
+ },
6545
+ "requiredMessage": {
6546
+ "type": "string",
6547
+ "required": false
6548
+ },
6549
+ "size": {
6550
+ "type": "RadioSize",
6551
+ "required": false
6552
+ },
6553
+ "value": {
6554
+ "type": "string",
6555
+ "required": false
6556
+ }
6557
+ },
6558
+ "events": [
6846
6559
  {
6847
- "name": "dsResponsiveModeChange",
6848
- "detail": "{ mode: ShellResponsiveMode }"
6560
+ "name": "dsChange",
6561
+ "detail": "string"
6849
6562
  }
6850
6563
  ],
6851
6564
  "slots": [],
6852
6565
  "exports": {
6853
- "customElement": "ds-shell-app",
6854
- "react": "DsShellApp",
6855
- "angular": "DsShellApp"
6566
+ "customElement": "ds-radio",
6567
+ "react": "DsRadio",
6568
+ "angular": "DsRadio"
6856
6569
  }
6857
6570
  },
6858
6571
  "dependencies": [
6859
6572
  "@ds-mo/ui",
6860
6573
  "@ds-mo/tokens"
6861
6574
  ],
6862
- "registryDependencies": []
6575
+ "registryDependencies": [
6576
+ "text"
6577
+ ]
6863
6578
  },
6864
6579
  {
6865
- "name": "shell-gradient-picker",
6866
- "title": "ShellGradientPicker",
6867
- "description": "Deprecated compatibility wrapper that maps the fixed ShellApp wash presets into SwatchPicker.",
6580
+ "name": "scroll-overlay",
6581
+ "title": "ScrollOverlay",
6582
+ "description": "Generic scroll owner for content that moves behind a persistent footer action or composer with an always-active alpha fade.",
6868
6583
  "type": "registry:ui",
6869
6584
  "meta": {
6870
6585
  "library": "@ds-mo/ui",
6871
6586
  "distribution": "npm",
6872
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-gradient-picker",
6873
- "source": "src/wc/components/ShellGradientPicker/ShellGradientPicker.tsx",
6587
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/scroll-overlay",
6588
+ "source": "src/wc/components/ScrollOverlay/ScrollOverlay.tsx",
6874
6589
  "intentStatus": "complete",
6875
6590
  "intent": {
6876
- "audience": "specialized",
6877
- "status": "deprecated",
6878
- "replacedBy": "component:ds-swatch-picker",
6879
- "replacementReason": "SwatchPicker now owns the same accessible interaction with a generic option model that supports both flat colors and gradients.",
6880
- "summary": "Deprecated compatibility wrapper that maps the fixed ShellApp wash presets into SwatchPicker.",
6591
+ "audience": "general",
6592
+ "status": "experimental",
6593
+ "summary": "Generic scroll owner for content that moves behind a persistent footer action or composer with an always-active alpha fade.",
6881
6594
  "useWhen": [
6882
- "Adding the Appearance or Theme section to the application's user or account menu.",
6883
- "Users must choose the global ShellApp chrome treatment from none, cool, neutral, warm, or fresh."
6595
+ "A bounded region owns scrolling while footer actions remain overlaid and continuously visible.",
6596
+ "The final content must clear a live-height footer while earlier content can move behind it."
6884
6597
  ],
6885
6598
  "avoidWhen": [
6886
- "Choosing semantic intent, page background, chart, content, or brand colors.",
6887
- "Building an arbitrary gradient editor or allowing custom gradient values.",
6888
- "A picker already exists for the application; provide exactly one canonical preference location.",
6889
- "Rendering an individual swatch outside the complete picker."
6890
- ],
6891
- "alternatives": [
6892
- {
6893
- "when": "The user is selecting the application light, dark, or system color mode.",
6894
- "component": "component:ds-menu",
6895
- "reason": "Color mode is a separate appearance preference and should use ordinary menu selection rows."
6896
- }
6599
+ "The footer belongs in normal document flow rather than overlaying content.",
6600
+ "Another component already owns scrolling and cannot delegate its scrollport to this component."
6897
6601
  ],
6898
6602
  "commonlyComposedWith": [
6899
- "component:ds-shell-app",
6900
- "component:ds-menu"
6901
- ],
6902
- "patterns": [
6903
- "pattern:application-shell"
6603
+ "component:ds-button-filled",
6604
+ "component:ds-message-composer"
6904
6605
  ],
6905
6606
  "accessibility": [
6906
- "Provide a localized groupLabel that describes the shell appearance choice.",
6907
- "Treat the presets as one radio group with one Tab stop; Arrow keys, Home, and End move and select within the group.",
6908
- "Keep the visible compact swatches and their accessible preset names; do not rely on color alone for assistive technology."
6607
+ "Provide scrollLabel when the scrollport needs its own named, keyboard-focusable region.",
6608
+ "Keep footer actions keyboard accessible and explicitly named; the fade is decorative and never intercepts pointer input."
6909
6609
  ],
6910
6610
  "states": [
6911
- "Neutral is the default preset; none renders solid shell chrome without a wash.",
6912
- "Cool, neutral, warm, and fresh use design tokens and automatically adapt to the active light or dark color theme.",
6913
- "Apply dsChange immediately to ShellApp.gradientPreset and keep the containing account menu open.",
6914
- "The application owns local persistence, cross-tab synchronization, and server or account preference precedence; the picker owns only selection UI and events.",
6915
- "Treat the fixed preset union as the only supported values and do not construct custom gradients."
6611
+ "The alpha mask remains active at every scroll position and moves in content coordinates so it stays pinned behind the footer without masking native scrollbars.",
6612
+ "The component measures the complete overlay for end clearance, measures its visible child for fade depth, and begins the fade 8px before that visible content.",
6613
+ "An md 32px footer action with 8px bottom inset therefore produces a 48px fade; variable-height composers produce a correspondingly taller measured fade."
6916
6614
  ],
6917
6615
  "responsiveBehavior": [
6918
- "Keep the compact picker in the user or account appearance menu on supported desktop and tablet shell compositions.",
6919
- "The future mobile account surface may present the same preference differently."
6616
+ "The scrollport and overlay fill the available width and height; the owner supplies responsive sizing and overlay insets."
6920
6617
  ],
6921
6618
  "frameworkCaveats": {
6922
6619
  "customElements": [
6923
- "Listen for dsChange, resolve application preference precedence, and assign the result to the single ShellApp gradientPreset property."
6620
+ "Place scrollable content in the default slot and one footer wrapper in the overlay slot; use dsScroll only when the application needs position data."
6924
6621
  ],
6925
6622
  "react": [
6926
- "Use the generated wrapper and handle onDsChange without closing the containing account menu."
6623
+ "Use DsScrollOverlay with ordinary children plus an element carrying slot=\"overlay\"."
6927
6624
  ],
6928
6625
  "angular": [
6929
- "Bind value to the resolved preference and handle dsChange to update application state."
6626
+ "Import DsScrollOverlay and project the persistent footer wrapper with slot=\"overlay\"."
6930
6627
  ]
6931
6628
  },
6932
6629
  "references": [
6933
6630
  {
6934
- "label": "Replacement stories",
6935
- "path": "src/wc/components/SwatchPicker/SwatchPicker.stories.ts"
6936
- },
6937
- {
6938
- "label": "ShellApp gradient contract",
6939
- "path": "src/wc/components/ShellApp/ShellApp.mdx"
6940
- },
6941
- {
6942
- "label": "Application shell composition",
6943
- "path": "agent/patterns/application-shell/pattern.agent.json"
6631
+ "label": "Storybook examples",
6632
+ "path": "src/wc/components/ScrollOverlay/ScrollOverlay.stories.ts"
6944
6633
  }
6945
6634
  ]
6946
6635
  },
6947
6636
  "props": {
6948
- "groupLabel": {
6949
- "type": "string",
6950
- "required": false
6951
- },
6952
- "value": {
6953
- "type": "ShellGradientPreset",
6637
+ "scrollLabel": {
6638
+ "type": "string | undefined",
6954
6639
  "required": false
6955
6640
  }
6956
6641
  },
6957
6642
  "events": [
6958
6643
  {
6959
- "name": "dsChange",
6960
- "detail": "ShellGradientPreset"
6644
+ "name": "dsScroll",
6645
+ "detail": "ScrollOverlayScrollDetail"
6961
6646
  }
6962
6647
  ],
6963
6648
  "slots": [],
6964
6649
  "exports": {
6965
- "customElement": "ds-shell-gradient-picker",
6966
- "react": "DsShellGradientPicker",
6967
- "angular": "DsShellGradientPicker"
6650
+ "customElement": "ds-scroll-overlay",
6651
+ "react": "DsScrollOverlay",
6652
+ "angular": "DsScrollOverlay"
6968
6653
  }
6969
6654
  },
6970
6655
  "dependencies": [
6971
6656
  "@ds-mo/ui",
6972
6657
  "@ds-mo/tokens"
6973
6658
  ],
6974
- "registryDependencies": [
6975
- "swatch-picker"
6976
- ]
6659
+ "registryDependencies": []
6977
6660
  },
6978
6661
  {
6979
- "name": "shell-gradient-swatch",
6980
- "title": "ShellGradientSwatch",
6981
- "description": "Deprecated internal compatibility component for one legacy ShellApp gradient swatch.",
6662
+ "name": "select",
6663
+ "title": "Select",
6664
+ "description": "Form-associated single-value select with listbox semantics, local search, rich flat options, grouped sections, loading, clearing, and surface-aware trigger chrome.",
6982
6665
  "type": "registry:ui",
6983
6666
  "meta": {
6984
6667
  "library": "@ds-mo/ui",
6985
6668
  "distribution": "npm",
6986
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-gradient-swatch",
6987
- "source": "src/wc/components/ShellGradientSwatch/ShellGradientSwatch.tsx",
6669
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/select",
6670
+ "source": "src/wc/components/Select/Select.tsx",
6988
6671
  "intentStatus": "complete",
6989
6672
  "intent": {
6990
- "audience": "internal",
6991
- "status": "deprecated",
6992
- "replacedBy": "component:ds-swatch-picker",
6993
- "replacementReason": "SwatchPicker renders its option buttons internally so an individually published radio swatch is no longer needed.",
6994
- "summary": "Deprecated internal compatibility component for one legacy ShellApp gradient swatch.",
6673
+ "audience": "general",
6674
+ "status": "stable",
6675
+ "summary": "Form-associated single-value select with listbox semantics, local search, rich flat options, grouped sections, loading, clearing, and surface-aware trigger chrome.",
6995
6676
  "useWhen": [
6996
- "Maintaining or extending ShellGradientPicker inside CompoMo."
6677
+ "The user must choose one value from a finite set.",
6678
+ "The option set benefits from local search, subtext, prefix icons, grouping, or disabled choices.",
6679
+ "The choice set has more than roughly 20 options, comes from a user-managed listing, or represents a large domain such as addresses where search materially improves retrieval.",
6680
+ "The selected value must participate in native, Angular, or React form state."
6997
6681
  ],
6998
6682
  "avoidWhen": [
6999
- "Building application UI directly; use ShellGradientPicker instead.",
7000
- "Selecting semantic, brand, chart, page, or arbitrary gradient colors.",
7001
- "Creating a partial or custom set of shell gradient choices."
6683
+ "Several values may be selected at once.",
6684
+ "The rows perform commands rather than choosing a form value.",
6685
+ "The choices form a hierarchy with expandable parents."
7002
6686
  ],
7003
6687
  "alternatives": [
7004
6688
  {
7005
- "when": "An application needs the supported global shell appearance control.",
7006
- "component": "component:ds-swatch-picker",
7007
- "reason": "SwatchPicker provides the complete radio-group semantics, keyboard behavior, generic previews, and selection event."
6689
+ "when": "Several independent values may be selected.",
6690
+ "component": "component:ds-select-multi",
6691
+ "reason": "SelectMulti owns array values, multi-selection semantics, and count presentation."
6692
+ },
6693
+ {
6694
+ "when": "The popup contains commands or state-changing actions.",
6695
+ "component": "component:ds-menu",
6696
+ "reason": "Menu uses action-menu roles and command-focused keyboard behavior."
6697
+ },
6698
+ {
6699
+ "when": "A small set of choices should remain visible.",
6700
+ "component": "component:ds-radio",
6701
+ "reason": "Prefer Radio for roughly two to five mutually exclusive choices when the available space allows all choices to remain visible."
7008
6702
  }
7009
6703
  ],
7010
6704
  "commonlyComposedWith": [
7011
- "component:ds-swatch-picker"
6705
+ "component:ds-text",
6706
+ "component:ds-icon",
6707
+ "component:ds-empty-state",
6708
+ "component:ds-loader"
7012
6709
  ],
7013
6710
  "accessibility": [
7014
- "Keep radio semantics, aria-checked state, and a preset-specific accessible name on the internal button.",
7015
- "Let ShellGradientPicker manage the roving tab stop and group keyboard navigation.",
7016
- "Do not expose an unlabeled color-only choice."
6711
+ "In forms, provide a persistent visible external field label; placeholder text is guidance and must not be the field's only label. In a compact filter bar, the trigger's visible text may supply the accessible name.",
6712
+ "The trigger uses combobox semantics and the popup uses listbox and option semantics; do not replace them with menu roles.",
6713
+ "Disabled options remain visible, expose aria-disabled, and are skipped by keyboard navigation and typeahead.",
6714
+ "Keyboard navigation keeps the aria-activedescendant option scrolled into the visible listbox viewport.",
6715
+ "Selected options rely on active fill and foreground treatment without a redundant trailing check icon.",
6716
+ "Local search moves focus into the search field while preserving the active option through aria-activedescendant.",
6717
+ "Use errorMessage with error so the trigger is described by the rendered alert."
7017
6718
  ],
7018
6719
  "states": [
7019
- "Preset determines the token-based preview; selected determines radio state and selected visuals.",
7020
- "The selected swatch owns the radio group's single tab stop while ShellGradientPicker coordinates selection and focus movement.",
7021
- "isInactive disables interaction but does not remove the accessible name."
6720
+ "Value is controlled through the mutable value property; dsChange reports user selection and clearing.",
6721
+ "Required Selects begin without an automatic selection and require the user to make an explicit choice; do not preselect the first option merely to satisfy validity.",
6722
+ "When allowClear is enabled, the clear affordance appears only after a value exists. Clearing is valid for optional and required fields; a required field becomes invalid until the user selects again.",
6723
+ "Clearing emits dsChange with an empty string and dsClear, keeps the popup open, and restores useful focus.",
6724
+ "Loading keeps the trigger visible, replaces its prefix icon, marks the control busy, and makes selection interaction temporarily unavailable without presenting the control as inactive.",
6725
+ "The trigger label stays left-aligned at every width. The default size is md in both forms and filter bars; smaller sizes require an explicit density need.",
6726
+ "Use option icons only when they help users differentiate choices. Icons render only when every option in the complete list provides one; mixed icon data falls back to the text-only row layout.",
6727
+ "Create sections only for categories that are meaningful to customers, not merely to break a long list into arbitrary chunks.",
6728
+ "When any option supplies subtext, every row uses the same subtext structure and missing values render an em dash. Subtext should disambiguate or add decision-helpful information.",
6729
+ "Option labels and the selected trigger label stay on one line and truncate when constrained. Option subtext may wrap to at most two lines.",
6730
+ "The optional prefix icon and chevron always use the parent surface's secondary foreground color, including when a selected value promotes the label to primary.",
6731
+ "The shared popup search control stays md at every trigger size, using body-medium text, a 20px icon, and the same internal spacing as a borderless Select trigger. Its container uses menu-item padding on every side and owns a 1px bottom divider that becomes a 1.5px bold-brand stroke while search has focus. Search placeholder text is secondary at rest and quaternary while focused because it becomes decorative once the editable field is active.",
6732
+ "When search contains text, the shared control shows a rounded sm icon-only ButtonUnfilled with the CrossCircle icon and no border. It clears the local term, stays hidden for an empty term, and returns focus to search.",
6733
+ "The shared clear footer mirrors the search region's sizing: menu-item padding surrounds an md-height borderless row, and the Clear label uses the same row and label insets as option text. The outer footer owns a 1px top divider.",
6734
+ "An empty filtered list composes the message-only body variant of EmptyState. Keep the default neutral no-results message unless localized product guidance makes the outcome clearer.",
6735
+ "Enable searchable for more than roughly 20 options, user-managed listings, large domains such as addresses, or sets users cannot efficiently scan. Local matching includes option labels, subtext, and section headings; the owner resolves remote data before assigning options.",
6736
+ "Validation timing belongs to the form owner and may be immediate or deferred until blur or submit; the Select exposes validity and error presentation without imposing that policy.",
6737
+ "The error trigger uses a 1.5px bold-negative inset stroke so invalid state remains distinguishable from the normal 1px border without changing control geometry.",
6738
+ "An initially empty option set is not an expected Select use case. The no-results state describes a search with no matches, not a source with no choices.",
6739
+ "Use options for a flat list or sections for grouped choices; when sections are present they take precedence.",
6740
+ "The background prop describes the actual parent surface and uses the same surface set as ButtonUnfilled."
7022
6741
  ],
7023
6742
  "responsiveBehavior": [
7024
- "Preserve the fixed compact swatch geometry and let ShellGradientPicker own layout."
6743
+ "Use width fill for form fields and width hug for compact filter bars. Override those defaults only when the owning layout has a clear constraint.",
6744
+ "The popup matches the trigger minimum width, may grow for content, and clamps to the viewport.",
6745
+ "Long option collections scroll inside the popup; virtualization and remote search are not part of this component."
7025
6746
  ],
7026
6747
  "frameworkCaveats": {
7027
6748
  "customElements": [
7028
- "Do not instantiate this internal primitive in consuming applications."
6749
+ "Assign options and sections through JavaScript properties because arrays and objects cannot be represented safely as attributes."
7029
6750
  ],
7030
6751
  "react": [
7031
- "Use DsShellGradientPicker rather than the generated swatch wrapper."
6752
+ "Pass options or sections as wrapper props and handle onDsChange, onDsClear, and onDsOpenChange."
7032
6753
  ],
7033
6754
  "angular": [
7034
- "Use DsShellGradientPicker rather than importing DsShellGradientSwatch."
6755
+ "Import DsSelect and SelectValueAccessor when integrating with Angular Forms; bind options and sections as properties."
7035
6756
  ]
7036
6757
  },
7037
6758
  "references": [
7038
6759
  {
7039
- "label": "Parent picker",
7040
- "path": "src/wc/components/ShellGradientPicker/ShellGradientPicker.tsx"
6760
+ "label": "Storybook examples",
6761
+ "path": "src/wc/components/Select/Select.stories.ts"
6762
+ },
6763
+ {
6764
+ "label": "Selection patterns",
6765
+ "path": "src/docs/SelectionPatterns.mdx"
7041
6766
  }
7042
6767
  ]
7043
6768
  },
7044
6769
  "props": {
7045
- "ariaLabel": {
7046
- "type": "string | null",
6770
+ "activeFill": {
6771
+ "type": "boolean",
7047
6772
  "required": false
7048
6773
  },
7049
- "isInactive": {
6774
+ "allowClear": {
7050
6775
  "type": "boolean",
7051
6776
  "required": false
7052
6777
  },
7053
- "preset": {
7054
- "type": "ShellGradientPreset",
6778
+ "ariaDescribedby": {
6779
+ "type": "string | undefined",
7055
6780
  "required": false
7056
6781
  },
7057
- "selected": {
7058
- "type": "boolean",
6782
+ "ariaLabel": {
6783
+ "type": "string | null",
7059
6784
  "required": false
7060
- }
6785
+ },
6786
+ "ariaLabelledby": {
6787
+ "type": "string | undefined",
6788
+ "required": false
6789
+ },
6790
+ "background": {
6791
+ "type": "SelectBackground | undefined",
6792
+ "required": false
6793
+ },
6794
+ "clearLabel": {
6795
+ "type": "string",
6796
+ "required": false
6797
+ },
6798
+ "disabled": {
6799
+ "type": "boolean",
6800
+ "required": false
6801
+ },
6802
+ "error": {
6803
+ "type": "boolean",
6804
+ "required": false
6805
+ },
6806
+ "errorMessage": {
6807
+ "type": "string | undefined",
6808
+ "required": false
6809
+ },
6810
+ "hasBorder": {
6811
+ "type": "boolean",
6812
+ "required": false
6813
+ },
6814
+ "icon": {
6815
+ "type": "string | undefined",
6816
+ "required": false
6817
+ },
6818
+ "inputId": {
6819
+ "type": "string | undefined",
6820
+ "required": false
6821
+ },
6822
+ "isInactive": {
6823
+ "type": "boolean",
6824
+ "required": false
6825
+ },
6826
+ "isLoading": {
6827
+ "type": "boolean",
6828
+ "required": false
6829
+ },
6830
+ "loadingLabel": {
6831
+ "type": "string",
6832
+ "required": false
6833
+ },
6834
+ "name": {
6835
+ "type": "string | undefined",
6836
+ "required": false
6837
+ },
6838
+ "noResultsText": {
6839
+ "type": "string",
6840
+ "required": false
6841
+ },
6842
+ "open": {
6843
+ "type": "boolean",
6844
+ "required": false
6845
+ },
6846
+ "options": {
6847
+ "type": "SelectOption[]",
6848
+ "required": false
6849
+ },
6850
+ "placeholder": {
6851
+ "type": "string",
6852
+ "required": false
6853
+ },
6854
+ "required": {
6855
+ "type": "boolean",
6856
+ "required": false
6857
+ },
6858
+ "requiredMessage": {
6859
+ "type": "string",
6860
+ "required": false
6861
+ },
6862
+ "searchPlaceholder": {
6863
+ "type": "string",
6864
+ "required": false
6865
+ },
6866
+ "searchable": {
6867
+ "type": "boolean",
6868
+ "required": false
6869
+ },
6870
+ "sections": {
6871
+ "type": "SelectSection[]",
6872
+ "required": false
6873
+ },
6874
+ "size": {
6875
+ "type": "SelectSize",
6876
+ "required": false
6877
+ },
6878
+ "value": {
6879
+ "type": "string",
6880
+ "required": false
6881
+ },
6882
+ "width": {
6883
+ "type": "SelectWidth",
6884
+ "required": false
6885
+ }
7061
6886
  },
7062
6887
  "events": [
7063
6888
  {
7064
- "name": "dsSelect",
7065
- "detail": "ShellGradientPreset"
6889
+ "name": "dsChange",
6890
+ "detail": "string"
6891
+ },
6892
+ {
6893
+ "name": "dsClear",
6894
+ "detail": "void"
6895
+ },
6896
+ {
6897
+ "name": "dsOpenChange",
6898
+ "detail": "boolean"
7066
6899
  }
7067
6900
  ],
7068
6901
  "slots": [],
7069
6902
  "exports": {
7070
- "customElement": "ds-shell-gradient-swatch",
7071
- "react": "DsShellGradientSwatch",
7072
- "angular": "DsShellGradientSwatch"
6903
+ "customElement": "ds-select",
6904
+ "react": "DsSelect",
6905
+ "angular": "DsSelect"
7073
6906
  }
7074
6907
  },
7075
6908
  "dependencies": [
7076
6909
  "@ds-mo/ui",
7077
- "@ds-mo/tokens"
6910
+ "@ds-mo/tokens",
6911
+ "@ds-mo/icons"
7078
6912
  ],
7079
- "registryDependencies": []
6913
+ "registryDependencies": [
6914
+ "button-unfilled",
6915
+ "empty-state",
6916
+ "icon",
6917
+ "loader",
6918
+ "text",
6919
+ "tooltip"
6920
+ ]
7080
6921
  },
7081
6922
  {
7082
- "name": "shell-mobile-bar",
7083
- "title": "ShellMobileBar",
7084
- "description": "Persistent mobile shell navigation for Menu, the router-derived current area, Search, Agents, and Inbox.",
6923
+ "name": "select-multi",
6924
+ "title": "SelectMulti",
6925
+ "description": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
7085
6926
  "type": "registry:ui",
7086
6927
  "meta": {
7087
6928
  "library": "@ds-mo/ui",
7088
6929
  "distribution": "npm",
7089
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-mobile-bar",
7090
- "source": "src/wc/components/ShellMobileBar/ShellMobileBar.tsx",
6930
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/select-multi",
6931
+ "source": "src/wc/components/SelectMulti/SelectMulti.tsx",
7091
6932
  "intentStatus": "complete",
7092
6933
  "intent": {
7093
- "audience": "specialized",
7094
- "status": "experimental",
7095
- "summary": "Persistent mobile shell navigation for Menu, the router-derived current area, Search, Agents, and Inbox.",
6934
+ "audience": "general",
6935
+ "status": "stable",
6936
+ "summary": "Form-associated multi-value select with a persistent trigger label, inline selected count, local search, rich flat options, grouped sections, loading, and clear-all behavior.",
7096
6937
  "useWhen": [
7097
- "ShellApp is rendering its dedicated below-768px application composition."
6938
+ "The user may choose several independent values from one finite set.",
6939
+ "A compact trigger should summarize selection with the field label and a count.",
6940
+ "The option set benefits from local search, subtext, grouping, or disabled choices.",
6941
+ "The choice set has more than roughly 20 options, comes from a user-managed listing, or represents a large domain where search materially improves retrieval."
7098
6942
  ],
7099
6943
  "avoidWhen": [
7100
- "Rendering desktop or tablet shell chrome.",
7101
- "An arbitrary set of product tabs is required."
6944
+ "Exactly one value may be selected.",
6945
+ "Selected values must remain individually removable as persistent tags outside the popup.",
6946
+ "The choices form a hierarchy with cascading parent selection.",
6947
+ "The customer task benefits more from keeping every choice and checkbox directly visible; choose between SelectMulti and a visible checkbox list from the use-case context rather than a fixed option-count threshold."
7102
6948
  ],
7103
- "commonlyComposedWith": [
7104
- "component:ds-shell-app"
6949
+ "alternatives": [
6950
+ {
6951
+ "when": "Exactly one value may be selected.",
6952
+ "component": "component:ds-select",
6953
+ "reason": "Select owns scalar form value and single-select listbox behavior."
6954
+ },
6955
+ {
6956
+ "when": "The popup contains actions rather than values.",
6957
+ "component": "component:ds-menu",
6958
+ "reason": "Menu uses command semantics and closes according to action-menu expectations."
6959
+ }
7105
6960
  ],
7106
- "patterns": [
7107
- "pattern:application-shell"
6961
+ "commonlyComposedWith": [
6962
+ "component:ds-text",
6963
+ "component:ds-checkbox",
6964
+ "component:ds-empty-state",
6965
+ "component:ds-loader"
7108
6966
  ],
7109
6967
  "accessibility": [
7110
- "Every item keeps a visible label and accessible name.",
7111
- "Only the active destination exposes aria-current; Menu exposes its controlled pane through aria-expanded."
6968
+ "In forms, provide a persistent visible external field label. In a compact filter bar, the trigger's visible persistent label and count may supply the accessible name.",
6969
+ "The popup is a listbox with aria-multiselectable and every option exposes its independent aria-selected state.",
6970
+ "Disabled options expose aria-disabled and are skipped by keyboard navigation and typeahead.",
6971
+ "Keyboard navigation keeps the aria-activedescendant option scrolled into the visible listbox viewport.",
6972
+ "Each row uses a medium-size presentation-only ds-checkbox indicator; multi-select option rows never add a prefix icon alongside it, and the option remains the sole selection semantic and interaction target.",
6973
+ "The trigger keeps its field label visible and appends the current selected count; an explicit aria-label or aria-labelledby remains the authoritative accessible name when supplied.",
6974
+ "Use errorMessage with error so the trigger is described by the rendered alert."
7112
6975
  ],
7113
6976
  "states": [
7114
- "The item order is fixed: Menu, current area, Search, Agents, Inbox.",
7115
- "Reselecting an active destination does not reset its nested state."
6977
+ "Values is a controlled JavaScript array; dsChange emits a new array after each user toggle.",
6978
+ "Required SelectMulti controls begin without an automatic selection and require the user to make an explicit choice.",
6979
+ "Selecting an option keeps the popup open so additional values can be toggled.",
6980
+ "The trigger label stays left-aligned at every width; every option row uses the same leading medium Checkbox indicator. The default control size is md in both forms and filter bars.",
6981
+ "The selected count always follows the persistent label as plain text separated by a centered dot, including for one selection, and counts every selected value even when search or grouping hides it. Never replace the count with selected option names.",
6982
+ "Create sections only for categories that are meaningful to customers, not merely to break a long list into arbitrary chunks.",
6983
+ "When any option supplies subtext, every row uses the same subtext structure and missing values render an em dash. Subtext should disambiguate or add decision-helpful information.",
6984
+ "Option labels stay on one line and truncate when constrained. Option subtext may wrap to at most two lines.",
6985
+ "The optional prefix icon and chevron always use the parent surface's secondary foreground color, including when selection promotes the label and count to primary.",
6986
+ "The shared popup search control stays md at every trigger size, using body-medium text, a 20px icon, and the same internal spacing as a borderless Select trigger. Its container uses menu-item padding on every side and owns a 1px bottom divider that becomes a 1.5px bold-brand stroke while search has focus. Search placeholder text is secondary at rest and quaternary while focused because it becomes decorative once the editable field is active.",
6987
+ "When search contains text, the shared control shows a rounded sm icon-only ButtonUnfilled with the Cross icon and no border. It clears the local term, stays hidden for an empty term, and returns focus to search.",
6988
+ "The shared summary-and-clear footer mirrors the search region's sizing: menu-item padding surrounds an md-height borderless row, and both texts use the same row and label insets as option text. The outer footer owns a 1px top divider.",
6989
+ "An empty filtered list composes the message-only body variant of EmptyState. Keep the default neutral no-results message unless localized product guidance makes the outcome clearer.",
6990
+ "Enable searchable for more than roughly 20 options, user-managed listings, large domains such as addresses, or sets users cannot efficiently scan. Local matching includes option labels, subtext, and section headings; the owner resolves remote data before assigning options.",
6991
+ "When allowClear is enabled, clear-all appears only after at least one value exists. Clearing is valid for optional and required fields; a required field becomes invalid until the user selects again.",
6992
+ "Clear-all emits an empty dsChange and dsClear while preserving useful popup or search focus.",
6993
+ "Loading keeps the trigger visible, marks the control busy, and makes selection interaction temporarily unavailable without presenting the control as inactive.",
6994
+ "SelectMulti has no maximum-selection behavior; every available non-inactive option may be selected.",
6995
+ "Validation timing belongs to the form owner and may be immediate or deferred until blur or submit; the component exposes validity and error presentation without imposing that policy.",
6996
+ "The error trigger uses a 1.5px bold-negative inset stroke so invalid state remains distinguishable from the normal 1px border without changing control geometry.",
6997
+ "An initially empty option set is not an expected SelectMulti use case. The no-results state describes a search with no matches, not a source with no choices.",
6998
+ "Native form submission emits one entry per selected value under the component name.",
6999
+ "Use options for a flat list or sections for grouped choices. Multi-select option contracts intentionally exclude icons because the leading checkbox owns that row zone; hierarchical parent selection is deferred."
7116
7000
  ],
7117
7001
  "responsiveBehavior": [
7118
- "Render only below the mobile breakpoint and preserve safe-area clearance."
7002
+ "Use width fill for form fields and width hug for compact filter bars; the persistent trigger label avoids variable-width selected labels.",
7003
+ "The popup matches the trigger minimum width, may grow for content, and clamps to the viewport.",
7004
+ "Long option collections scroll inside the popup; virtualization and remote search are not part of this version."
7119
7005
  ],
7006
+ "frameworkCaveats": {
7007
+ "customElements": [
7008
+ "Assign values, options, and sections through JavaScript properties; array values cannot be represented safely as attributes."
7009
+ ],
7010
+ "react": [
7011
+ "Pass values, options, and sections as wrapper props and handle onDsChange, onDsClear, and onDsOpenChange."
7012
+ ],
7013
+ "angular": [
7014
+ "Import DsSelectMulti and SelectMultiValueAccessor when integrating with Angular Forms."
7015
+ ]
7016
+ },
7120
7017
  "references": [
7121
7018
  {
7122
- "label": "Storybook",
7123
- "path": "src/wc/components/ShellMobileBar/ShellMobileBar.stories.ts"
7019
+ "label": "Storybook examples",
7020
+ "path": "src/wc/components/SelectMulti/SelectMulti.stories.ts"
7021
+ },
7022
+ {
7023
+ "label": "Selection patterns",
7024
+ "path": "src/docs/SelectionPatterns.mdx"
7124
7025
  }
7125
7026
  ]
7126
7027
  },
7127
7028
  "props": {
7128
- "activeDestination": {
7129
- "type": "ShellMobileDestination",
7029
+ "activeFill": {
7030
+ "type": "boolean",
7130
7031
  "required": false
7131
7032
  },
7132
- "agentsDot": {
7033
+ "allowClear": {
7133
7034
  "type": "boolean",
7134
7035
  "required": false
7135
7036
  },
7136
- "agentsLabel": {
7037
+ "ariaDescribedby": {
7038
+ "type": "string | undefined",
7039
+ "required": false
7040
+ },
7041
+ "ariaLabel": {
7042
+ "type": "string | null",
7043
+ "required": false
7044
+ },
7045
+ "ariaLabelledby": {
7046
+ "type": "string | undefined",
7047
+ "required": false
7048
+ },
7049
+ "background": {
7050
+ "type": "SelectMultiBackground | undefined",
7051
+ "required": false
7052
+ },
7053
+ "clearLabel": {
7054
+ "type": "string",
7055
+ "required": false
7056
+ },
7057
+ "disabled": {
7058
+ "type": "boolean",
7059
+ "required": false
7060
+ },
7061
+ "error": {
7062
+ "type": "boolean",
7063
+ "required": false
7064
+ },
7065
+ "errorMessage": {
7066
+ "type": "string | undefined",
7067
+ "required": false
7068
+ },
7069
+ "hasBorder": {
7070
+ "type": "boolean",
7071
+ "required": false
7072
+ },
7073
+ "icon": {
7074
+ "type": "string | undefined",
7075
+ "required": false
7076
+ },
7077
+ "inputId": {
7078
+ "type": "string | undefined",
7079
+ "required": false
7080
+ },
7081
+ "isInactive": {
7082
+ "type": "boolean",
7083
+ "required": false
7084
+ },
7085
+ "isLoading": {
7086
+ "type": "boolean",
7087
+ "required": false
7088
+ },
7089
+ "loadingLabel": {
7090
+ "type": "string",
7091
+ "required": false
7092
+ },
7093
+ "name": {
7094
+ "type": "string | undefined",
7095
+ "required": false
7096
+ },
7097
+ "noResultsText": {
7098
+ "type": "string",
7099
+ "required": false
7100
+ },
7101
+ "open": {
7102
+ "type": "boolean",
7103
+ "required": false
7104
+ },
7105
+ "options": {
7106
+ "type": "SelectMultiOption[]",
7107
+ "required": false
7108
+ },
7109
+ "placeholder": {
7110
+ "type": "string",
7111
+ "required": false
7112
+ },
7113
+ "required": {
7114
+ "type": "boolean",
7115
+ "required": false
7116
+ },
7117
+ "requiredMessage": {
7118
+ "type": "string",
7119
+ "required": false
7120
+ },
7121
+ "searchPlaceholder": {
7122
+ "type": "string",
7123
+ "required": false
7124
+ },
7125
+ "searchable": {
7126
+ "type": "boolean",
7127
+ "required": false
7128
+ },
7129
+ "sections": {
7130
+ "type": "SelectMultiSection[]",
7131
+ "required": false
7132
+ },
7133
+ "selectedLabel": {
7137
7134
  "type": "string",
7138
7135
  "required": false
7139
7136
  },
7140
- "currentArea": {
7141
- "type": "PanelNavItem",
7137
+ "size": {
7138
+ "type": "SelectMultiSize",
7139
+ "required": false
7140
+ },
7141
+ "values": {
7142
+ "type": "string[]",
7143
+ "required": false
7144
+ },
7145
+ "width": {
7146
+ "type": "SelectMultiWidth",
7147
+ "required": false
7148
+ }
7149
+ },
7150
+ "events": [
7151
+ {
7152
+ "name": "dsChange",
7153
+ "detail": "string[]"
7154
+ },
7155
+ {
7156
+ "name": "dsClear",
7157
+ "detail": "void"
7158
+ },
7159
+ {
7160
+ "name": "dsOpenChange",
7161
+ "detail": "boolean"
7162
+ }
7163
+ ],
7164
+ "slots": [],
7165
+ "exports": {
7166
+ "customElement": "ds-select-multi",
7167
+ "react": "DsSelectMulti",
7168
+ "angular": "DsSelectMulti"
7169
+ }
7170
+ },
7171
+ "dependencies": [
7172
+ "@ds-mo/ui",
7173
+ "@ds-mo/tokens",
7174
+ "@ds-mo/icons"
7175
+ ],
7176
+ "registryDependencies": [
7177
+ "button-unfilled",
7178
+ "checkbox",
7179
+ "empty-state",
7180
+ "icon",
7181
+ "loader",
7182
+ "text",
7183
+ "tooltip"
7184
+ ]
7185
+ },
7186
+ {
7187
+ "name": "shell-app",
7188
+ "title": "ShellApp",
7189
+ "description": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
7190
+ "type": "registry:ui",
7191
+ "meta": {
7192
+ "library": "@ds-mo/ui",
7193
+ "distribution": "npm",
7194
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-app",
7195
+ "source": "src/wc/components/ShellApp/ShellApp.tsx",
7196
+ "intentStatus": "complete",
7197
+ "intent": {
7198
+ "audience": "specialized",
7199
+ "status": "stable",
7200
+ "summary": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
7201
+ "useWhen": [
7202
+ "Building any standard authenticated product or workspace page with CompoMo.",
7203
+ "PanelNav, BarNav, ShellTools, mobile navigation, page content, shared chrome, responsive behavior, and shell shortcuts must be composed as one application frame.",
7204
+ "Future application templates need the supported base-page composition boundary."
7205
+ ],
7206
+ "avoidWhen": [
7207
+ "Building authentication, onboarding, public, marketing, print, error, or intentionally focused full-screen experiences that require a different layout.",
7208
+ "Another ShellApp already exists in the page; applications must render exactly one and must never nest ShellApps.",
7209
+ "Building content inside an existing ShellApp; render the page content rather than another shell."
7210
+ ],
7211
+ "commonlyComposedWith": [
7212
+ "component:ds-panel-nav",
7213
+ "component:ds-bar-nav",
7214
+ "component:ds-panel-tools",
7215
+ "component:ds-shell-tools",
7216
+ "component:ds-mobile-sheet-nav",
7217
+ "component:ds-mobile-header",
7218
+ "component:ds-mobile-bar-nav",
7219
+ "component:ds-shell-page",
7220
+ "component:ds-swatch-picker"
7221
+ ],
7222
+ "patterns": [
7223
+ "pattern:application-shell",
7224
+ "pattern:shell-page"
7225
+ ],
7226
+ "accessibility": [
7227
+ "Keep primary destinations in PanelNav and secondary route sections in BarNav.",
7228
+ "Ensure the default content region contains the page's single main landmark.",
7229
+ "Keep PanelNav, BarNav, and PanelTools-compatible chrome available in desktop and tablet compositions and the persistent mobile bar available below 768px.",
7230
+ "Do not override browser keyboard chords when enabling shell shortcuts.",
7231
+ "Require Search and Help as the minimum PanelTools actions and provide accessible labels for every tool.",
7232
+ "Preserve focus and accessible names across navigation, collapse, overflow, and responsive presentation changes."
7233
+ ],
7234
+ "states": [
7235
+ "Render exactly one ShellApp as the workspace root and never nest it.",
7236
+ "PanelNav, BarNav, and ShellTools are the responsive shell regions; ShellTools contains at least Search and Help even when no additional product tools apply.",
7237
+ "The application router owns the current route, authorization filtering, Dashboard or Settings context, destination collections, section collections, and localized content labels.",
7238
+ "ShellApp propagates navStyle and resolved responsive mode and coordinates layout, gradient alignment, transitions, metrics, shortcuts, and mobile-stage visibility.",
7239
+ "The application controls mobileDestination and mobileSheetNavOpen and keeps router state independent from global tool-surface changes.",
7240
+ "Set gradientPreset to the single resolved global chrome preference: neutral by default, none for solid chrome, or cool, neutral, warm, and fresh for token-based washes.",
7241
+ "The application owns gradient preference persistence, cross-tab synchronization, and server or account precedence; ShellApp owns rendering the resolved preset across authenticated routes.",
7242
+ "Dashboard represents day-to-day operational work while Settings represents administrative and configuration work; route state selects the context.",
7243
+ "Update PanelNav groups, BarNav tabs and heading, navStyle, basePath, and currentUrl atomically from one resolved route state.",
7244
+ "BarNav remains present: it shows route-section tabs when available and the active PanelNav destination label as heading otherwise.",
7245
+ "Render one ShellPage as the default-slot child for each standard routed page; ShellApp owns the content scroller while ShellPage owns page header stickiness and content inset.",
7246
+ "The application filters unauthorized destinations, sections, and tools before passing them into shell components."
7247
+ ],
7248
+ "responsiveBehavior": [
7249
+ "ShellApp owns the fixed system breakpoints and resolves desktop at 1200px and wider, tablet from 768px through 1199px, and mobile below 768px.",
7250
+ "On desktop, PanelNav defaults expanded, permits user collapse or expansion, and respects the locally persisted desktop preference.",
7251
+ "On tablet, ShellApp keeps PanelNav permanently collapsed and prevents user expansion without overwriting the desktop preference.",
7252
+ "On mobile, ShellApp hides and inerts PanelNav and BarNav, uses a solid primary stage, and composes routed ShellPage MobileHeader presentations, MobileSheetNav, ShellTools, and the persistent five-item MobileBarNav.",
7253
+ "Mobile global surfaces conceal and inert the routed workspace without unmounting it, preserving nested routes and scroll state.",
7254
+ "Keep PanelNav width, BarNav height, PanelTools chrome, and main-content origin stable except during intentional responsive or collapse transitions.",
7255
+ "The bottom bar remains visible at all route and tool depths in the foundation release."
7256
+ ],
7257
+ "frameworkCaveats": {
7258
+ "customElements": [
7259
+ "Assign complex navigation and tool collections as JavaScript properties on the slotted components.",
7260
+ "Stamp route-derived nav-style before components connect when deterministic first paint is required."
7261
+ ],
7262
+ "react": [
7263
+ "Use generated wrappers and preserve native slot names for desktop navigation, responsive tools, mobile navigation, and main content.",
7264
+ "Resolve all shell inputs from one router state before rendering the composition."
7265
+ ],
7266
+ "angular": [
7267
+ "Use generated standalone adapters and preserve slot attributes in templates.",
7268
+ "Bind complex inputs as properties and update navigation inputs atomically from one resolved router state.",
7269
+ "Bind both nav-style attributes and properties when deterministic first paint is required."
7270
+ ]
7271
+ },
7272
+ "references": [
7273
+ {
7274
+ "label": "Component guide",
7275
+ "path": "src/wc/components/ShellApp/ShellApp.mdx"
7276
+ },
7277
+ {
7278
+ "label": "Executable Storybook composition",
7279
+ "path": "src/wc/components/ShellApp/ShellApp.stories.ts"
7280
+ },
7281
+ {
7282
+ "label": "Framework integration",
7283
+ "path": "docs/framework-integration.md"
7284
+ },
7285
+ {
7286
+ "label": "Application shell contract",
7287
+ "path": "agent/patterns/application-shell/pattern.agent.json"
7288
+ }
7289
+ ]
7290
+ },
7291
+ "props": {
7292
+ "gradientPreset": {
7293
+ "type": "ShellGradientPreset",
7294
+ "required": false
7295
+ },
7296
+ "mobileDestination": {
7297
+ "type": "MobileDestination",
7142
7298
  "required": false
7143
7299
  },
7144
- "inboxDot": {
7300
+ "mobileSheetNavOpen": {
7145
7301
  "type": "boolean",
7146
7302
  "required": false
7147
7303
  },
7148
- "inboxLabel": {
7149
- "type": "string",
7150
- "required": false
7151
- },
7152
- "menuLabel": {
7153
- "type": "string",
7154
- "required": false
7155
- },
7156
- "navigationExpanded": {
7157
- "type": "boolean",
7304
+ "navStyle": {
7305
+ "type": "NavChromeStyle",
7158
7306
  "required": false
7159
7307
  },
7160
- "searchDot": {
7308
+ "shortcutsEnabled": {
7161
7309
  "type": "boolean",
7162
7310
  "required": false
7163
- },
7164
- "searchLabel": {
7165
- "type": "string",
7166
- "required": false
7167
7311
  }
7168
7312
  },
7169
7313
  "events": [
7170
7314
  {
7171
- "name": "dsDestinationChange",
7172
- "detail": "ShellMobileBarDestinationDetail"
7173
- },
7174
- {
7175
- "name": "dsNavigationToggle",
7176
- "detail": "boolean"
7315
+ "name": "dsResponsiveModeChange",
7316
+ "detail": "{ mode: ShellResponsiveMode }"
7177
7317
  }
7178
7318
  ],
7179
7319
  "slots": [],
7180
7320
  "exports": {
7181
- "customElement": "ds-shell-mobile-bar",
7182
- "react": "DsShellMobileBar",
7183
- "angular": "DsShellMobileBar"
7321
+ "customElement": "ds-shell-app",
7322
+ "react": "DsShellApp",
7323
+ "angular": "DsShellApp"
7184
7324
  }
7185
7325
  },
7186
7326
  "dependencies": [
7187
7327
  "@ds-mo/ui",
7188
- "@ds-mo/tokens",
7189
- "@ds-mo/icons"
7328
+ "@ds-mo/tokens"
7190
7329
  ],
7191
- "registryDependencies": [
7192
- "icon",
7193
- "text"
7194
- ]
7330
+ "registryDependencies": []
7195
7331
  },
7196
7332
  {
7197
- "name": "shell-mobile-nav",
7198
- "title": "ShellMobileNav",
7199
- "description": "Full-height mobile primary navigation pane with local Dashboard and Settings browsing.",
7333
+ "name": "shell-gradient-picker",
7334
+ "title": "ShellGradientPicker",
7335
+ "description": "Deprecated compatibility wrapper that maps the fixed ShellApp wash presets into SwatchPicker.",
7200
7336
  "type": "registry:ui",
7201
7337
  "meta": {
7202
7338
  "library": "@ds-mo/ui",
7203
7339
  "distribution": "npm",
7204
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-mobile-nav",
7205
- "source": "src/wc/components/ShellMobileNav/ShellMobileNav.tsx",
7340
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-gradient-picker",
7341
+ "source": "src/wc/components/ShellGradientPicker/ShellGradientPicker.tsx",
7206
7342
  "intentStatus": "complete",
7207
7343
  "intent": {
7208
7344
  "audience": "specialized",
7209
- "status": "experimental",
7210
- "summary": "Full-height mobile primary navigation pane with local Dashboard and Settings browsing.",
7345
+ "status": "deprecated",
7346
+ "replacedBy": "component:ds-swatch-picker",
7347
+ "replacementReason": "SwatchPicker now owns the same accessible interaction with a generic option model that supports both flat colors and gradients.",
7348
+ "summary": "Deprecated compatibility wrapper that maps the fixed ShellApp wash presets into SwatchPicker.",
7211
7349
  "useWhen": [
7212
- "The mobile ShellApp Menu control needs to expose the complete primary navigation collection."
7350
+ "Adding the Appearance or Theme section to the application's user or account menu.",
7351
+ "Users must choose the global ShellApp chrome treatment from none, cool, neutral, warm, or fresh."
7213
7352
  ],
7214
7353
  "avoidWhen": [
7215
- "Rendering desktop PanelNav.",
7216
- "Switching local page content."
7354
+ "Choosing semantic intent, page background, chart, content, or brand colors.",
7355
+ "Building an arbitrary gradient editor or allowing custom gradient values.",
7356
+ "A picker already exists for the application; provide exactly one canonical preference location.",
7357
+ "Rendering an individual swatch outside the complete picker."
7358
+ ],
7359
+ "alternatives": [
7360
+ {
7361
+ "when": "The user is selecting the application light, dark, or system color mode.",
7362
+ "component": "component:ds-menu",
7363
+ "reason": "Color mode is a separate appearance preference and should use ordinary menu selection rows."
7364
+ }
7217
7365
  ],
7218
7366
  "commonlyComposedWith": [
7219
7367
  "component:ds-shell-app",
7220
- "component:ds-shell-mobile-bar"
7368
+ "component:ds-menu"
7221
7369
  ],
7222
7370
  "patterns": [
7223
7371
  "pattern:application-shell"
7224
7372
  ],
7225
7373
  "accessibility": [
7226
- "The pane is a named navigation landmark and retains visible labels for every destination.",
7227
- "Escape requests dismissal and opening moves focus to the selected or first available area."
7374
+ "Provide a localized groupLabel that describes the shell appearance choice.",
7375
+ "Treat the presets as one radio group with one Tab stop; Arrow keys, Home, and End move and select within the group.",
7376
+ "Keep the visible compact swatches and their accessible preset names; do not rely on color alone for assistive technology."
7228
7377
  ],
7229
7378
  "states": [
7230
- "Dashboard and Settings change only the collection being browsed.",
7231
- "Area, Help, and Account events express intent while the application owns navigation and product behavior."
7379
+ "Neutral is the default preset; none renders solid shell chrome without a wash.",
7380
+ "Cool, neutral, warm, and fresh use design tokens and automatically adapt to the active light or dark color theme.",
7381
+ "Apply dsChange immediately to ShellApp.gradientPreset and keep the containing account menu open.",
7382
+ "The application owns local persistence, cross-tab synchronization, and server or account preference precedence; the picker owns only selection UI and events.",
7383
+ "Treat the fixed preset union as the only supported values and do not construct custom gradients."
7232
7384
  ],
7233
7385
  "responsiveBehavior": [
7234
- "The pane fills the mobile content stage while the bottom bar remains available."
7386
+ "Keep the compact picker in the user or account appearance menu on supported desktop and tablet shell compositions.",
7387
+ "The future mobile account surface may present the same preference differently."
7235
7388
  ],
7389
+ "frameworkCaveats": {
7390
+ "customElements": [
7391
+ "Listen for dsChange, resolve application preference precedence, and assign the result to the single ShellApp gradientPreset property."
7392
+ ],
7393
+ "react": [
7394
+ "Use the generated wrapper and handle onDsChange without closing the containing account menu."
7395
+ ],
7396
+ "angular": [
7397
+ "Bind value to the resolved preference and handle dsChange to update application state."
7398
+ ]
7399
+ },
7236
7400
  "references": [
7237
7401
  {
7238
- "label": "Storybook",
7239
- "path": "src/wc/components/ShellMobileNav/ShellMobileNav.stories.ts"
7402
+ "label": "Replacement stories",
7403
+ "path": "src/wc/components/SwatchPicker/SwatchPicker.stories.ts"
7404
+ },
7405
+ {
7406
+ "label": "ShellApp gradient contract",
7407
+ "path": "src/wc/components/ShellApp/ShellApp.mdx"
7408
+ },
7409
+ {
7410
+ "label": "Application shell composition",
7411
+ "path": "agent/patterns/application-shell/pattern.agent.json"
7240
7412
  }
7241
7413
  ]
7242
7414
  },
7243
7415
  "props": {
7244
- "accountLabel": {
7245
- "type": "string",
7246
- "required": false
7247
- },
7248
- "browseContext": {
7249
- "type": "NavChromeStyle",
7250
- "required": false
7251
- },
7252
- "currentUrl": {
7253
- "type": "string",
7254
- "required": false
7255
- },
7256
- "dashboardGroups": {
7257
- "type": "PanelNavGroup[]",
7258
- "required": false
7259
- },
7260
- "dashboardLabel": {
7261
- "type": "string",
7262
- "required": false
7263
- },
7264
- "heading": {
7265
- "type": "string",
7266
- "required": false
7267
- },
7268
- "helpLabel": {
7269
- "type": "string",
7270
- "required": false
7271
- },
7272
- "navigationLabel": {
7416
+ "groupLabel": {
7273
7417
  "type": "string",
7274
7418
  "required": false
7275
7419
  },
7276
- "open": {
7277
- "type": "boolean",
7278
- "required": false
7279
- },
7280
- "settingsGroups": {
7281
- "type": "PanelNavGroup[]",
7282
- "required": false
7283
- },
7284
- "settingsLabel": {
7285
- "type": "string",
7420
+ "value": {
7421
+ "type": "ShellGradientPreset",
7286
7422
  "required": false
7287
7423
  }
7288
7424
  },
7289
7425
  "events": [
7290
7426
  {
7291
- "name": "dsAreaSelect",
7292
- "detail": "string"
7293
- },
7294
- {
7295
- "name": "dsAuxiliarySelect",
7296
- "detail": "ShellMobileNavAuxiliaryDetail"
7297
- },
7298
- {
7299
- "name": "dsBrowseContextChange",
7300
- "detail": "NavChromeStyle"
7301
- },
7302
- {
7303
- "name": "dsClose",
7304
- "detail": "void"
7427
+ "name": "dsChange",
7428
+ "detail": "ShellGradientPreset"
7305
7429
  }
7306
7430
  ],
7307
7431
  "slots": [],
7308
7432
  "exports": {
7309
- "customElement": "ds-shell-mobile-nav",
7310
- "react": "DsShellMobileNav",
7311
- "angular": "DsShellMobileNav"
7433
+ "customElement": "ds-shell-gradient-picker",
7434
+ "react": "DsShellGradientPicker",
7435
+ "angular": "DsShellGradientPicker"
7312
7436
  }
7313
7437
  },
7314
7438
  "dependencies": [
7315
7439
  "@ds-mo/ui",
7316
- "@ds-mo/tokens",
7317
- "@ds-mo/icons"
7440
+ "@ds-mo/tokens"
7318
7441
  ],
7319
7442
  "registryDependencies": [
7320
- "icon",
7321
- "tab-group",
7322
- "text"
7443
+ "swatch-picker"
7323
7444
  ]
7324
7445
  },
7325
7446
  {
7326
- "name": "shell-mobile-section-nav",
7327
- "title": "ShellMobileSectionNav",
7328
- "description": "Horizontally scrollable mobile route navigation corresponding to the active area's desktop BarNav.",
7447
+ "name": "shell-gradient-swatch",
7448
+ "title": "ShellGradientSwatch",
7449
+ "description": "Deprecated internal compatibility component for one legacy ShellApp gradient swatch.",
7329
7450
  "type": "registry:ui",
7330
7451
  "meta": {
7331
7452
  "library": "@ds-mo/ui",
7332
7453
  "distribution": "npm",
7333
- "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-mobile-section-nav",
7334
- "source": "src/wc/components/ShellMobileSectionNav/ShellMobileSectionNav.tsx",
7454
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-gradient-swatch",
7455
+ "source": "src/wc/components/ShellGradientSwatch/ShellGradientSwatch.tsx",
7335
7456
  "intentStatus": "complete",
7336
7457
  "intent": {
7337
- "audience": "specialized",
7338
- "status": "experimental",
7339
- "summary": "Horizontally scrollable mobile route navigation corresponding to the active area's desktop BarNav.",
7458
+ "audience": "internal",
7459
+ "status": "deprecated",
7460
+ "replacedBy": "component:ds-swatch-picker",
7461
+ "replacementReason": "SwatchPicker renders its option buttons internally so an individually published radio swatch is no longer needed.",
7462
+ "summary": "Deprecated internal compatibility component for one legacy ShellApp gradient swatch.",
7340
7463
  "useWhen": [
7341
- "ShellApp is rendering the below-768px routed workspace and the active area has peer route sections."
7464
+ "Maintaining or extending ShellGradientPicker inside CompoMo."
7342
7465
  ],
7343
7466
  "avoidWhen": [
7344
- "Choices switch local content without navigation; use TabGroup.",
7345
- "Rendering the desktop or tablet secondary navigation; use BarNav."
7467
+ "Building application UI directly; use ShellGradientPicker instead.",
7468
+ "Selecting semantic, brand, chart, page, or arbitrary gradient colors.",
7469
+ "Creating a partial or custom set of shell gradient choices."
7346
7470
  ],
7347
7471
  "alternatives": [
7348
7472
  {
7349
- "when": "The choices switch local content without changing routes.",
7350
- "component": "component:ds-tab-group",
7351
- "reason": "TabGroup owns local view selection."
7473
+ "when": "An application needs the supported global shell appearance control.",
7474
+ "component": "component:ds-swatch-picker",
7475
+ "reason": "SwatchPicker provides the complete radio-group semantics, keyboard behavior, generic previews, and selection event."
7352
7476
  }
7353
7477
  ],
7354
7478
  "commonlyComposedWith": [
7355
- "component:ds-shell-app",
7356
- "component:ds-shell-mobile-bar",
7357
- "component:ds-bar-nav"
7358
- ],
7359
- "patterns": [
7360
- "pattern:application-shell"
7479
+ "component:ds-swatch-picker"
7361
7480
  ],
7362
7481
  "accessibility": [
7363
- "The row is a named navigation landmark and the selected section exposes aria-current.",
7364
- "Disabled route sections remain visible but cannot emit navigation intent."
7482
+ "Keep radio semantics, aria-checked state, and a preset-specific accessible name on the internal button.",
7483
+ "Let ShellGradientPicker manage the roving tab stop and group keyboard navigation.",
7484
+ "Do not expose an unlabeled color-only choice."
7365
7485
  ],
7366
7486
  "states": [
7367
- "The host router owns the current URL and handles dsTabChange.",
7368
- "Detail routes that do not match a section show the active-area heading."
7487
+ "Preset determines the token-based preview; selected determines radio state and selected visuals.",
7488
+ "The selected swatch owns the radio group's single tab stop while ShellGradientPicker coordinates selection and focus movement.",
7489
+ "isInactive disables interaction but does not remove the accessible name."
7369
7490
  ],
7370
7491
  "responsiveBehavior": [
7371
- "The row scrolls horizontally without wrapping and centers the selected section when selection changes."
7492
+ "Preserve the fixed compact swatch geometry and let ShellGradientPicker own layout."
7372
7493
  ],
7373
7494
  "frameworkCaveats": {
7374
7495
  "customElements": [
7375
- "Assign tabs as a JavaScript property and update currentUrl and basePath with router state."
7496
+ "Do not instantiate this internal primitive in consuming applications."
7376
7497
  ],
7377
7498
  "react": [
7378
- "Pass the same BarNavTab array used by the desktop BarNav through the generated React wrapper."
7499
+ "Use DsShellGradientPicker rather than the generated swatch wrapper."
7379
7500
  ],
7380
7501
  "angular": [
7381
- "Import the generated standalone adapter and bind tabs as a property."
7502
+ "Use DsShellGradientPicker rather than importing DsShellGradientSwatch."
7382
7503
  ]
7383
7504
  },
7384
7505
  "references": [
7385
7506
  {
7386
- "label": "Storybook",
7387
- "path": "src/wc/components/ShellMobileSectionNav/ShellMobileSectionNav.stories.ts"
7507
+ "label": "Parent picker",
7508
+ "path": "src/wc/components/ShellGradientPicker/ShellGradientPicker.tsx"
7388
7509
  }
7389
7510
  ]
7390
7511
  },
7391
7512
  "props": {
7392
- "basePath": {
7393
- "type": "string",
7394
- "required": false
7395
- },
7396
- "currentUrl": {
7397
- "type": "string",
7398
- "required": false
7399
- },
7400
- "heading": {
7401
- "type": "string | undefined",
7402
- "required": false
7403
- },
7404
- "navigationLabel": {
7405
- "type": "string",
7513
+ "ariaLabel": {
7514
+ "type": "string | null",
7406
7515
  "required": false
7407
7516
  },
7408
- "tabs": {
7409
- "type": "BarNavTab[]",
7517
+ "isInactive": {
7518
+ "type": "boolean",
7410
7519
  "required": false
7411
7520
  },
7412
- "tabsJson": {
7413
- "type": "string",
7521
+ "preset": {
7522
+ "type": "ShellGradientPreset",
7414
7523
  "required": false
7415
7524
  },
7416
- "value": {
7417
- "type": "string",
7525
+ "selected": {
7526
+ "type": "boolean",
7418
7527
  "required": false
7419
7528
  }
7420
7529
  },
7421
7530
  "events": [
7422
7531
  {
7423
- "name": "dsTabChange",
7424
- "detail": "string"
7532
+ "name": "dsSelect",
7533
+ "detail": "ShellGradientPreset"
7425
7534
  }
7426
7535
  ],
7427
7536
  "slots": [],
7428
7537
  "exports": {
7429
- "customElement": "ds-shell-mobile-section-nav",
7430
- "react": "DsShellMobileSectionNav",
7431
- "angular": "DsShellMobileSectionNav"
7538
+ "customElement": "ds-shell-gradient-swatch",
7539
+ "react": "DsShellGradientSwatch",
7540
+ "angular": "DsShellGradientSwatch"
7432
7541
  }
7433
7542
  },
7434
7543
  "dependencies": [
7435
7544
  "@ds-mo/ui",
7436
7545
  "@ds-mo/tokens"
7437
7546
  ],
7438
- "registryDependencies": [
7439
- "text"
7440
- ]
7547
+ "registryDependencies": []
7441
7548
  },
7442
7549
  {
7443
7550
  "name": "shell-page",
@@ -7488,7 +7595,7 @@
7488
7595
  ],
7489
7596
  "accessibility": [
7490
7597
  "ShellPage exposes the routed page as the main landmark; render exactly one active ShellPage inside ShellApp.",
7491
- "Provide exactly one BarTitle or BarWorkflow through the header slot so the page has one h1.",
7598
+ "Provide one BarTitle or BarWorkflow through the desktop header slot and one MobileHeader through mobile-header when the page participates in the mobile shell.",
7492
7599
  "Keep loading, empty, validation, error, progress, success, and failure communication in the default product-content slot.",
7493
7600
  "Responsive variant changes preserve the same heading, controls, accessible names, and keyboard focus targets."
7494
7601
  ],
@@ -7497,12 +7604,13 @@
7497
7604
  "headerPresentation=auto selects the matching header variant from headerCapacity and scroll position.",
7498
7605
  "expanded, compact, and constrained are explicit overrides for exceptional layouts and deterministic examples.",
7499
7606
  "contentInset=default supplies standard page gutters; none permits maps, canvases, and other full-bleed content.",
7500
- "The required header slot accepts one BarTitle or BarWorkflow. The default slot owns router output and all page product content."
7607
+ "The header slot accepts one desktop BarTitle or BarWorkflow; mobile-header accepts the corresponding MobileHeader presentation. The default slot owns router output and all page product content."
7501
7608
  ],
7502
7609
  "responsiveBehavior": [
7503
7610
  "The owning application shell resolves viewport and persistent-chrome state into the explicit headerCapacity prop; ShellPage never guesses the cause of reduced width from its own rendered size.",
7504
7611
  "Roomy capacity expands at the top and compacts after scroll; compact capacity stays compact; constrained capacity uses the constrained action layout.",
7505
7612
  "A ShellPage-managed BarTitle remains concealed until headerCapacity is available and its rendered variant matches the resolved presentation, preventing a default-variant flash during route activation.",
7613
+ "responsiveMode=mobile hides and inerts the desktop header, exposes mobile-header, and disables desktop scroll-compaction geometry.",
7506
7614
  "Update headerCapacity synchronously with shell layout state so opening tools or crossing application breakpoints cannot briefly render the wrong presentation.",
7507
7615
  "On roomy pages, the expanded header scrolls upward until its title and action row reaches the compact row position, then snaps variants without moving that shared visual anchor.",
7508
7616
  "Scroll compaction preserves the expanded page flow offset so content never jumps beneath the sticky header.",
@@ -7511,15 +7619,15 @@
7511
7619
  ],
7512
7620
  "frameworkCaveats": {
7513
7621
  "customElements": [
7514
- "Import ShellPage with BarTitle or BarWorkflow, place one header in slot=header, and render route content as default children.",
7622
+ "Import ShellPage with BarTitle or BarWorkflow in slot=header and MobileHeader in slot=mobile-header, then render route content as default children.",
7515
7623
  "Do not set BarTitle.variant while ShellPage owns headerPresentation."
7516
7624
  ],
7517
7625
  "react": [
7518
- "Render DsBarTitle or DsBarWorkflow with slot=header inside DsShellPage and keep routed content as the remaining children.",
7626
+ "Render the desktop header with slot=header and DsMobileHeader with slot=mobile-header inside DsShellPage.",
7519
7627
  "Use contentInset none only for deliberately full-bleed page products."
7520
7628
  ],
7521
7629
  "angular": [
7522
- "Import the generated standalone DsShellPage adapter with DsBarTitle or DsBarWorkflow, preserve slot=header, and place router-outlet in the ShellPage default slot.",
7630
+ "Import the generated standalone DsShellPage adapter with the desktop header and DsMobileHeader, preserve both header slots, and place router-outlet in the default slot.",
7523
7631
  "Do not add another overflow auto wrapper around the routed page."
7524
7632
  ]
7525
7633
  },
@@ -7550,6 +7658,10 @@
7550
7658
  "headerPresentation": {
7551
7659
  "type": "ShellPageHeaderPresentation",
7552
7660
  "required": false
7661
+ },
7662
+ "responsiveMode": {
7663
+ "type": "ShellResponsiveMode",
7664
+ "required": false
7553
7665
  }
7554
7666
  },
7555
7667
  "events": [],
@@ -7598,7 +7710,9 @@
7598
7710
  "commonlyComposedWith": [
7599
7711
  "component:ds-shell-app",
7600
7712
  "component:ds-panel-tool-header",
7601
- "component:ds-shell-mobile-bar"
7713
+ "component:ds-mobile-header",
7714
+ "component:ds-mobile-section-switcher",
7715
+ "component:ds-mobile-bar-nav"
7602
7716
  ],
7603
7717
  "patterns": [
7604
7718
  "pattern:application-shell"
@@ -7606,7 +7720,7 @@
7606
7720
  "accessibility": [
7607
7721
  "Only the active mobile tool view participates in focus or the accessibility tree.",
7608
7722
  "Header Back and application-owned header actions preserve the PanelTools event contract.",
7609
- "Inbox uses TabGroup semantics for Messages, Stacks, and Activity."
7723
+ "Inbox uses the MobileSectionSwitcher popup trigger for Messages, Stacks, and Activity and never relies on a gesture-only interaction."
7610
7724
  ],
7611
7725
  "states": [
7612
7726
  "The application owns open and activeTool and replaces headers when tool depth changes.",
@@ -7615,7 +7729,7 @@
7615
7729
  ],
7616
7730
  "responsiveBehavior": [
7617
7731
  "Desktop and tablet compose PanelTools-compatible rail and drawer chrome.",
7618
- "Mobile renders the active tool across the shell stage and groups available inbox tools in a segmented control."
7732
+ "Mobile renders one centered MobileHeader for every tool and presents Messages, Stacks, and Activity directly as peer section titles without an additional Inbox heading."
7619
7733
  ],
7620
7734
  "frameworkCaveats": {
7621
7735
  "customElements": [
@@ -7727,9 +7841,10 @@
7727
7841
  "@ds-mo/tokens"
7728
7842
  ],
7729
7843
  "registryDependencies": [
7730
- "panel-tool-header",
7844
+ "button-unfilled",
7845
+ "mobile-header",
7731
7846
  "panel-tools",
7732
- "tab-group"
7847
+ "tooltip"
7733
7848
  ]
7734
7849
  },
7735
7850
  {