@ds-mo/ui 11.1.0 → 12.0.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 (204) hide show
  1. package/README.md +1 -1
  2. package/dist/.build-stamp +1 -1
  3. package/dist/agent-patterns.json +150 -9
  4. package/dist/agent.json +481 -174
  5. package/dist/angular/ds-bar-title.d.ts +28 -0
  6. package/dist/angular/ds-bar-title.js +48 -0
  7. package/dist/angular/ds-panel-nav.d.ts +1 -1
  8. package/dist/angular/{ds-app-shell.d.ts → ds-shell-app.d.ts} +5 -5
  9. package/dist/angular/{ds-app-shell.js → ds-shell-app.js} +10 -10
  10. package/dist/angular/ds-shell-page.d.ts +12 -0
  11. package/dist/angular/ds-shell-page.js +38 -0
  12. package/dist/angular/index.d.ts +1 -1
  13. package/dist/angular/index.js +3 -1
  14. package/dist/angular/proxies.d.ts +3 -1
  15. package/dist/angular/proxies.js +3 -1
  16. package/dist/components/ds-agent-activity.js +1 -1
  17. package/dist/components/ds-agent-response.js +1 -1
  18. package/dist/components/ds-agent-response.js.map +1 -1
  19. package/dist/components/ds-agent-source-list.js +1 -1
  20. package/dist/components/ds-agent-tool-call.js +1 -1
  21. package/dist/components/ds-attachment-list.js +1 -1
  22. package/dist/components/ds-avatar.js +1 -1
  23. package/dist/components/ds-avatar.js.map +1 -1
  24. package/dist/components/ds-badge.js +1 -1
  25. package/dist/components/ds-bar-nav.js +1 -1
  26. package/dist/components/ds-bar-nav.js.map +1 -1
  27. package/dist/components/{ds-app-shell.d.ts → ds-bar-title.d.ts} +4 -4
  28. package/dist/components/ds-bar-title.js +2 -0
  29. package/dist/components/ds-bar-title.js.map +1 -0
  30. package/dist/components/ds-button-filled.js +1 -1
  31. package/dist/components/ds-button-unfilled.js +1 -1
  32. package/dist/components/ds-card-data-viz-donut.js +1 -1
  33. package/dist/components/ds-card-setting.js +1 -1
  34. package/dist/components/ds-card-shell-data-viz.js +1 -1
  35. package/dist/components/ds-chart-bar.js +1 -1
  36. package/dist/components/ds-chart-donut.js +1 -1
  37. package/dist/components/ds-chart-legend.js +1 -1
  38. package/dist/components/ds-chart-line.js +1 -1
  39. package/dist/components/ds-checkbox.js +1 -1
  40. package/dist/components/ds-chip.js +1 -1
  41. package/dist/components/ds-code-block.js +1 -1
  42. package/dist/components/ds-conversation-list-item.js +1 -1
  43. package/dist/components/ds-conversation-list-item.js.map +1 -1
  44. package/dist/components/ds-conversation-list-section.js +1 -1
  45. package/dist/components/ds-conversation-list.js +1 -1
  46. package/dist/components/ds-empty-state.js +1 -1
  47. package/dist/components/ds-field.js +1 -1
  48. package/dist/components/ds-input.js +1 -1
  49. package/dist/components/ds-markdown.js +1 -1
  50. package/dist/components/ds-menu.js +1 -1
  51. package/dist/components/ds-message-composer.js +1 -1
  52. package/dist/components/ds-message-composer.js.map +1 -1
  53. package/dist/components/ds-message-scroller.js +1 -1
  54. package/dist/components/ds-message-scroller.js.map +1 -1
  55. package/dist/components/ds-message.js +1 -1
  56. package/dist/components/ds-modal.js +1 -1
  57. package/dist/components/ds-modal.js.map +1 -1
  58. package/dist/components/ds-panel-nav.js +1 -1
  59. package/dist/components/ds-panel-nav.js.map +1 -1
  60. package/dist/components/ds-panel-sub-nav.js +1 -1
  61. package/dist/components/ds-panel-sub-nav.js.map +1 -1
  62. package/dist/components/ds-panel-tool-header.js +1 -1
  63. package/dist/components/ds-panel-tool-search.js +1 -1
  64. package/dist/components/ds-panel-tool-search.js.map +1 -1
  65. package/dist/components/ds-panel-tools.js +1 -1
  66. package/dist/components/ds-panel-tools.js.map +1 -1
  67. package/dist/components/ds-radio.js +1 -1
  68. package/dist/components/ds-select-multi.js +1 -1
  69. package/dist/components/ds-select-multi.js.map +1 -1
  70. package/dist/components/ds-select.js +1 -1
  71. package/dist/components/ds-select.js.map +1 -1
  72. package/dist/components/ds-shell-app.d.ts +11 -0
  73. package/dist/components/ds-shell-app.js +2 -0
  74. package/dist/components/ds-shell-app.js.map +1 -0
  75. package/dist/components/ds-shell-gradient-picker.js +1 -1
  76. package/dist/components/ds-shell-gradient-picker.js.map +1 -1
  77. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  78. package/dist/components/ds-shell-page.d.ts +11 -0
  79. package/dist/components/ds-shell-page.js +2 -0
  80. package/dist/components/ds-shell-page.js.map +1 -0
  81. package/dist/components/ds-skeleton.js +1 -1
  82. package/dist/components/ds-slider.js +1 -1
  83. package/dist/components/ds-slider.js.map +1 -1
  84. package/dist/components/ds-swatch-picker.js +1 -1
  85. package/dist/components/ds-switch.js +1 -1
  86. package/dist/components/ds-tab-group.js +1 -1
  87. package/dist/components/ds-tag.js +1 -1
  88. package/dist/components/ds-text.js +1 -1
  89. package/dist/components/ds-toast.js +1 -1
  90. package/dist/components/ds-tooltip-data-viz.js +1 -1
  91. package/dist/components/ds-tooltip.js +1 -1
  92. package/dist/components/ds-typing-indicator.js +1 -1
  93. package/dist/components/{p-DJ78wdNv.js → p-6vj4kh70.js} +2 -2
  94. package/dist/components/{p-bNpFhP5L.js → p-B3YvoGjS.js} +2 -2
  95. package/dist/components/{p-BEWtqFX7.js → p-BH3es4p7.js} +2 -2
  96. package/dist/components/{p-BaZRP4Oo.js → p-BUmDHPr3.js} +2 -2
  97. package/dist/components/p-BYHKdFzV.js +2 -0
  98. package/dist/components/p-BYHKdFzV.js.map +1 -0
  99. package/dist/components/p-BZZwQfmN.js +2 -0
  100. package/dist/components/{p-B_qVPsEU.js.map → p-BZZwQfmN.js.map} +1 -1
  101. package/dist/components/{p-Dh4q5TSS.js → p-BhKhX1er.js} +2 -2
  102. package/dist/components/{p-CZZYGqKz.js → p-Bs6SS34m.js} +2 -2
  103. package/dist/components/p-CUik7PCi.js +2 -0
  104. package/dist/components/p-CUik7PCi.js.map +1 -0
  105. package/dist/components/{p-CyoHRqy6.js → p-Cf-i-6aE.js} +2 -2
  106. package/dist/components/p-Cf2J9MEo.js +2 -0
  107. package/dist/components/{p-Bet_UjML.js.map → p-Cf2J9MEo.js.map} +1 -1
  108. package/dist/components/{p-P_4vE1ub.js → p-CwTVEAl2.js} +2 -2
  109. package/dist/components/p-Cy04lXlc.js +2 -0
  110. package/dist/components/p-Cy04lXlc.js.map +1 -0
  111. package/dist/components/{p-BKhG2xrW.js → p-D2x17ei-.js} +1 -1
  112. package/dist/components/{p-BKhG2xrW.js.map → p-D2x17ei-.js.map} +1 -1
  113. package/dist/components/{p-CjP8sYlo.js → p-DABj3qTX.js} +2 -2
  114. package/dist/components/{p-DTqCBjUj.js → p-DUHcJWTQ.js} +2 -2
  115. package/dist/components/{p-CPPAndX2.js → p-DVk0wxxX.js} +2 -2
  116. package/dist/components/p-DfIch2Dk.js +2 -0
  117. package/dist/components/{p-BCCt2eT_.js.map → p-DfIch2Dk.js.map} +1 -1
  118. package/dist/components/{p-CrwU83-g.js → p-Dg3xLna0.js} +2 -2
  119. package/dist/components/{p-DrDHC7V6.js → p-DxeHimqk.js} +2 -2
  120. package/dist/components/{p-DrDHC7V6.js.map → p-DxeHimqk.js.map} +1 -1
  121. package/dist/components/{p-CLn7QnE0.js → p-Dy_sZ-dI.js} +2 -2
  122. package/dist/components/{p-0kEg-Z4f.js → p-liMPkhUP.js} +2 -2
  123. package/dist/components/p-xFbUt9Tc.js +2 -0
  124. package/dist/components/p-xFbUt9Tc.js.map +1 -0
  125. package/dist/docs/components.json +1082 -336
  126. package/dist/lib/shell/chrome-transition.d.ts +1 -1
  127. package/dist/lib/shell/index.js +1 -1
  128. package/dist/lib/shell/index.js.map +1 -1
  129. package/dist/lib/shell/shell-gradient.d.ts +2 -2
  130. package/dist/mcp-data/registry/avatar.json +1 -1
  131. package/dist/mcp-data/registry/badge.json +4 -4
  132. package/dist/mcp-data/registry/bar-nav.json +8 -8
  133. package/dist/mcp-data/registry/bar-title.json +431 -0
  134. package/dist/mcp-data/registry/code-block.json +4 -3
  135. package/dist/mcp-data/registry/menu.json +1 -1
  136. package/dist/mcp-data/registry/message-composer.json +7 -5
  137. package/dist/mcp-data/registry/message-scroller.json +4 -3
  138. package/dist/mcp-data/registry/modal.json +5 -4
  139. package/dist/mcp-data/registry/panel-nav.json +8 -8
  140. package/dist/mcp-data/registry/panel-sub-nav.json +1 -1
  141. package/dist/mcp-data/registry/panel-tool-header.json +4 -3
  142. package/dist/mcp-data/registry/panel-tool-search.json +6 -5
  143. package/dist/mcp-data/registry/panel-tools.json +13 -13
  144. package/dist/mcp-data/registry/registry.json +489 -176
  145. package/dist/mcp-data/registry/select-multi.json +2 -1
  146. package/dist/mcp-data/registry/select.json +2 -1
  147. package/dist/mcp-data/registry/shell-app.json +213 -0
  148. package/dist/mcp-data/registry/shell-gradient-picker.json +8 -8
  149. package/dist/mcp-data/registry/shell-gradient-swatch.json +2 -2
  150. package/dist/mcp-data/registry/shell-page.json +199 -0
  151. package/dist/mcp-data/registry/swatch-picker.json +1 -1
  152. package/dist/react/components.d.ts +3 -1
  153. package/dist/react/components.js +3 -1
  154. package/dist/react/ds-bar-title.d.ts +14 -0
  155. package/dist/react/ds-bar-title.js +16 -0
  156. package/dist/react/{ds-app-shell.d.ts → ds-shell-app.d.ts} +3 -3
  157. package/dist/react/ds-shell-app.js +12 -0
  158. package/dist/react/ds-shell-page.d.ts +9 -0
  159. package/dist/react/ds-shell-page.js +12 -0
  160. package/dist/types/components/Badge/Badge.d.ts +1 -1
  161. package/dist/types/components/BarTitle/BarTitle.d.ts +71 -0
  162. package/dist/types/components/BarTitle/bar-title-types.d.ts +29 -0
  163. package/dist/types/components/BarTitle/index.d.ts +2 -0
  164. package/dist/types/components/Menu/Menu.d.ts +5 -0
  165. package/dist/types/components/PanelNav/PanelNav.d.ts +1 -1
  166. package/dist/types/components/{AppShell/AppShell.d.ts → ShellApp/ShellApp.d.ts} +3 -3
  167. package/dist/types/components/ShellPage/ShellPage.d.ts +37 -0
  168. package/dist/types/components/ShellPage/index.d.ts +3 -0
  169. package/dist/types/components/ShellPage/shell-page-responsive.d.ts +12 -0
  170. package/dist/types/components/ShellPage/shell-page-types.d.ts +5 -0
  171. package/dist/types/components.d.ts +267 -55
  172. package/dist/types/shell/chrome-transition.d.ts +1 -1
  173. package/dist/types/shell/shell-gradient.d.ts +2 -2
  174. package/dist/types/shell/shell-shortcuts.d.ts +1 -1
  175. package/package.json +1 -1
  176. package/dist/components/ds-app-shell.js +0 -2
  177. package/dist/components/ds-app-shell.js.map +0 -1
  178. package/dist/components/p-BCCt2eT_.js +0 -2
  179. package/dist/components/p-B_qVPsEU.js +0 -2
  180. package/dist/components/p-Bet_UjML.js +0 -2
  181. package/dist/components/p-BsnezUUC.js +0 -2
  182. package/dist/components/p-BsnezUUC.js.map +0 -1
  183. package/dist/components/p-C1K5QGUZ.js +0 -2
  184. package/dist/components/p-C1K5QGUZ.js.map +0 -1
  185. package/dist/components/p-CKaJx0IX.js +0 -2
  186. package/dist/components/p-CKaJx0IX.js.map +0 -1
  187. package/dist/components/p-ZTugT4as.js +0 -2
  188. package/dist/components/p-ZTugT4as.js.map +0 -1
  189. package/dist/mcp-data/registry/app-shell.json +0 -210
  190. package/dist/react/ds-app-shell.js +0 -12
  191. /package/dist/components/{p-DJ78wdNv.js.map → p-6vj4kh70.js.map} +0 -0
  192. /package/dist/components/{p-bNpFhP5L.js.map → p-B3YvoGjS.js.map} +0 -0
  193. /package/dist/components/{p-BEWtqFX7.js.map → p-BH3es4p7.js.map} +0 -0
  194. /package/dist/components/{p-BaZRP4Oo.js.map → p-BUmDHPr3.js.map} +0 -0
  195. /package/dist/components/{p-Dh4q5TSS.js.map → p-BhKhX1er.js.map} +0 -0
  196. /package/dist/components/{p-CZZYGqKz.js.map → p-Bs6SS34m.js.map} +0 -0
  197. /package/dist/components/{p-CyoHRqy6.js.map → p-Cf-i-6aE.js.map} +0 -0
  198. /package/dist/components/{p-P_4vE1ub.js.map → p-CwTVEAl2.js.map} +0 -0
  199. /package/dist/components/{p-CjP8sYlo.js.map → p-DABj3qTX.js.map} +0 -0
  200. /package/dist/components/{p-DTqCBjUj.js.map → p-DUHcJWTQ.js.map} +0 -0
  201. /package/dist/components/{p-CPPAndX2.js.map → p-DVk0wxxX.js.map} +0 -0
  202. /package/dist/components/{p-CrwU83-g.js.map → p-Dg3xLna0.js.map} +0 -0
  203. /package/dist/components/{p-CLn7QnE0.js.map → p-Dy_sZ-dI.js.map} +0 -0
  204. /package/dist/components/{p-0kEg-Z4f.js.map → p-liMPkhUP.js.map} +0 -0
@@ -0,0 +1,431 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "bar-title",
4
+ "title": "BarTitle",
5
+ "description": "Page-level title chrome with optional Back navigation, supporting description, inline active-section menu, one primary action, grouped overflow actions, and explicit expanded, compact, or constrained variants.",
6
+ "type": "registry:ui",
7
+ "meta": {
8
+ "library": "@ds-mo/ui",
9
+ "distribution": "npm",
10
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/bar-title",
11
+ "source": "src/wc/components/BarTitle/BarTitle.tsx",
12
+ "intentStatus": "complete",
13
+ "intent": {
14
+ "audience": "general",
15
+ "status": "stable",
16
+ "summary": "Page-level title chrome with optional Back navigation, supporting description, inline active-section menu, one primary action, grouped overflow actions, and explicit expanded, compact, or constrained variants.",
17
+ "useWhen": [
18
+ "A top-level page needs one h1 above its content.",
19
+ "A list or detail page has multiple route-level sections that belong in the inline active-section menu.",
20
+ "A detail, create, or edit page needs a page-level Back action.",
21
+ "A page needs one primary action plus optional secondary or destructive overflow commands."
22
+ ],
23
+ "avoidWhen": [
24
+ "The title belongs to a PanelTools drawer or fullscreen pane; use PanelToolHeader through PanelTools instead.",
25
+ "The choices are primary application destinations or BarNav destinations rather than sections within the current page.",
26
+ "The heading belongs to a card, modal, or other bounded region rather than the page.",
27
+ "Local panels inside page content should remain directly selectable; use TabGroup instead.",
28
+ "Automatic sticky or responsive page orchestration is required; compose BarTitle in ShellPage rather than implementing it in the header."
29
+ ],
30
+ "alternatives": [
31
+ {
32
+ "when": "The header belongs to a PanelTools product view.",
33
+ "component": "component:ds-panel-tool-header",
34
+ "reason": "PanelToolHeader owns pane-level Back and actions without creating page chrome."
35
+ },
36
+ {
37
+ "when": "A small set of inner-page panels should remain visible as tabs.",
38
+ "component": "component:ds-tab-group",
39
+ "reason": "TabGroup is the local content-view control rather than route-level page title chrome."
40
+ }
41
+ ],
42
+ "commonlyComposedWith": [
43
+ "component:ds-shell-page",
44
+ "component:ds-button-filled",
45
+ "component:ds-button-unfilled",
46
+ "component:ds-menu",
47
+ "component:ds-text"
48
+ ],
49
+ "patterns": [
50
+ "pattern:shell-page"
51
+ ],
52
+ "accessibility": [
53
+ "Provide one concise heading; BarTitle renders exactly one h1 and changes only its visual recipe between variants.",
54
+ "Give Back a destination-specific accessible name such as Back to Drivers, provide the concise parent label such as Drivers for the expanded breadcrumb, and handle dsBack in the route owner.",
55
+ "Keep value synchronized with the current child route; dsSectionChange returns the selected section id.",
56
+ "Section and overflow triggers expose menu relationships and restore focus after selection or dismissal.",
57
+ "Use one filled primary action in the page decision area and mark destructive overflow actions explicitly."
58
+ ],
59
+ "states": [
60
+ "Omitting Back, sections, primaryAction, and actions produces the top-level title-only header.",
61
+ "Two or more selectable sections add the inline section trigger; one section does not render a redundant menu.",
62
+ "Dividers in sections or actions create separate Menu groups without becoming selectable rows.",
63
+ "expanded renders the larger heading, optional description, inset divider, and an xs icon-label Back breadcrumb above a flush-left h1; compact renders 48px chrome with inline Back; constrained uses compact chrome and moves an auto-collapse primary action into overflow.",
64
+ "primaryAction collapse defaults to auto. Use never for Save-like actions whose hierarchy must remain visible in constrained layouts."
65
+ ],
66
+ "responsiveBehavior": [
67
+ "BarTitle does not observe viewport, shell, scroll, or container state. Its owner selects an explicit variant.",
68
+ "ShellPage is the standard owner for automatic expanded, compact, and constrained selection.",
69
+ "Compact titles use the shared md control inset so top-level headings align with BarNav and inline Back geometry aligns with PanelToolHeader. Long headings and section labels truncate independently while Back and action controls retain complete hit targets and accessible names.",
70
+ "A never-collapse primary action remains visible in constrained mode; the title and section label yield space first."
71
+ ],
72
+ "frameworkCaveats": {
73
+ "customElements": [
74
+ "Assign sections, primaryAction, and actions as JavaScript properties and replace array or object identities when controlled state changes.",
75
+ "Handle dsBack in the router owner, update value after dsSectionChange, and execute product commands from dsAction."
76
+ ],
77
+ "react": [
78
+ "Pass arrays and objects directly to DsBarTitle and keep value controlled from route state.",
79
+ "Place DsBarTitle in DsShellPage with slot=header when automatic page behavior is required."
80
+ ],
81
+ "angular": [
82
+ "Bind complex values on the standalone DsBarTitle adapter and handle the three intent events in the route shell.",
83
+ "Place ds-bar-title in ds-shell-page with slot=header; do not render router-outlet inside BarTitle."
84
+ ]
85
+ },
86
+ "references": [
87
+ {
88
+ "label": "Explicit variant examples",
89
+ "path": "src/wc/components/BarTitle/BarTitle.stories.ts"
90
+ },
91
+ {
92
+ "label": "ShellPage composition and responsive examples",
93
+ "path": "src/wc/components/ShellPage/ShellPage.stories.ts"
94
+ },
95
+ {
96
+ "label": "Cross-browser shell-page and header coverage",
97
+ "path": "tests/e2e/bar-title.spec.ts"
98
+ }
99
+ ]
100
+ },
101
+ "api": {
102
+ "props": {
103
+ "actions": {
104
+ "type": "BarTitleActionItem[]",
105
+ "resolvedType": "BarTitleActionItem[]",
106
+ "default": "[]",
107
+ "required": false,
108
+ "mutable": false,
109
+ "description": "Secondary page actions shown in the overflow menu. Dividers create groups."
110
+ },
111
+ "actionsAriaLabel": {
112
+ "type": "string",
113
+ "resolvedType": "string",
114
+ "attribute": "actions-aria-label",
115
+ "default": "'More page actions'",
116
+ "required": false,
117
+ "mutable": false,
118
+ "description": "Accessible name for the page-actions menu."
119
+ },
120
+ "backAriaLabel": {
121
+ "type": "string",
122
+ "resolvedType": "string",
123
+ "attribute": "back-aria-label",
124
+ "default": "'Back'",
125
+ "required": false,
126
+ "mutable": false,
127
+ "description": "Accessible name for the leading Back action."
128
+ },
129
+ "backLabel": {
130
+ "type": "string",
131
+ "resolvedType": "string",
132
+ "attribute": "back-label",
133
+ "default": "'Back'",
134
+ "required": false,
135
+ "mutable": false,
136
+ "description": "Visible parent-page label used by the expanded Back breadcrumb."
137
+ },
138
+ "description": {
139
+ "type": "string",
140
+ "resolvedType": "string",
141
+ "attribute": "description",
142
+ "default": "''",
143
+ "required": false,
144
+ "mutable": false,
145
+ "description": "Optional supporting copy shown in the expanded presentation."
146
+ },
147
+ "heading": {
148
+ "type": "string",
149
+ "resolvedType": "string",
150
+ "attribute": "heading",
151
+ "required": true,
152
+ "mutable": false,
153
+ "description": "The page's single visible h1."
154
+ },
155
+ "primaryAction": {
156
+ "type": "BarTitlePrimaryAction | null",
157
+ "resolvedType": "BarTitlePrimaryAction | null",
158
+ "default": "null",
159
+ "required": false,
160
+ "mutable": false,
161
+ "description": "The one highest-emphasis page action."
162
+ },
163
+ "sections": {
164
+ "type": "BarTitleSectionItem[]",
165
+ "resolvedType": "BarTitleSectionItem[]",
166
+ "default": "[]",
167
+ "required": false,
168
+ "mutable": false,
169
+ "description": "Optional page sections exposed through the active-section menu."
170
+ },
171
+ "sectionsAriaLabel": {
172
+ "type": "string",
173
+ "resolvedType": "string",
174
+ "attribute": "sections-aria-label",
175
+ "default": "'Change page section'",
176
+ "required": false,
177
+ "mutable": false,
178
+ "description": "Accessible name for the page-section menu."
179
+ },
180
+ "showBack": {
181
+ "type": "boolean",
182
+ "resolvedType": "boolean",
183
+ "attribute": "show-back",
184
+ "default": "false",
185
+ "required": false,
186
+ "mutable": false,
187
+ "description": "Show the leading page-level Back action."
188
+ },
189
+ "value": {
190
+ "type": "string",
191
+ "resolvedType": "string",
192
+ "attribute": "value",
193
+ "default": "''",
194
+ "required": false,
195
+ "mutable": false,
196
+ "description": "Id of the active page section."
197
+ },
198
+ "variant": {
199
+ "type": "BarTitleVariant",
200
+ "resolvedType": "\"compact\" | \"constrained\" | \"expanded\"",
201
+ "attribute": "variant",
202
+ "default": "'expanded'",
203
+ "required": false,
204
+ "mutable": false,
205
+ "description": "Explicit visual/capacity variant. ShellPage owns automatic selection."
206
+ }
207
+ },
208
+ "events": [
209
+ {
210
+ "name": "dsAction",
211
+ "detail": "string",
212
+ "bubbles": true,
213
+ "cancelable": true,
214
+ "composed": true,
215
+ "description": "Emitted with the activated primary or overflow action id."
216
+ },
217
+ {
218
+ "name": "dsBack",
219
+ "detail": "MouseEvent",
220
+ "bubbles": true,
221
+ "cancelable": true,
222
+ "composed": true,
223
+ "description": "Emitted when the leading Back action is activated."
224
+ },
225
+ {
226
+ "name": "dsSectionChange",
227
+ "detail": "string",
228
+ "bubbles": true,
229
+ "cancelable": true,
230
+ "composed": true,
231
+ "description": "Emitted with the newly selected page-section id."
232
+ }
233
+ ],
234
+ "methods": [],
235
+ "slots": []
236
+ },
237
+ "props": {
238
+ "actions": {
239
+ "type": "BarTitleActionItem[]",
240
+ "resolvedType": "BarTitleActionItem[]",
241
+ "default": "[]",
242
+ "required": false,
243
+ "mutable": false,
244
+ "description": "Secondary page actions shown in the overflow menu. Dividers create groups."
245
+ },
246
+ "actionsAriaLabel": {
247
+ "type": "string",
248
+ "resolvedType": "string",
249
+ "attribute": "actions-aria-label",
250
+ "default": "'More page actions'",
251
+ "required": false,
252
+ "mutable": false,
253
+ "description": "Accessible name for the page-actions menu."
254
+ },
255
+ "backAriaLabel": {
256
+ "type": "string",
257
+ "resolvedType": "string",
258
+ "attribute": "back-aria-label",
259
+ "default": "'Back'",
260
+ "required": false,
261
+ "mutable": false,
262
+ "description": "Accessible name for the leading Back action."
263
+ },
264
+ "backLabel": {
265
+ "type": "string",
266
+ "resolvedType": "string",
267
+ "attribute": "back-label",
268
+ "default": "'Back'",
269
+ "required": false,
270
+ "mutable": false,
271
+ "description": "Visible parent-page label used by the expanded Back breadcrumb."
272
+ },
273
+ "description": {
274
+ "type": "string",
275
+ "resolvedType": "string",
276
+ "attribute": "description",
277
+ "default": "''",
278
+ "required": false,
279
+ "mutable": false,
280
+ "description": "Optional supporting copy shown in the expanded presentation."
281
+ },
282
+ "heading": {
283
+ "type": "string",
284
+ "resolvedType": "string",
285
+ "attribute": "heading",
286
+ "required": true,
287
+ "mutable": false,
288
+ "description": "The page's single visible h1."
289
+ },
290
+ "primaryAction": {
291
+ "type": "BarTitlePrimaryAction | null",
292
+ "resolvedType": "BarTitlePrimaryAction | null",
293
+ "default": "null",
294
+ "required": false,
295
+ "mutable": false,
296
+ "description": "The one highest-emphasis page action."
297
+ },
298
+ "sections": {
299
+ "type": "BarTitleSectionItem[]",
300
+ "resolvedType": "BarTitleSectionItem[]",
301
+ "default": "[]",
302
+ "required": false,
303
+ "mutable": false,
304
+ "description": "Optional page sections exposed through the active-section menu."
305
+ },
306
+ "sectionsAriaLabel": {
307
+ "type": "string",
308
+ "resolvedType": "string",
309
+ "attribute": "sections-aria-label",
310
+ "default": "'Change page section'",
311
+ "required": false,
312
+ "mutable": false,
313
+ "description": "Accessible name for the page-section menu."
314
+ },
315
+ "showBack": {
316
+ "type": "boolean",
317
+ "resolvedType": "boolean",
318
+ "attribute": "show-back",
319
+ "default": "false",
320
+ "required": false,
321
+ "mutable": false,
322
+ "description": "Show the leading page-level Back action."
323
+ },
324
+ "value": {
325
+ "type": "string",
326
+ "resolvedType": "string",
327
+ "attribute": "value",
328
+ "default": "''",
329
+ "required": false,
330
+ "mutable": false,
331
+ "description": "Id of the active page section."
332
+ },
333
+ "variant": {
334
+ "type": "BarTitleVariant",
335
+ "resolvedType": "\"compact\" | \"constrained\" | \"expanded\"",
336
+ "attribute": "variant",
337
+ "default": "'expanded'",
338
+ "required": false,
339
+ "mutable": false,
340
+ "description": "Explicit visual/capacity variant. ShellPage owns automatic selection."
341
+ }
342
+ },
343
+ "events": [
344
+ {
345
+ "name": "dsAction",
346
+ "detail": "string",
347
+ "bubbles": true,
348
+ "cancelable": true,
349
+ "composed": true,
350
+ "description": "Emitted with the activated primary or overflow action id."
351
+ },
352
+ {
353
+ "name": "dsBack",
354
+ "detail": "MouseEvent",
355
+ "bubbles": true,
356
+ "cancelable": true,
357
+ "composed": true,
358
+ "description": "Emitted when the leading Back action is activated."
359
+ },
360
+ {
361
+ "name": "dsSectionChange",
362
+ "detail": "string",
363
+ "bubbles": true,
364
+ "cancelable": true,
365
+ "composed": true,
366
+ "description": "Emitted with the newly selected page-section id."
367
+ }
368
+ ],
369
+ "methods": [],
370
+ "slots": [],
371
+ "exports": {
372
+ "customElement": "ds-bar-title",
373
+ "react": "DsBarTitle",
374
+ "angular": "DsBarTitle"
375
+ },
376
+ "consumption": {
377
+ "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
378
+ "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
379
+ "customElements": {
380
+ "import": "import '@ds-mo/ui/dist/components/ds-bar-title.js';",
381
+ "example": "<ds-bar-title></ds-bar-title>"
382
+ },
383
+ "react": {
384
+ "import": "import { DsBarTitle } from '@ds-mo/ui/react';",
385
+ "example": "<DsBarTitle />"
386
+ },
387
+ "angular": {
388
+ "import": "import { DsBarTitle } from '@ds-mo/ui/angular/ds-bar-title';",
389
+ "example": "<ds-bar-title></ds-bar-title>"
390
+ },
391
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: actions, primaryAction, sections.",
392
+ "peerDependencies": {
393
+ "required": [
394
+ "@ds-mo/tokens ^3.1.1",
395
+ "@ds-mo/icons ^6.3.0"
396
+ ],
397
+ "frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
398
+ }
399
+ }
400
+ },
401
+ "dependencies": [
402
+ "@ds-mo/ui",
403
+ "@ds-mo/tokens",
404
+ "@ds-mo/icons"
405
+ ],
406
+ "registryDependencies": [
407
+ "button-filled",
408
+ "button-unfilled",
409
+ "icon",
410
+ "menu",
411
+ "text",
412
+ "tooltip"
413
+ ],
414
+ "files": [
415
+ {
416
+ "path": "src/wc/components/BarTitle/BarTitle.css",
417
+ "content": "@import '../../utils/control-density.css';\n@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n\n:host {\n display: block;\n min-width: 0;\n box-sizing: border-box;\n background: var(--color-background-primary);\n}\n\n.bar-title {\n position: relative;\n min-width: 0;\n padding: 0;\n box-sizing: border-box;\n background: var(--color-background-primary);\n}\n\n.bar-title::after {\n content: '';\n position: absolute;\n inset: auto var(--dimension-space-400) 0;\n height: var(--dimension-stroke-width-012);\n background: var(--color-border-tertiary);\n pointer-events: none;\n}\n\n.bar-title__inner {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--dimension-space-100);\n padding: var(--dimension-space-400);\n box-sizing: border-box;\n}\n\n.bar-title__row {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-100);\n min-height: var(--dimension-size-400);\n min-width: 0;\n}\n\n.bar-title__identity {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n gap: var(--dimension-space-050);\n min-width: 0;\n}\n\n.bar-title__back,\n.bar-title__breadcrumb-back,\n.bar-title__section-chevron {\n flex: 0 0 auto;\n}\n\n.bar-title__breadcrumb {\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n.bar-title__heading {\n display: block;\n width: auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n user-select: none;\n}\n\n.bar-title__divider {\n width: var(--dimension-stroke-width-012);\n height: var(--dimension-size-250);\n flex: 0 0 var(--dimension-stroke-width-012);\n background: var(--color-border-tertiary);\n}\n\n.bar-title__section-selector {\n display: flex;\n flex: 0 1 auto;\n min-width: 0;\n max-width: var(--dimension-panel-width-sm);\n}\n\n.bar-title__section-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--ds-control-gap);\n height: var(--ds-control-height);\n min-width: 0;\n max-width: 100%;\n padding-inline: var(--ds-control-padding-inline);\n border: none;\n border-radius: var(--ds-control-radius);\n box-sizing: border-box;\n background: transparent;\n color: var(--color-foreground-secondary);\n cursor: pointer;\n font-family: inherit;\n user-select: none;\n transition: color var(--effect-motion-short-2);\n}\n\n.bar-title__section-trigger--expanded {\n color: var(--color-foreground-primary);\n}\n\n.bar-title__section-trigger--expanded::after,\n.bar-title__section-trigger--expanded:hover::after {\n background: var(--ds-interaction-pressed);\n}\n\n.bar-title__section-label {\n min-width: 0;\n padding-inline-start: var(--ds-control-label-inset);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.bar-title__section-chevron {\n margin-inline-end: var(--ds-control-label-inset);\n}\n\n.bar-title__actions {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-100);\n margin-inline-start: auto;\n flex: 0 0 auto;\n}\n\n.bar-title__description {\n display: block;\n width: auto;\n min-width: 0;\n max-width: 100%;\n height: var(--dimension-size-400);\n margin-inline-start: 0;\n overflow: hidden;\n}\n\n:host(.bar-title-host--compact) .bar-title {\n height: var(--dimension-size-600);\n padding: var(--dimension-space-100);\n}\n\n:host(.bar-title-host--compact) .bar-title::after {\n inset-inline: 0;\n}\n\n:host(.bar-title-host--compact) .bar-title__inner {\n height: 100%;\n padding: 0;\n gap: 0;\n}\n\n:host(.bar-title-host--compact) .bar-title__row {\n height: 100%;\n}\n\n:host(.bar-title-host--compact) .bar-title__identity {\n height: var(--dimension-size-400);\n}\n\n:host(.bar-title-host--compact) .bar-title__heading {\n display: inline-flex;\n flex: 1 1 auto;\n align-items: center;\n height: var(--dimension-size-400);\n padding-inline: calc(var(--ds-control-padding-inline) + var(--ds-control-label-inset));\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .bar-title__section-trigger {\n transition: none;\n }\n}\n",
418
+ "type": "registry:ui"
419
+ },
420
+ {
421
+ "path": "src/wc/components/BarTitle/BarTitle.tsx",
422
+ "content": "import { Component, Event, EventEmitter, h, Host, Prop, State, Watch } from '@stencil/core';\nimport type { MenuItemData, MenuSection } from '../Menu/menu-types';\nimport {\n isBarTitleDivider,\n type BarTitleAction,\n type BarTitleActionItem,\n type BarTitlePrimaryAction,\n type BarTitleSection,\n type BarTitleSectionItem,\n type BarTitleVariant,\n} from './bar-title-types';\n\nlet nextBarTitleId = 0;\n\ntype FocusableButton = HTMLElement & { setFocus?: () => Promise<void> };\n\n@Component({\n tag: 'ds-bar-title',\n styleUrl: 'BarTitle.css',\n scoped: true,\n})\nexport class BarTitle {\n /** The page's single visible h1. */\n @Prop() heading!: string;\n\n /** Optional supporting copy shown in the expanded presentation. */\n @Prop() description: string = '';\n\n /** Show the leading page-level Back action. */\n @Prop({ attribute: 'show-back' }) showBack: boolean = false;\n\n /** Accessible name for the leading Back action. */\n @Prop() backAriaLabel: string = 'Back';\n\n /** Visible parent-page label used by the expanded Back breadcrumb. */\n @Prop() backLabel: string = 'Back';\n\n /** Optional page sections exposed through the active-section menu. */\n @Prop() sections: BarTitleSectionItem[] = [];\n\n /** Id of the active page section. */\n @Prop() value: string = '';\n\n /** Accessible name for the page-section menu. */\n @Prop() sectionsAriaLabel: string = 'Change page section';\n\n /** The one highest-emphasis page action. */\n @Prop() primaryAction: BarTitlePrimaryAction | null = null;\n\n /** Secondary page actions shown in the overflow menu. Dividers create groups. */\n @Prop() actions: BarTitleActionItem[] = [];\n\n /** Accessible name for the page-actions menu. */\n @Prop() actionsAriaLabel: string = 'More page actions';\n\n /** Explicit visual/capacity variant. ShellPage owns automatic selection. */\n @Prop() variant: BarTitleVariant = 'expanded';\n\n /** Emitted when the leading Back action is activated. */\n @Event() dsBack!: EventEmitter<MouseEvent>;\n\n /** Emitted with the newly selected page-section id. */\n @Event() dsSectionChange!: EventEmitter<string>;\n\n /** Emitted with the activated primary or overflow action id. */\n @Event() dsAction!: EventEmitter<string>;\n\n @State() private sectionMenuOpen = false;\n @State() private actionMenuOpen = false;\n @State() private sectionMenuInitialFocusVisible = false;\n @State() private actionMenuInitialFocusVisible = false;\n\n private readonly instanceId = nextBarTitleId++;\n private readonly sectionMenuTriggerId = `bar-title-section-trigger-${this.instanceId}`;\n private readonly sectionMenuId = `bar-title-section-menu-${this.instanceId}`;\n private readonly actionMenuTriggerId = `bar-title-action-trigger-${this.instanceId}`;\n private readonly actionMenuId = `bar-title-action-menu-${this.instanceId}`;\n private sectionTriggerEl: HTMLButtonElement | null = null;\n private actionTriggerEl: FocusableButton | null = null;\n\n @Watch('sections')\n handleSectionsChange() {\n if (!this.hasSectionSelector) this.closeSectionMenu();\n }\n\n @Watch('actions')\n @Watch('primaryAction')\n handleActionsChange() {\n if (!this.showActionMenuTrigger) this.closeActionMenu();\n }\n\n private get compact(): boolean {\n return this.variant !== 'expanded';\n }\n\n private get primaryCollapsed(): boolean {\n return (\n this.variant === 'constrained' &&\n this.primaryAction !== null &&\n (this.primaryAction.collapse ?? 'auto') === 'auto'\n );\n }\n\n private get selectableSections(): BarTitleSection[] {\n return this.sections.filter((item): item is BarTitleSection => !isBarTitleDivider(item));\n }\n\n private get hasSectionSelector(): boolean {\n return this.selectableSections.length > 1;\n }\n\n private get effectiveValue(): string {\n return this.selectableSections.some(section => section.id === this.value)\n ? this.value\n : (this.selectableSections[0]?.id ?? '');\n }\n\n private get selectedSectionLabel(): string {\n return this.selectableSections.find(section => section.id === this.effectiveValue)?.label ?? '';\n }\n\n private get sectionTriggerAriaLabel(): string {\n return `${this.sectionsAriaLabel}. Current section: ${this.selectedSectionLabel}`;\n }\n\n private groupsFromItems<T extends BarTitleSection | BarTitleAction>(\n source: Array<T | { type: 'divider' }>,\n map: (item: T) => MenuItemData\n ): MenuSection[] {\n const groups: MenuSection[] = [];\n let items: MenuItemData[] = [];\n const commit = () => {\n if (items.length > 0) groups.push({ items });\n items = [];\n };\n\n for (const item of source) {\n if (isBarTitleDivider(item)) {\n commit();\n } else {\n items.push(map(item));\n }\n }\n commit();\n return groups;\n }\n\n private get sectionMenuSections(): MenuSection[] {\n return this.groupsFromItems(this.sections, section => ({\n label: section.label,\n value: section.id,\n isSelected: section.id === this.effectiveValue,\n isInactive: section.isInactive,\n }));\n }\n\n private get selectableActions(): BarTitleAction[] {\n return this.actions.filter((item): item is BarTitleAction => !isBarTitleDivider(item));\n }\n\n private get showActionMenuTrigger(): boolean {\n return (\n this.selectableActions.length > 0 || (this.primaryCollapsed && this.primaryAction !== null)\n );\n }\n\n private actionMenuItem(action: BarTitleAction | BarTitlePrimaryAction): MenuItemData {\n const primary = action as BarTitlePrimaryAction;\n return {\n label: action.label,\n value: action.id,\n isInactive: action.isInactive || primary.isLoading,\n isDestructive: action.isDestructive || primary.intent === 'negative',\n };\n }\n\n private get actionMenuSections(): MenuSection[] {\n const groups = this.groupsFromItems(this.actions, action => this.actionMenuItem(action));\n if (!this.primaryCollapsed || !this.primaryAction) return groups;\n return [{ items: [this.actionMenuItem(this.primaryAction)] }, ...groups];\n }\n\n private toggleSectionMenu = (event: MouseEvent) => {\n this.sectionMenuInitialFocusVisible = event.detail === 0;\n this.actionMenuOpen = false;\n this.sectionMenuOpen = !this.sectionMenuOpen;\n };\n\n private closeSectionMenu = () => {\n this.sectionMenuOpen = false;\n };\n\n private handleSectionSelect = (event: CustomEvent<MenuItemData>) => {\n const id = String(event.detail?.value ?? '');\n const selected = this.selectableSections.find(section => section.id === id);\n if (!selected || selected.isInactive) return;\n this.closeSectionMenu();\n this.dsSectionChange.emit(id);\n requestAnimationFrame(() => this.sectionTriggerEl?.focus());\n };\n\n private toggleActionMenu = (event: MouseEvent) => {\n this.actionMenuInitialFocusVisible = event.detail === 0;\n this.sectionMenuOpen = false;\n this.actionMenuOpen = !this.actionMenuOpen;\n };\n\n private closeActionMenu = () => {\n this.actionMenuOpen = false;\n };\n\n private handleActionSelect = (event: CustomEvent<MenuItemData>) => {\n const id = String(event.detail?.value ?? '');\n const primaryMatches = this.primaryCollapsed && this.primaryAction?.id === id;\n const action = this.selectableActions.find(candidate => candidate.id === id);\n if (!primaryMatches && !action) return;\n if (\n (primaryMatches && (this.primaryAction?.isInactive || this.primaryAction?.isLoading)) ||\n action?.isInactive\n ) {\n return;\n }\n this.closeActionMenu();\n this.dsAction.emit(id);\n requestAnimationFrame(() => void this.actionTriggerEl?.setFocus?.());\n };\n\n private renderSectionSelector() {\n if (!this.hasSectionSelector) return null;\n return [\n <div class=\"bar-title__divider\" aria-hidden=\"true\" />,\n <div class=\"bar-title__section-selector\">\n <button\n ref={el => {\n this.sectionTriggerEl = el ?? null;\n }}\n id={this.sectionMenuTriggerId}\n class={{\n 'bar-title__section-trigger': true,\n 'bar-title__section-trigger--expanded': this.sectionMenuOpen,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-interaction-fill': true,\n }}\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-controls={this.sectionMenuId}\n aria-expanded={String(this.sectionMenuOpen)}\n aria-label={this.sectionTriggerAriaLabel}\n onClick={this.toggleSectionMenu}\n >\n <ds-text\n class=\"bar-title__section-label ds-interaction-fill__content\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis\n color=\"primary\"\n >\n {this.selectedSectionLabel}\n </ds-text>\n <ds-icon\n class=\"bar-title__section-chevron ds-interaction-fill__content\"\n name=\"ChevronUpDown\"\n size=\"sm\"\n color=\"inherit\"\n aria-hidden=\"true\"\n />\n </button>\n </div>,\n ];\n }\n\n private renderActions() {\n const primary = this.primaryAction;\n if (!primary && !this.showActionMenuTrigger) return null;\n\n return (\n <div class=\"bar-title__actions\">\n {primary && !this.primaryCollapsed ? (\n <ds-button-filled\n class=\"bar-title__primary-action\"\n variant={primary.icon ? 'icon-label' : 'label'}\n icon={primary.icon ?? ''}\n label={primary.label}\n intent={primary.intent ?? 'brand'}\n contrast={primary.contrast ?? 'bold'}\n size=\"md\"\n type={primary.type ?? 'button'}\n isInactive={primary.isInactive}\n isLoading={primary.isLoading}\n onDsClick={() => this.dsAction.emit(primary.id)}\n />\n ) : null}\n {this.showActionMenuTrigger ? (\n <ds-button-unfilled\n ref={el => {\n this.actionTriggerEl = el ?? null;\n }}\n id={this.actionMenuTriggerId}\n class=\"bar-title__more-actions\"\n variant=\"icon\"\n icon=\"Ellipses\"\n aria-label={this.actionsAriaLabel}\n size=\"md\"\n activeFill={!this.compact}\n hasBorder={!this.compact && !this.primaryCollapsed}\n haspopup=\"menu\"\n controls={this.actionMenuId}\n expanded={this.actionMenuOpen}\n onDsClick={(event: CustomEvent<MouseEvent>) => this.toggleActionMenu(event.detail)}\n />\n ) : null}\n </div>\n );\n }\n\n private renderBack(compact: boolean) {\n if (!this.showBack) return null;\n\n if (!compact) {\n return (\n <div class=\"bar-title__breadcrumb\">\n <ds-button-unfilled\n class=\"bar-title__breadcrumb-back\"\n variant=\"icon-label\"\n icon=\"ChevronLeft\"\n label={this.backLabel}\n aria-label={this.backAriaLabel}\n size=\"xs\"\n hasBorder={false}\n onDsClick={(event: CustomEvent<MouseEvent>) => this.dsBack.emit(event.detail)}\n />\n </div>\n );\n }\n\n return (\n <ds-tooltip label={this.backAriaLabel} side=\"bottom\" size=\"sm\">\n <ds-button-unfilled\n class=\"bar-title__back\"\n variant=\"icon\"\n icon=\"ChevronLeft\"\n aria-label={this.backAriaLabel}\n size=\"md\"\n activeFill={false}\n hasBorder={false}\n onDsClick={(event: CustomEvent<MouseEvent>) => this.dsBack.emit(event.detail)}\n />\n </ds-tooltip>\n );\n }\n\n render() {\n const compact = this.compact;\n return (\n <Host\n class={{\n 'bar-title-host--compact': compact,\n 'bar-title-host--expanded': this.variant === 'expanded',\n 'bar-title-host--constrained': this.variant === 'constrained',\n 'bar-title-host--has-description': !!this.description,\n 'bar-title-host--has-back': this.showBack,\n }}\n >\n <div class=\"bar-title\">\n <div class=\"bar-title__inner\">\n {!compact ? this.renderBack(false) : null}\n <div class=\"bar-title__row\">\n <div class=\"bar-title__identity\">\n {compact ? this.renderBack(true) : null}\n <ds-text\n class=\"bar-title__heading ds-control--md\"\n variant={compact ? 'text-title-small' : 'text-title-medium'}\n emphasis\n color=\"primary\"\n as=\"h1\"\n lineTruncation={1}\n >\n {this.heading}\n </ds-text>\n </div>\n {this.renderSectionSelector()}\n {this.renderActions()}\n </div>\n {this.description && !compact ? (\n <ds-text\n class=\"bar-title__description\"\n variant=\"text-body-small\"\n color=\"secondary\"\n lineTruncation={2}\n wrap=\"wrap\"\n as=\"p\"\n >\n {this.description}\n </ds-text>\n ) : null}\n </div>\n </div>\n\n {this.hasSectionSelector ? (\n <ds-menu\n id={this.sectionMenuId}\n class=\"bar-title__section-menu\"\n anchorId={this.sectionMenuTriggerId}\n menuLabel={this.sectionsAriaLabel}\n open={this.sectionMenuOpen}\n initialFocusVisible={this.sectionMenuInitialFocusVisible}\n sections={this.sectionMenuSections}\n onDsClose={this.closeSectionMenu}\n onDsSelect={this.handleSectionSelect}\n />\n ) : null}\n\n {this.showActionMenuTrigger ? (\n <ds-menu\n id={this.actionMenuId}\n class=\"bar-title__action-menu\"\n anchorId={this.actionMenuTriggerId}\n align=\"end\"\n menuLabel={this.actionsAriaLabel}\n open={this.actionMenuOpen}\n initialFocusVisible={this.actionMenuInitialFocusVisible}\n sections={this.actionMenuSections}\n onDsClose={this.closeActionMenu}\n onDsSelect={this.handleActionSelect}\n />\n ) : null}\n </Host>\n );\n }\n}\n",
423
+ "type": "registry:ui"
424
+ },
425
+ {
426
+ "path": "src/wc/components/BarTitle/bar-title-types.ts",
427
+ "content": "import type { ButtonFilledContrast, ButtonFilledIntent } from '../ButtonFilled/ButtonFilled';\n\nexport interface BarTitleSection {\n id: string;\n label: string;\n isInactive?: boolean;\n}\n\nexport interface BarTitleDivider {\n type: 'divider';\n}\n\nexport type BarTitleSectionItem = BarTitleSection | BarTitleDivider;\n\nexport interface BarTitleAction {\n id: string;\n label: string;\n isInactive?: boolean;\n isDestructive?: boolean;\n}\n\nexport interface BarTitlePrimaryAction extends BarTitleAction {\n icon?: string;\n intent?: ButtonFilledIntent;\n contrast?: ButtonFilledContrast;\n isLoading?: boolean;\n type?: 'button' | 'submit' | 'reset';\n collapse?: BarTitlePrimaryActionCollapse;\n}\n\nexport type BarTitleActionItem = BarTitleAction | BarTitleDivider;\n\nexport type BarTitleVariant = 'expanded' | 'compact' | 'constrained';\n\nexport type BarTitlePrimaryActionCollapse = 'auto' | 'never';\n\nexport function isBarTitleDivider(\n item: BarTitleSectionItem | BarTitleActionItem\n): item is BarTitleDivider {\n return 'type' in item && item.type === 'divider';\n}\n",
428
+ "type": "registry:ui"
429
+ }
430
+ ]
431
+ }
@@ -25,7 +25,7 @@
25
25
  "component:ds-button-unfilled"
26
26
  ],
27
27
  "accessibility": [
28
- "The copy action has explicit status wording and the code remains selectable text.",
28
+ "The copy action has matching accessible-name and visible-tooltip status wording, and the code remains selectable text.",
29
29
  "Language and filename labels supplement rather than replace the code content."
30
30
  ],
31
31
  "responsiveBehavior": [
@@ -133,7 +133,8 @@
133
133
  ],
134
134
  "registryDependencies": [
135
135
  "button-unfilled",
136
- "text"
136
+ "text",
137
+ "tooltip"
137
138
  ],
138
139
  "files": [
139
140
  {
@@ -143,7 +144,7 @@
143
144
  },
144
145
  {
145
146
  "path": "src/wc/components/CodeBlock/CodeBlock.tsx",
146
- "content": "import { Component, h, Host, Prop, State } from '@stencil/core';\n\n@Component({\n tag: 'ds-code-block',\n styleUrl: 'CodeBlock.css',\n scoped: true,\n})\nexport class CodeBlock {\n @Prop() code: string = '';\n @Prop() language: string = '';\n @Prop() filename: string = '';\n\n @State() private copied: boolean = false;\n private copiedTimer?: ReturnType<typeof setTimeout>;\n\n disconnectedCallback() {\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n }\n\n private copy = async () => {\n if (!navigator.clipboard || !this.code) return;\n await navigator.clipboard.writeText(this.code);\n this.copied = true;\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copied = false;\n }, 2000);\n };\n\n render() {\n const label = this.filename || this.language || 'Code';\n return (\n <Host>\n <figure class=\"code-block\">\n <figcaption class=\"code-block__header\">\n <ds-text as=\"span\" variant=\"text-caption\" emphasis color=\"on-strong\">\n {label}\n </ds-text>\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.copied ? 'Check' : 'Copy'}\n size=\"xs\"\n aria-label={this.copied ? 'Copied' : 'Copy code'}\n hasBorder={false}\n onDsClick={this.copy}\n />\n </figcaption>\n <pre>\n <code>{this.code}</code>\n </pre>\n </figure>\n </Host>\n );\n }\n}\n",
147
+ "content": "import { Component, h, Host, Prop, State } from '@stencil/core';\n\n@Component({\n tag: 'ds-code-block',\n styleUrl: 'CodeBlock.css',\n scoped: true,\n})\nexport class CodeBlock {\n @Prop() code: string = '';\n @Prop() language: string = '';\n @Prop() filename: string = '';\n\n @State() private copied: boolean = false;\n private copiedTimer?: ReturnType<typeof setTimeout>;\n\n disconnectedCallback() {\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n }\n\n private copy = async () => {\n if (!navigator.clipboard || !this.code) return;\n await navigator.clipboard.writeText(this.code);\n this.copied = true;\n if (this.copiedTimer) clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => {\n this.copied = false;\n }, 2000);\n };\n\n render() {\n const label = this.filename || this.language || 'Code';\n return (\n <Host>\n <figure class=\"code-block\">\n <figcaption class=\"code-block__header\">\n <ds-text as=\"span\" variant=\"text-caption\" emphasis color=\"on-strong\">\n {label}\n </ds-text>\n <ds-tooltip label={this.copied ? 'Copied' : 'Copy code'} side=\"bottom\" size=\"sm\">\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.copied ? 'Check' : 'Copy'}\n size=\"xs\"\n aria-label={this.copied ? 'Copied' : 'Copy code'}\n hasBorder={false}\n onDsClick={this.copy}\n />\n </ds-tooltip>\n </figcaption>\n <pre>\n <code>{this.code}</code>\n </pre>\n </figure>\n </Host>\n );\n }\n}\n",
147
148
  "type": "registry:ui"
148
149
  }
149
150
  ]