@ds-mo/ui 6.0.1 → 8.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 (195) hide show
  1. package/README.md +3 -3
  2. package/dist/.build-stamp +1 -1
  3. package/dist/agent.json +978 -147
  4. package/dist/angular/ds-button-filled.d.ts +1 -1
  5. package/dist/angular/ds-button-filled.js +3 -3
  6. package/dist/angular/ds-button-unfilled.d.ts +1 -1
  7. package/dist/angular/ds-button-unfilled.js +3 -3
  8. package/dist/angular/ds-chip.d.ts +1 -1
  9. package/dist/angular/ds-chip.js +3 -3
  10. package/dist/angular/ds-divider.d.ts +1 -1
  11. package/dist/angular/ds-divider.js +3 -3
  12. package/dist/angular/ds-icon.d.ts +1 -1
  13. package/dist/angular/ds-icon.js +3 -3
  14. package/dist/angular/ds-panel-sub-nav.d.ts +15 -0
  15. package/dist/angular/{ds-tab-group-nav.js → ds-panel-sub-nav.js} +13 -17
  16. package/dist/angular/ds-skeleton.d.ts +1 -1
  17. package/dist/angular/ds-skeleton.js +3 -3
  18. package/dist/angular/ds-tab-group.d.ts +1 -1
  19. package/dist/angular/ds-tab-group.js +3 -3
  20. package/dist/angular/ds-tag.d.ts +8 -2
  21. package/dist/angular/ds-tag.js +9 -5
  22. package/dist/angular/index.d.ts +1 -1
  23. package/dist/angular/index.js +1 -1
  24. package/dist/angular/proxies.d.ts +1 -1
  25. package/dist/angular/proxies.js +1 -1
  26. package/dist/components/ds-app-shell.js +1 -1
  27. package/dist/components/ds-app-shell.js.map +1 -1
  28. package/dist/components/ds-badge.js +1 -1
  29. package/dist/components/ds-banner.js +1 -1
  30. package/dist/components/ds-bar-nav.js +1 -1
  31. package/dist/components/ds-bar-nav.js.map +1 -1
  32. package/dist/components/ds-button-filled.js +1 -1
  33. package/dist/components/ds-button-unfilled.js +1 -1
  34. package/dist/components/ds-card-data-viz-donut.js +1 -1
  35. package/dist/components/ds-card-data-viz-donut.js.map +1 -1
  36. package/dist/components/ds-card-setting.js +1 -1
  37. package/dist/components/ds-card-setting.js.map +1 -1
  38. package/dist/components/ds-card.js +1 -1
  39. package/dist/components/ds-chart-bar.js +1 -1
  40. package/dist/components/ds-chart-donut.js +1 -1
  41. package/dist/components/ds-chart-legend.js +1 -1
  42. package/dist/components/ds-chart-legend.js.map +1 -1
  43. package/dist/components/ds-chart-line.js +1 -1
  44. package/dist/components/ds-checkbox.js +1 -1
  45. package/dist/components/ds-chip.js +1 -1
  46. package/dist/components/ds-chip.js.map +1 -1
  47. package/dist/components/ds-divider.js +1 -1
  48. package/dist/components/ds-divider.js.map +1 -1
  49. package/dist/components/ds-empty-state.js +1 -1
  50. package/dist/components/ds-field.js +1 -1
  51. package/dist/components/ds-icon.js +1 -1
  52. package/dist/components/ds-input.js +1 -1
  53. package/dist/components/ds-loader.js +1 -1
  54. package/dist/components/ds-loader.js.map +1 -1
  55. package/dist/components/ds-menu.js +1 -1
  56. package/dist/components/ds-modal.js +1 -1
  57. package/dist/components/ds-pagination.js +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-tab-group-nav.d.ts → ds-panel-sub-nav.d.ts} +4 -4
  61. package/dist/components/ds-panel-sub-nav.js +2 -0
  62. package/dist/components/ds-panel-sub-nav.js.map +1 -0
  63. package/dist/components/ds-panel-tools.js +1 -1
  64. package/dist/components/ds-panel-tools.js.map +1 -1
  65. package/dist/components/ds-radio-group.js +1 -1
  66. package/dist/components/ds-select.js +1 -1
  67. package/dist/components/ds-select.js.map +1 -1
  68. package/dist/components/ds-shell-gradient-picker.js +1 -1
  69. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  70. package/dist/components/ds-skeleton.js +1 -1
  71. package/dist/components/ds-slider.js +1 -1
  72. package/dist/components/ds-switch.js +1 -1
  73. package/dist/components/ds-tab-group.js +1 -1
  74. package/dist/components/ds-tab-group.js.map +1 -1
  75. package/dist/components/ds-table.js +1 -1
  76. package/dist/components/ds-tag.js +1 -1
  77. package/dist/components/ds-tag.js.map +1 -1
  78. package/dist/components/ds-text.js +1 -1
  79. package/dist/components/ds-tooltip-data-viz.js +1 -1
  80. package/dist/components/ds-tooltip.js +1 -1
  81. package/dist/components/{p-BmiNX9Mc.js → p-3bRWSqaN.js} +2 -2
  82. package/dist/components/p-B8ERbwc9.js +2 -0
  83. package/dist/components/{p-DhgDNluD.js.map → p-B8ERbwc9.js.map} +1 -1
  84. package/dist/components/p-BKhG2xrW.js.map +1 -1
  85. package/dist/components/p-BQq26pt9.js.map +1 -1
  86. package/dist/components/{p-bl7d1jB2.js → p-CPD_mML6.js} +2 -2
  87. package/dist/components/p-Ca1H1HPf.js +2 -0
  88. package/dist/components/p-Ca1H1HPf.js.map +1 -0
  89. package/dist/components/p-CpX87AQy.js +2 -0
  90. package/dist/components/p-CpX87AQy.js.map +1 -0
  91. package/dist/components/p-CyMmsNCF.js +2 -0
  92. package/dist/components/p-CyMmsNCF.js.map +1 -0
  93. package/dist/components/p-D0B9uDTP.js.map +1 -1
  94. package/dist/components/{p-DHwtgzjP.js → p-DavEAOUa.js} +2 -2
  95. package/dist/components/{p-DHwtgzjP.js.map → p-DavEAOUa.js.map} +1 -1
  96. package/dist/components/{p-9Qu1ls2y.js → p-DoZU8RH0.js} +2 -2
  97. package/dist/components/p-DoZU8RH0.js.map +1 -0
  98. package/dist/components/p-DsiueSMI.js +2 -0
  99. package/dist/components/p-DsiueSMI.js.map +1 -0
  100. package/dist/components/{p-CWd8L7Fk.js → p-Dt0XnMxc.js} +2 -2
  101. package/dist/components/p-Dt0XnMxc.js.map +1 -0
  102. package/dist/components/p-Mx6VFEQc.js +2 -0
  103. package/dist/components/p-Mx6VFEQc.js.map +1 -0
  104. package/dist/components/{p-RBe9XqjU.js → p-clDpFcdU.js} +2 -2
  105. package/dist/components/p-drBA73M_.js.map +1 -1
  106. package/dist/components/p-wxw8arTd.js +2 -0
  107. package/dist/components/p-wxw8arTd.js.map +1 -0
  108. package/dist/docs/components.json +878 -941
  109. package/dist/lib/components/Icon/icon-cache.d.ts +2 -2
  110. package/dist/lib/components/Text/text-types.d.ts +1 -1
  111. package/dist/lib/{nav → shell}/index.js +7 -7
  112. package/dist/lib/{nav → shell}/index.js.map +2 -2
  113. package/dist/lib/utils/index.js +1 -1
  114. package/dist/lib/utils/index.js.map +2 -2
  115. package/dist/react/components.d.ts +1 -1
  116. package/dist/react/components.js +1 -1
  117. package/dist/react/ds-panel-sub-nav.d.ts +12 -0
  118. package/dist/react/ds-panel-sub-nav.js +12 -0
  119. package/dist/react/ds-tag.d.ts +5 -2
  120. package/dist/react/ds-tag.js +1 -1
  121. package/dist/types/components/AppShell/AppShell.d.ts +2 -2
  122. package/dist/types/components/Badge/Badge.d.ts +4 -4
  123. package/dist/types/components/BarNav/BarNav.d.ts +11 -5
  124. package/dist/types/components/BarNav/index.d.ts +1 -1
  125. package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +3 -0
  126. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +5 -9
  127. package/dist/types/components/ButtonUnfilled/index.d.ts +1 -1
  128. package/dist/types/components/Chip/Chip.d.ts +0 -5
  129. package/dist/types/components/Chip/index.d.ts +1 -1
  130. package/dist/types/components/Divider/Divider.d.ts +3 -3
  131. package/dist/types/components/Divider/index.d.ts +1 -1
  132. package/dist/types/components/Icon/Icon.d.ts +2 -4
  133. package/dist/types/components/Icon/icon-cache.d.ts +2 -2
  134. package/dist/types/components/Loader/Loader.d.ts +1 -1
  135. package/dist/types/components/Menu/Menu.d.ts +1 -1
  136. package/dist/types/components/Menu/menu-types.d.ts +1 -1
  137. package/dist/types/components/PanelNav/PanelNav.d.ts +2 -2
  138. package/dist/types/components/PanelNav/index.d.ts +1 -1
  139. package/dist/types/components/PanelNav/panel-nav-types.d.ts +1 -2
  140. package/dist/types/components/PanelNav/panel-nav-utils.d.ts +2 -2
  141. package/dist/types/components/PanelSubNav/PanelSubNav.d.ts +27 -0
  142. package/dist/types/components/PanelSubNav/panel-sub-nav-types.d.ts +10 -0
  143. package/dist/types/components/PanelTools/PanelTools.d.ts +1 -1
  144. package/dist/types/components/ShellGradientSwatch/shell-gradient-swatch-types.d.ts +2 -2
  145. package/dist/types/components/Skeleton/Skeleton.d.ts +3 -3
  146. package/dist/types/components/Skeleton/index.d.ts +1 -1
  147. package/dist/types/components/TabGroup/TabGroup.d.ts +3 -4
  148. package/dist/types/components/TabGroup/tab-item-utils.d.ts +14 -0
  149. package/dist/types/components/Tag/Tag.d.ts +14 -0
  150. package/dist/types/components/Text/Text.d.ts +1 -1
  151. package/dist/types/components/Text/text-types.d.ts +1 -1
  152. package/dist/types/components.d.ts +242 -214
  153. package/package.json +7 -7
  154. package/dist/angular/ds-tab-group-nav.d.ts +0 -20
  155. package/dist/components/ds-tab-group-nav.js +0 -2
  156. package/dist/components/ds-tab-group-nav.js.map +0 -1
  157. package/dist/components/p-9Qu1ls2y.js.map +0 -1
  158. package/dist/components/p-B5kfuVQz.js +0 -2
  159. package/dist/components/p-B5kfuVQz.js.map +0 -1
  160. package/dist/components/p-BeIuJQO9.js +0 -2
  161. package/dist/components/p-BeIuJQO9.js.map +0 -1
  162. package/dist/components/p-CWd8L7Fk.js.map +0 -1
  163. package/dist/components/p-CxOQaZ4f.js +0 -2
  164. package/dist/components/p-CxOQaZ4f.js.map +0 -1
  165. package/dist/components/p-D5wc8lKR.js +0 -2
  166. package/dist/components/p-D5wc8lKR.js.map +0 -1
  167. package/dist/components/p-DPxfMUfH.js +0 -2
  168. package/dist/components/p-DPxfMUfH.js.map +0 -1
  169. package/dist/components/p-DhgDNluD.js +0 -2
  170. package/dist/components/p-cgo-rgl4.js +0 -2
  171. package/dist/components/p-cgo-rgl4.js.map +0 -1
  172. package/dist/react/ds-tab-group-nav.d.ts +0 -13
  173. package/dist/react/ds-tab-group-nav.js +0 -15
  174. package/dist/types/components/BarNav/bar-nav-dom-utils.d.ts +0 -11
  175. package/dist/types/components/TabGroupNav/TabGroupNav.d.ts +0 -46
  176. /package/dist/components/{p-BmiNX9Mc.js.map → p-3bRWSqaN.js.map} +0 -0
  177. /package/dist/components/{p-bl7d1jB2.js.map → p-CPD_mML6.js.map} +0 -0
  178. /package/dist/components/{p-RBe9XqjU.js.map → p-clDpFcdU.js.map} +0 -0
  179. /package/dist/lib/{nav → shell}/badge-gradient-ring.d.ts +0 -0
  180. /package/dist/lib/{nav → shell}/chrome-transition.d.ts +0 -0
  181. /package/dist/lib/{nav → shell}/index.d.ts +0 -0
  182. /package/dist/lib/{nav → shell}/nav-chrome.d.ts +0 -0
  183. /package/dist/lib/{nav → shell}/shell-chrome-metrics.d.ts +0 -0
  184. /package/dist/lib/{nav → shell}/shell-gradient-presets.d.ts +0 -0
  185. /package/dist/lib/{nav → shell}/shell-gradient.d.ts +0 -0
  186. /package/dist/lib/{nav → shell}/shell-view-transition.d.ts +0 -0
  187. /package/dist/types/{nav → shell}/badge-gradient-ring.d.ts +0 -0
  188. /package/dist/types/{nav → shell}/chrome-transition.d.ts +0 -0
  189. /package/dist/types/{nav → shell}/index.d.ts +0 -0
  190. /package/dist/types/{nav → shell}/nav-chrome.d.ts +0 -0
  191. /package/dist/types/{nav → shell}/shell-chrome-metrics.d.ts +0 -0
  192. /package/dist/types/{nav → shell}/shell-gradient-presets.d.ts +0 -0
  193. /package/dist/types/{nav → shell}/shell-gradient.d.ts +0 -0
  194. /package/dist/types/{nav → shell}/shell-shortcuts.d.ts +0 -0
  195. /package/dist/types/{nav → shell}/shell-view-transition.d.ts +0 -0
package/dist/agent.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
3
  "package": "@ds-mo/ui",
4
- "packageVersion": "6.0.1",
4
+ "packageVersion": "8.0.0",
5
5
  "kind": "components",
6
6
  "entries": [
7
7
  {
@@ -130,9 +130,83 @@
130
130
  "tag": "ds-badge",
131
131
  "name": "badge",
132
132
  "title": "Badge",
133
- "summary": "Compact counter or notification dot for status and unread indicators.",
134
- "intentStatus": "migration-pending",
135
- "intent": null,
133
+ "summary": "Non-interactive brand counter or dot that supplements an owning control or label with unread notification information.",
134
+ "intentStatus": "complete",
135
+ "intent": {
136
+ "audience": "general",
137
+ "status": "stable",
138
+ "summary": "Non-interactive brand counter or dot that supplements an owning control or label with unread notification information.",
139
+ "useWhen": [
140
+ "An existing control, navigation item, or label needs a compact unread notification count.",
141
+ "An owning element needs a small visual dot indicating that supplemental notification information exists.",
142
+ "The immediate backing surface can be identified so the badge ring visually separates the mark from its owner."
143
+ ],
144
+ "avoidWhen": [
145
+ "The status must stand alone without an owning label or control.",
146
+ "The mark needs semantic positive, caution, negative, or neutral color; Badge intentionally uses one brand treatment.",
147
+ "The compact content is metadata or taxonomy; use Tag or Chip according to whether it is removable.",
148
+ "The badge itself would receive pointer or keyboard interaction; put interaction on the owning control."
149
+ ],
150
+ "alternatives": [
151
+ {
152
+ "when": "A compact static label communicates taxonomy or a semantic status.",
153
+ "component": "component:ds-tag",
154
+ "reason": "Tag owns static metadata labels and semantic intent coloring."
155
+ },
156
+ {
157
+ "when": "A metadata value must be individually removable.",
158
+ "component": "component:ds-chip",
159
+ "reason": "Chip owns dismissible metadata values."
160
+ },
161
+ {
162
+ "when": "The count is primary content rather than supplemental notification chrome.",
163
+ "component": "component:ds-text",
164
+ "reason": "Text preserves the quantity as normal readable content."
165
+ }
166
+ ],
167
+ "commonlyComposedWith": [
168
+ "component:ds-button-unfilled",
169
+ "component:ds-bar-nav",
170
+ "component:ds-panel-nav",
171
+ "component:ds-menu"
172
+ ],
173
+ "accessibility": [
174
+ "The owning control or content provides the primary accessible name; Badge contributes only supplemental unread or notification meaning.",
175
+ "When a dot is announced, provide contextual text that explains its meaning. Otherwise mark it aria-hidden from the owning composition.",
176
+ "When a counter is announced, provide contextual text such as “5 unread notifications”; a bare number is insufficient.",
177
+ "Avoid duplicating information already included in the owning control's accessible name.",
178
+ "Badge never receives focus and never owns an interaction."
179
+ ],
180
+ "states": [
181
+ "Counter represents an unread or notification count, while dot communicates presence without quantity.",
182
+ "Non-positive counter values hide the badge.",
183
+ "Counts above the configured compact limit display the limit with a plus suffix while accessible text retains meaningful context.",
184
+ "Badge keeps one brand treatment; semantic severity belongs to another component or adjacent content.",
185
+ "The ring matches the immediate backing surface for both variants. Use a direct ring override only for a component-local fill that no surface preset represents.",
186
+ "Shell gradient rings align automatically inside active AppShell gradient chrome and may be explicitly enabled or disabled when composition requires it."
187
+ ],
188
+ "responsiveBehavior": [
189
+ "The owning control or layout positions Badge and decides whether notification indicators remain visible, condense, or move at responsive breakpoints.",
190
+ "Badge does not anchor itself or automatically switch between counter and dot variants."
191
+ ],
192
+ "frameworkCaveats": {
193
+ "customElements": [
194
+ "Position Badge from the owning element's layout and synchronize its contextual accessibility text with the owner."
195
+ ],
196
+ "react": [
197
+ "Keep count, visibility, and contextual accessibility text derived from the same unread-notification state as the owning control."
198
+ ],
199
+ "angular": [
200
+ "Keep count, visibility, and contextual accessibility text derived from the same unread-notification state as the owning control."
201
+ ]
202
+ },
203
+ "references": [
204
+ {
205
+ "label": "Storybook examples",
206
+ "path": "src/wc/components/Badge/Badge.stories.ts"
207
+ }
208
+ ]
209
+ },
136
210
  "api": {
137
211
  "props": {
138
212
  "background": {
@@ -290,7 +364,7 @@
290
364
  ],
291
365
  "accessibility": [
292
366
  "Use concise localized labels for every route section.",
293
- "Keep section navigation keyboard accessible through the generated TabGroupNav behavior and overflow menu.",
367
+ "Keep section navigation keyboard accessible through BarNav's built-in horizontal roving focus and overflow menu.",
294
368
  "Preserve the selected route state when sections move between the visible row and overflow menu.",
295
369
  "Use notification dots only as supplemental status and not as the sole indication of important information.",
296
370
  "Pass the active PanelNav destination label through heading whenever section tabs are absent or hidden."
@@ -393,9 +467,9 @@
393
467
  "@ds-mo/tokens"
394
468
  ],
395
469
  "componentDependencies": [
470
+ "badge",
396
471
  "button-unfilled",
397
472
  "menu",
398
- "tab-group-nav",
399
473
  "text"
400
474
  ]
401
475
  },
@@ -404,20 +478,23 @@
404
478
  "tag": "ds-button-filled",
405
479
  "name": "button-filled",
406
480
  "title": "ButtonFilled",
407
- "summary": "Emphasized command button for primary, confirming, or semantically important actions.",
481
+ "summary": "Highest-emphasis command button for the single primary action in a local decision area, with semantic consequence and async progress treatments.",
408
482
  "intentStatus": "complete",
409
483
  "intent": {
410
484
  "audience": "general",
411
485
  "status": "stable",
412
- "summary": "Emphasized command button for primary, confirming, or semantically important actions.",
486
+ "summary": "Highest-emphasis command button for the single primary action in a local decision area, with semantic consequence and async progress treatments.",
413
487
  "useWhen": [
414
- "The user initiates a primary or emphasized command.",
415
- "An action needs a semantic intent such as positive, negative, warning, or AI."
488
+ "The user initiates the single primary command in a local decision area.",
489
+ "An action's consequence requires a matching semantic treatment.",
490
+ "A standalone compact primary action needs an icon-only presentation with an explicit accessible name."
416
491
  ],
417
492
  "avoidWhen": [
493
+ "Another filled action already exists in the same local decision area.",
418
494
  "The action is unfilled icon-only shell or navigation chrome.",
419
495
  "The element represents navigation rather than a command.",
420
- "The content is a persistent selected state rather than an action."
496
+ "The content is a persistent selected state rather than an action.",
497
+ "A semantic color would be decorative or merely match the surrounding product area."
421
498
  ],
422
499
  "alternatives": [
423
500
  {
@@ -438,15 +515,31 @@
438
515
  "accessibility": [
439
516
  "Provide an explicit accessible name for icon-only buttons.",
440
517
  "Use inactive state only when the action must remain visible but unavailable.",
441
- "Do not encode the action meaning through color alone."
518
+ "Do not encode the action meaning through color alone.",
519
+ "Loading keeps the action's accessible name and exposes busy state; announce broader operation progress from the owning workflow when users need confirmation.",
520
+ "Use native submit behavior for form submission and handle the form submit event rather than submitting from the button click event."
442
521
  ],
443
522
  "states": [
444
- "Choose one primary filled action per local decision area when possible.",
445
- "Use semantic intent for meaning and contrast for emphasis; do not use contrast as a substitute for state."
523
+ "Use only one filled action per local decision area; render all secondary actions with ButtonUnfilled.",
524
+ "Choose brand or neutral for general commands. Reserve positive, negative, warning, and caution for matching action consequences, and AI, guide, or walkthrough for actions that enter those feature experiences.",
525
+ "Contrast serves both surface adaptation and hierarchy, but never permits a second filled action in the same decision area.",
526
+ "Loading prevents duplicate activation without applying inactive opacity.",
527
+ "Icon and icon-label loading replace the icon in place. Label-only loading centers the loader while preserving the button's measured width."
446
528
  ],
447
529
  "responsiveBehavior": [
448
530
  "Use fill width only when the parent layout calls for a full-width action, commonly on narrow form layouts."
449
531
  ],
532
+ "frameworkCaveats": {
533
+ "customElements": [
534
+ "For form submission, use the native submit type and listen to the form submit event; use dsClick for non-submit commands."
535
+ ],
536
+ "react": [
537
+ "Keep async state in the owner and pass it to the loading state until the command settles."
538
+ ],
539
+ "angular": [
540
+ "Keep async state in the owner and pass it to the loading state until the command settles."
541
+ ]
542
+ },
450
543
  "references": [
451
544
  {
452
545
  "label": "Storybook examples",
@@ -476,6 +569,10 @@
476
569
  "type": "boolean",
477
570
  "required": false
478
571
  },
572
+ "isLoading": {
573
+ "type": "boolean",
574
+ "required": false
575
+ },
479
576
  "label": {
480
577
  "type": "string",
481
578
  "required": false
@@ -517,6 +614,7 @@
517
614
  ],
518
615
  "componentDependencies": [
519
616
  "icon",
617
+ "loader",
520
618
  "text"
521
619
  ]
522
620
  },
@@ -525,9 +623,84 @@
525
623
  "tag": "ds-button-unfilled",
526
624
  "name": "button-unfilled",
527
625
  "title": "ButtonUnfilled",
528
- "summary": "Unfilled button with variant (label / icon / icon-label), control-density sizes, width hug/fill, active/border/dot, and surface-aware interaction states.",
529
- "intentStatus": "migration-pending",
530
- "intent": null,
626
+ "summary": "Secondary command and compact chrome button with optional persistent toggle state, surface-aware interaction treatment, and async progress.",
627
+ "intentStatus": "complete",
628
+ "intent": {
629
+ "audience": "general",
630
+ "status": "stable",
631
+ "summary": "Secondary command and compact chrome button with optional persistent toggle state, surface-aware interaction treatment, and async progress.",
632
+ "useWhen": [
633
+ "A secondary command accompanies the single filled primary action in a local decision area.",
634
+ "A toolbar, tool rail, overflow area, or shell region needs a compact icon action.",
635
+ "A command represents a persistent toggle or mode whose active state remains meaningful after activation."
636
+ ],
637
+ "avoidWhen": [
638
+ "The command is the single primary action in a local decision area; use ButtonFilled instead.",
639
+ "The control selects an application destination or local content panel; use the matching navigation component.",
640
+ "Active styling would only indicate the most recently invoked command or add decorative emphasis.",
641
+ "Surface context would be used to make the action louder or quieter rather than describe its actual parent surface."
642
+ ],
643
+ "alternatives": [
644
+ {
645
+ "when": "The command is the single primary action in the decision area.",
646
+ "component": "component:ds-button-filled",
647
+ "reason": "ButtonFilled owns highest-emphasis commands."
648
+ },
649
+ {
650
+ "when": "The choices are persistent application destinations.",
651
+ "component": "component:ds-panel-nav",
652
+ "reason": "PanelNav owns primary route selection and navigation semantics."
653
+ },
654
+ {
655
+ "when": "The choices are transient commands or contextual options.",
656
+ "component": "component:ds-menu",
657
+ "reason": "Menu owns temporary popup collections and their keyboard model."
658
+ }
659
+ ],
660
+ "commonlyComposedWith": [
661
+ "component:ds-button-filled",
662
+ "component:ds-menu",
663
+ "component:ds-panel-tools"
664
+ ],
665
+ "accessibility": [
666
+ "Provide an explicit accessible name for every icon-only action.",
667
+ "Use active state only for a persistent toggle or mode, and synchronize pressed semantics unless an owning composite exposes the selection state.",
668
+ "Treat notification dots as supplemental unread or status information; never use a dot as the sole state, meaning, or accessible name.",
669
+ "Loading keeps the action's accessible name and exposes busy state; announce broader operation progress from the owning workflow when needed.",
670
+ "Use inactive state only when an unavailable action must remain visible.",
671
+ "For form submission, use native submit behavior and handle the form submit event rather than submitting from the button click event."
672
+ ],
673
+ "states": [
674
+ "General content UI keeps the selected interaction fill and border for persistent active state.",
675
+ "Shell, navigation, and tool-rail chrome uses foreground-only active state with no selected fill or border.",
676
+ "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.",
677
+ "Surface context must match the actual parent surface; translucent, inverted, media, and always-dark treatments are reserved for those surfaces.",
678
+ "Loading prevents duplicate activation without applying inactive opacity.",
679
+ "Icon and icon-label loading replace the icon in place. Label-only loading centers the loader while preserving the button's measured width."
680
+ ],
681
+ "responsiveBehavior": [
682
+ "The consuming layout decides when an icon-label action becomes icon-only and must provide an explicit accessible name after changing variants.",
683
+ "Use fill width only when the parent layout requires a full-width secondary action."
684
+ ],
685
+ "frameworkCaveats": {
686
+ "customElements": [
687
+ "For form submission, use the native submit type and listen to the form submit event; use dsClick for non-submit commands.",
688
+ "Roving-focus composites own the button's tab-stop placement and selection semantics."
689
+ ],
690
+ "react": [
691
+ "Keep active, pressed, and async state synchronized from the owning toolbar or workflow."
692
+ ],
693
+ "angular": [
694
+ "Keep active, pressed, and async state synchronized from the owning toolbar or workflow."
695
+ ]
696
+ },
697
+ "references": [
698
+ {
699
+ "label": "Storybook examples",
700
+ "path": "src/wc/components/ButtonUnfilled/ButtonUnfilled.stories.ts"
701
+ }
702
+ ]
703
+ },
531
704
  "api": {
532
705
  "props": {
533
706
  "activeFill": {
@@ -542,10 +715,6 @@
542
715
  "type": "ButtonUnfilledBackground | undefined",
543
716
  "required": false
544
717
  },
545
- "backgroundContrast": {
546
- "type": "ButtonUnfilledOnBackgroundContrast",
547
- "required": false
548
- },
549
718
  "controls": {
550
719
  "type": "string | undefined",
551
720
  "required": false
@@ -582,6 +751,10 @@
582
751
  "type": "boolean",
583
752
  "required": false
584
753
  },
754
+ "isLoading": {
755
+ "type": "boolean",
756
+ "required": false
757
+ },
585
758
  "label": {
586
759
  "type": "string",
587
760
  "required": false
@@ -632,6 +805,7 @@
632
805
  "componentDependencies": [
633
806
  "badge",
634
807
  "icon",
808
+ "loader",
635
809
  "text"
636
810
  ]
637
811
  },
@@ -1058,15 +1232,81 @@
1058
1232
  "tag": "ds-chip",
1059
1233
  "name": "chip",
1060
1234
  "title": "Chip",
1061
- "summary": "Removable metadata chip same control-density recipe as Tag, colored by semantic state (default / active / error / caution). Not a toggle/select control.",
1062
- "intentStatus": "migration-pending",
1063
- "intent": null,
1235
+ "summary": "Always-removable metadata value for primary surfaces, with semantic value status and parent-owned removal.",
1236
+ "intentStatus": "complete",
1237
+ "intent": {
1238
+ "audience": "general",
1239
+ "status": "stable",
1240
+ "summary": "Always-removable metadata value for primary surfaces, with semantic value status and parent-owned removal.",
1241
+ "useWhen": [
1242
+ "A user-applied value such as a filter, recipient, or tokenized input entry must remain visible and individually removable.",
1243
+ "A compact metadata value needs a semantic neutral, active, error, or caution status before removal.",
1244
+ "A collection owner can remove the represented value and restore focus after the dismiss action."
1245
+ ],
1246
+ "avoidWhen": [
1247
+ "The label is static or not individually removable; use Tag instead.",
1248
+ "The control selects, toggles, or navigates; use the matching button or navigation component.",
1249
+ "The information is a persistent status, count, or unread indicator; use Badge or an appropriate status composition instead.",
1250
+ "The chip would be placed on any surface other than a primary surface."
1251
+ ],
1252
+ "alternatives": [
1253
+ {
1254
+ "when": "The metadata label is static and has no dismiss action.",
1255
+ "component": "component:ds-tag",
1256
+ "reason": "Tag owns non-interactive taxonomy and metadata labels."
1257
+ },
1258
+ {
1259
+ "when": "The compact mark communicates a count, status, or unread indicator.",
1260
+ "component": "component:ds-badge",
1261
+ "reason": "Badge owns supplemental counters and status marks without a dismiss action."
1262
+ },
1263
+ {
1264
+ "when": "The value is a selectable or persistent toggle.",
1265
+ "component": "component:ds-button-unfilled",
1266
+ "reason": "ButtonUnfilled owns command and toggle semantics."
1267
+ }
1268
+ ],
1269
+ "commonlyComposedWith": [
1270
+ "component:ds-input",
1271
+ "component:ds-select"
1272
+ ],
1273
+ "accessibility": [
1274
+ "Keep the visible label meaningful without relying on semantic color alone.",
1275
+ "Give the dismiss action a name that identifies the represented value.",
1276
+ "After removal, the parent moves focus to the next chip, then the previous chip, or the owning collection or input trigger when no chips remain.",
1277
+ "Inactive chips remain visible while their dismiss action is disabled and removed from keyboard interaction."
1278
+ ],
1279
+ "states": [
1280
+ "Semantic state describes the represented value; active does not mean selected or pressed.",
1281
+ "The dismiss action is the chip's only interaction, and the parent owns data mutation after dsRemove.",
1282
+ "Long labels remain on one line and truncate only when the consuming layout supplies a maximum width; otherwise the chip sizes to its content.",
1283
+ "Rounded shape is a visual choice and does not change semantics or interaction.",
1284
+ "Chip is designed only for primary surfaces and has no surface-context API."
1285
+ ],
1286
+ "responsiveBehavior": [
1287
+ "The parent chooses chip size and owns wrapping, overflow, and collection condensation.",
1288
+ "Chip does not automatically resize, hide, or collapse its label at responsive breakpoints."
1289
+ ],
1290
+ "frameworkCaveats": {
1291
+ "customElements": [
1292
+ "dsRemove has no payload; associate each rendered chip with its owning value and remove that value from the event handler."
1293
+ ],
1294
+ "react": [
1295
+ "Use the rendered chip's bound item context in the dsRemove handler, then restore focus after the collection rerenders."
1296
+ ],
1297
+ "angular": [
1298
+ "Use the rendered chip's bound item context in the dsRemove handler, then restore focus after the collection rerenders."
1299
+ ]
1300
+ },
1301
+ "references": [
1302
+ {
1303
+ "label": "Storybook examples",
1304
+ "path": "src/wc/components/Chip/Chip.stories.ts"
1305
+ }
1306
+ ]
1307
+ },
1064
1308
  "api": {
1065
1309
  "props": {
1066
- "background": {
1067
- "type": "ChipBackground | undefined",
1068
- "required": false
1069
- },
1070
1310
  "isInactive": {
1071
1311
  "type": "boolean",
1072
1312
  "required": false
@@ -1079,10 +1319,6 @@
1079
1319
  "type": "string | number | undefined",
1080
1320
  "required": false
1081
1321
  },
1082
- "removable": {
1083
- "type": "boolean",
1084
- "required": false
1085
- },
1086
1322
  "removeLabel": {
1087
1323
  "type": "string",
1088
1324
  "required": false
@@ -1128,11 +1364,80 @@
1128
1364
  "tag": "ds-divider",
1129
1365
  "name": "divider",
1130
1366
  "title": "Divider",
1131
- "summary": "Decorative horizontal or vertical visual separator for non-edge-to-edge separation. Supports surface-aware divider tokens, inset, and custom line length.",
1132
- "intentStatus": "migration-pending",
1133
- "intent": null,
1367
+ "summary": "Horizontal or vertical separator between sibling content groups, decorative by default with optional structural semantics.",
1368
+ "intentStatus": "complete",
1369
+ "intent": {
1370
+ "audience": "general",
1371
+ "status": "stable",
1372
+ "summary": "Horizontal or vertical separator between sibling content groups, decorative by default with optional structural semantics.",
1373
+ "useWhen": [
1374
+ "Related sibling content groups on one surface need stronger visual separation than spacing alone provides.",
1375
+ "A list or panel needs an inset separator that does not define the outer edge of its container.",
1376
+ "Meaningful document or group structure requires an explicit horizontal or vertical separator."
1377
+ ],
1378
+ "avoidWhen": [
1379
+ "Spacing alone communicates the grouping clearly.",
1380
+ "The line defines a container edge, control outline, or selected state; use the owning component's border treatment.",
1381
+ "The divider would compensate for weak headings or unclear information hierarchy.",
1382
+ "A decorative flourish does not clarify grouping."
1383
+ ],
1384
+ "alternatives": [
1385
+ {
1386
+ "when": "Content needs an enclosing surface and outer boundary.",
1387
+ "component": "component:ds-card",
1388
+ "reason": "Card owns container chrome, structure, and edge treatment."
1389
+ },
1390
+ {
1391
+ "when": "A static compact label is being used to name a group.",
1392
+ "component": "component:ds-text",
1393
+ "reason": "Text communicates hierarchy directly instead of relying on a line."
1394
+ }
1395
+ ],
1396
+ "commonlyComposedWith": [
1397
+ "component:ds-card",
1398
+ "component:ds-menu",
1399
+ "component:ds-panel-sub-nav"
1400
+ ],
1401
+ "accessibility": [
1402
+ "Keep purely visual dividers hidden from assistive technology.",
1403
+ "Expose separator semantics only when the line represents meaningful document or group structure.",
1404
+ "Semantic orientation must match the divider's visual orientation.",
1405
+ "Do not use a semantic divider as a substitute for headings, landmarks, or explicit group labels."
1406
+ ],
1407
+ "states": [
1408
+ "Horizontal and vertical variants separate sibling groups along the parent's layout axis.",
1409
+ "The omitted background context is for primary and secondary surfaces. Explicit faint documents a faint surface while using the same standard divider token.",
1410
+ "Other background contexts select their matching divider token, including navigation where Divider is composed inside app chrome.",
1411
+ "Inset is symmetric along the line axis. Explicit length is reserved for layout-specific separators; otherwise the line fills the available axis."
1412
+ ],
1413
+ "responsiveBehavior": [
1414
+ "The parent layout decides whether to change orientation, visibility, inset, or length at responsive breakpoints.",
1415
+ "Divider does not infer layout direction or hide itself responsively."
1416
+ ],
1417
+ "frameworkCaveats": {
1418
+ "customElements": [
1419
+ "Set semantic mode only from known document structure; presentation alone should remain hidden from assistive technology."
1420
+ ],
1421
+ "react": [
1422
+ "Derive orientation and visibility from the parent layout rather than viewport logic inside Divider."
1423
+ ],
1424
+ "angular": [
1425
+ "Derive orientation and visibility from the parent layout rather than viewport logic inside Divider."
1426
+ ]
1427
+ },
1428
+ "references": [
1429
+ {
1430
+ "label": "Storybook examples",
1431
+ "path": "src/wc/components/Divider/Divider.stories.ts"
1432
+ }
1433
+ ]
1434
+ },
1134
1435
  "api": {
1135
1436
  "props": {
1437
+ "background": {
1438
+ "type": "DividerBackground | undefined",
1439
+ "required": false
1440
+ },
1136
1441
  "inset": {
1137
1442
  "type": "DividerInset",
1138
1443
  "required": false
@@ -1148,10 +1453,6 @@
1148
1453
  "semantic": {
1149
1454
  "type": "boolean",
1150
1455
  "required": false
1151
- },
1152
- "surface": {
1153
- "type": "DividerSurface",
1154
- "required": false
1155
1456
  }
1156
1457
  },
1157
1458
  "events": [],
@@ -1247,17 +1548,90 @@
1247
1548
  "tag": "ds-icon",
1248
1549
  "name": "icon",
1249
1550
  "title": "Icon",
1250
- "summary": "Icon component from @ds-mo/ui.",
1251
- "intentStatus": "migration-pending",
1252
- "intent": null,
1551
+ "summary": "Secure, lazily loaded renderer for canonical IcoMo system and flag glyphs, decorative by default with optional graphic semantics.",
1552
+ "intentStatus": "complete",
1553
+ "intent": {
1554
+ "audience": "general",
1555
+ "status": "stable",
1556
+ "summary": "Secure, lazily loaded renderer for canonical IcoMo system and flag glyphs, decorative by default with optional graphic semantics.",
1557
+ "useWhen": [
1558
+ "An approved IcoMo system glyph supplements visible text or control chrome.",
1559
+ "A canonical flag glyph communicates a country or region with adjacent text or an explicit localized label.",
1560
+ "A standalone non-interactive symbol conveys meaning that is unavailable from nearby text."
1561
+ ],
1562
+ "avoidWhen": [
1563
+ "The glyph itself must be clickable or keyboard interactive; use an appropriate button or link and compose Icon inside it.",
1564
+ "The visual is an illustration, logo, chart, or arbitrary SVG artwork rather than a canonical IcoMo glyph.",
1565
+ "An alias, guessed name, or case-insensitive lookup would be required; runtime lookup uses exact canonical export names.",
1566
+ "A fallback glyph would be required when loading fails; Icon intentionally preserves an empty fixed-size box."
1567
+ ],
1568
+ "alternatives": [
1569
+ {
1570
+ "when": "The icon initiates an action or persistent toggle.",
1571
+ "component": "component:ds-button-unfilled",
1572
+ "reason": "ButtonUnfilled owns interaction, focus, naming, and toggle semantics."
1573
+ },
1574
+ {
1575
+ "when": "The visual communicates indeterminate loading progress.",
1576
+ "component": "component:ds-loader",
1577
+ "reason": "Loader owns progress status and motion behavior."
1578
+ },
1579
+ {
1580
+ "when": "The compact visual is an unread count or notification dot.",
1581
+ "component": "component:ds-badge",
1582
+ "reason": "Badge owns supplemental notification semantics."
1583
+ }
1584
+ ],
1585
+ "commonlyComposedWith": [
1586
+ "component:ds-button-filled",
1587
+ "component:ds-button-unfilled",
1588
+ "component:ds-menu",
1589
+ "component:ds-panel-nav"
1590
+ ],
1591
+ "accessibility": [
1592
+ "Icons are decorative by default and remain hidden from assistive technology when visible text or an owning control already communicates the meaning.",
1593
+ "The owning button, link, or composite control provides the accessible name; do not repeat that name on its nested Icon.",
1594
+ "Provide an explicit label only when the non-interactive icon itself communicates otherwise unavailable meaning.",
1595
+ "Informative flags require an explicit localized country or region label; never derive accessible text from the export name.",
1596
+ "Icon never receives focus or owns interaction."
1597
+ ],
1598
+ "states": [
1599
+ "Omitted color inherits currentColor from the owning context. Explicit semantic aliases and CSS-variable references are available when the icon has an independent color role.",
1600
+ "Built-in glyph lookup accepts exact canonical IcoMo export names only. Names beginning with Flag select the flag catalog automatically.",
1601
+ "A cache miss lazy-loads into a fixed-size box without layout shift. Unknown names, failed loads, and rejected markup leave that box empty.",
1602
+ "Critical first-paint glyphs may be pre-registered before rendering; all resolved glyphs share a global cache.",
1603
+ "Every SVG is validated at the render boundary and injected as parsed DOM nodes so app-registered markup cannot bypass executable-content or external-reference checks."
1604
+ ],
1605
+ "responsiveBehavior": [
1606
+ "The owning component or layout chooses icon size and any responsive changes.",
1607
+ "Icon does not scale from viewport width or change glyphs automatically."
1608
+ ],
1609
+ "frameworkCaveats": {
1610
+ "customElements": [
1611
+ "Import each canonical glyph as an SVG string and call registerIcons before first render when synchronous critical-icon paint is required."
1612
+ ],
1613
+ "react": [
1614
+ "Keep nested control icons decorative and place the accessible name on the owning React control."
1615
+ ],
1616
+ "angular": [
1617
+ "Keep nested control icons decorative and place the accessible name on the owning Angular control."
1618
+ ]
1619
+ },
1620
+ "references": [
1621
+ {
1622
+ "label": "Storybook examples",
1623
+ "path": "src/wc/components/Icon/Icon.stories.ts"
1624
+ },
1625
+ {
1626
+ "label": "Preload API guidance",
1627
+ "path": "src/wc/components/Icon/icon-cache.ts"
1628
+ }
1629
+ ]
1630
+ },
1253
1631
  "api": {
1254
1632
  "props": {
1255
1633
  "color": {
1256
- "type": "IconColor | undefined",
1257
- "required": false
1258
- },
1259
- "flag": {
1260
- "type": "boolean",
1634
+ "type": "IconColor",
1261
1635
  "required": false
1262
1636
  },
1263
1637
  "label": {
@@ -1393,16 +1767,82 @@
1393
1767
  "tag": "ds-loader",
1394
1768
  "name": "loader",
1395
1769
  "title": "Loader",
1396
- "summary": "Anti-clockwise SVG spinner matching ds-icon size/color tokens.",
1397
- "intentStatus": "migration-pending",
1398
- "intent": null,
1399
- "api": {
1400
- "props": {
1401
- "color": {
1402
- "type": "LoaderColor | undefined",
1403
- "required": false
1404
- },
1405
- "label": {
1770
+ "summary": "Indeterminate progress glyph for ongoing operations, inheriting owner color and optionally exposing standalone polite status text.",
1771
+ "intentStatus": "complete",
1772
+ "intent": {
1773
+ "audience": "general",
1774
+ "status": "stable",
1775
+ "summary": "Indeterminate progress glyph for ongoing operations, inheriting owner color and optionally exposing standalone polite status text.",
1776
+ "useWhen": [
1777
+ "An action or operation is in progress and its remaining duration cannot be quantified.",
1778
+ "A button, field, or bounded workflow needs a compact visual busy indicator owned by that control or region.",
1779
+ "A standalone operation needs a visible spinner with contextual polite status text."
1780
+ ],
1781
+ "avoidWhen": [
1782
+ "Pending content has a predictable structure; use Skeleton to preserve that layout.",
1783
+ "Progress is measurable; use an appropriate determinate progress pattern.",
1784
+ "The UI needs a blocking overlay or automatic centering; the owning layout must provide that structure.",
1785
+ "Success, failure, retry, or completion must be communicated; the owning workflow handles outcomes."
1786
+ ],
1787
+ "alternatives": [
1788
+ {
1789
+ "when": "A content region is waiting for structured data.",
1790
+ "component": "component:ds-skeleton",
1791
+ "reason": "Skeleton preserves the expected content geometry while data loads."
1792
+ },
1793
+ {
1794
+ "when": "A static visual symbol is needed without progress semantics.",
1795
+ "component": "component:ds-icon",
1796
+ "reason": "Icon owns non-progress system and flag glyphs."
1797
+ }
1798
+ ],
1799
+ "commonlyComposedWith": [
1800
+ "component:ds-button-filled",
1801
+ "component:ds-button-unfilled",
1802
+ "component:ds-input",
1803
+ "component:ds-select"
1804
+ ],
1805
+ "accessibility": [
1806
+ "When Loader is nested in a busy button, field, or region, keep it unnamed and expose busy state from the owner.",
1807
+ "Standalone Loader requires contextual status text that explains what is loading; do not rely on a generic visual spinner alone.",
1808
+ "Avoid duplicate announcements from both Loader and its owning busy region.",
1809
+ "Reduced motion stops rotation while keeping the glyph and status semantics visible."
1810
+ ],
1811
+ "states": [
1812
+ "Loader communicates indeterminate progress only and does not emit completion or failure events.",
1813
+ "Omitted color inherits currentColor. Explicit semantic aliases and CSS-variable references match Icon when an independent progress color is required.",
1814
+ "The owner decides whether to delay Loader visibility for short operations and removes it when the operation settles.",
1815
+ "The owner reserves space and supplies centering or overlay layout so Loader never causes unexpected layout movement."
1816
+ ],
1817
+ "responsiveBehavior": [
1818
+ "The owning component or layout chooses Loader size, placement, and any responsive changes.",
1819
+ "Loader does not infer container size or viewport breakpoints."
1820
+ ],
1821
+ "frameworkCaveats": {
1822
+ "customElements": [
1823
+ "Use the label only for standalone status; nested usage should synchronize aria-busy on the owning element."
1824
+ ],
1825
+ "react": [
1826
+ "Derive Loader visibility and the owner's busy state from the same operation state."
1827
+ ],
1828
+ "angular": [
1829
+ "Derive Loader visibility and the owner's busy state from the same operation state."
1830
+ ]
1831
+ },
1832
+ "references": [
1833
+ {
1834
+ "label": "Storybook examples",
1835
+ "path": "src/wc/components/Loader/Loader.stories.ts"
1836
+ }
1837
+ ]
1838
+ },
1839
+ "api": {
1840
+ "props": {
1841
+ "color": {
1842
+ "type": "LoaderColor",
1843
+ "required": false
1844
+ },
1845
+ "label": {
1406
1846
  "type": "string | undefined",
1407
1847
  "required": false
1408
1848
  },
@@ -1923,6 +2363,131 @@
1923
2363
  "tooltip"
1924
2364
  ]
1925
2365
  },
2366
+ {
2367
+ "id": "component:ds-panel-sub-nav",
2368
+ "tag": "ds-panel-sub-nav",
2369
+ "name": "panel-sub-nav",
2370
+ "title": "PanelSubNav",
2371
+ "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.",
2372
+ "intentStatus": "complete",
2373
+ "intent": {
2374
+ "audience": "general",
2375
+ "status": "stable",
2376
+ "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.",
2377
+ "useWhen": [
2378
+ "A panel or card side rail needs a persistent vertical list that switches adjacent local content.",
2379
+ "Each concise text label controls an immediately available tabpanel without changing application routes."
2380
+ ],
2381
+ "avoidWhen": [
2382
+ "The navigation is not contained in a panel or card side rail.",
2383
+ "Local views should be arranged horizontally; use TabGroup instead.",
2384
+ "The choices navigate routes in application shell chrome; use PanelNav or BarNav instead.",
2385
+ "The choices are temporary commands or contextual options; use Menu instead.",
2386
+ "Rows need icons, subtext, notification dots, nested levels, or section headers."
2387
+ ],
2388
+ "alternatives": [
2389
+ {
2390
+ "when": "Local panel choices fit a horizontal tab row.",
2391
+ "component": "component:ds-tab-group",
2392
+ "reason": "TabGroup is the horizontal local-view counterpart."
2393
+ },
2394
+ {
2395
+ "when": "The choices are primary application destinations.",
2396
+ "component": "component:ds-panel-nav",
2397
+ "reason": "PanelNav owns primary application navigation."
2398
+ },
2399
+ {
2400
+ "when": "The choices are secondary application routes.",
2401
+ "component": "component:ds-bar-nav",
2402
+ "reason": "BarNav owns route sections inside AppShell."
2403
+ },
2404
+ {
2405
+ "when": "The choices are transient actions or options.",
2406
+ "component": "component:ds-menu",
2407
+ "reason": "Menu owns temporary popup collections."
2408
+ }
2409
+ ],
2410
+ "commonlyComposedWith": [
2411
+ "component:ds-card",
2412
+ "component:ds-text"
2413
+ ],
2414
+ "accessibility": [
2415
+ "Provide an accessible name with aria-label or aria-labelledby.",
2416
+ "Give every item a unique id and the id of its controlled tabpanel.",
2417
+ "Keep each controlled tabpanel labelled by its matching item id.",
2418
+ "Always provide a valid selected item when enabled items exist so exactly one tab and panel are active.",
2419
+ "ArrowUp and ArrowDown move and activate selection; Home and End select the first and last available items.",
2420
+ "Do not use selected text weight as the selection cue; active fill and primary foreground communicate selection."
2421
+ ],
2422
+ "states": [
2423
+ "The parent owns the canonical selected value and panel visibility, and should update both from dsChange.",
2424
+ "A missing, empty, or unknown selected value is invalid when enabled items exist; the component does not choose a fallback selection.",
2425
+ "Inactive items remain visible but cannot be focused or selected.",
2426
+ "Selection is singular and follows keyboard focus.",
2427
+ "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.",
2428
+ "Rows contain one text label only and do not express nested navigation or grouped hierarchy."
2429
+ ],
2430
+ "responsiveBehavior": [
2431
+ "The component remains vertical at every width.",
2432
+ "The consuming panel owns responsive adaptation and decides whether to reposition or replace the side rail."
2433
+ ],
2434
+ "frameworkCaveats": {
2435
+ "customElements": [
2436
+ "Assign items as a JavaScript property because structured arrays are not represented by HTML attributes.",
2437
+ "Keep value synchronized to a valid enabled item and update the controlled panel from dsChange."
2438
+ ],
2439
+ "react": [
2440
+ "Pass items as an array through the generated wrapper, keep value controlled, and use onDsChange to synchronize the visible panel."
2441
+ ],
2442
+ "angular": [
2443
+ "Bind items and a valid value as properties, and handle dsChange to synchronize the visible panel."
2444
+ ]
2445
+ }
2446
+ },
2447
+ "api": {
2448
+ "props": {
2449
+ "ariaLabel": {
2450
+ "type": "string | null",
2451
+ "required": false
2452
+ },
2453
+ "ariaLabelledby": {
2454
+ "type": "string | undefined",
2455
+ "required": false
2456
+ },
2457
+ "background": {
2458
+ "type": "PanelSubNavBackground | undefined",
2459
+ "required": false
2460
+ },
2461
+ "items": {
2462
+ "type": "PanelSubNavItem[]",
2463
+ "required": false
2464
+ },
2465
+ "value": {
2466
+ "type": "string",
2467
+ "required": false
2468
+ }
2469
+ },
2470
+ "events": [
2471
+ {
2472
+ "name": "dsChange",
2473
+ "detail": "string"
2474
+ }
2475
+ ],
2476
+ "slots": []
2477
+ },
2478
+ "exports": {
2479
+ "customElement": "ds-panel-sub-nav",
2480
+ "react": "DsPanelSubNav",
2481
+ "angular": "DsPanelSubNav"
2482
+ },
2483
+ "dependencies": [
2484
+ "@ds-mo/ui",
2485
+ "@ds-mo/tokens"
2486
+ ],
2487
+ "componentDependencies": [
2488
+ "text"
2489
+ ]
2490
+ },
1926
2491
  {
1927
2492
  "id": "component:ds-panel-tools",
1928
2493
  "tag": "ds-panel-tools",
@@ -2465,11 +3030,88 @@
2465
3030
  "tag": "ds-skeleton",
2466
3031
  "name": "skeleton",
2467
3032
  "title": "Skeleton",
2468
- "summary": "Atomic loading placeholder with token-aligned text, icon, and control canvases. Supports optional shimmer, circular icons, and rounded controls.",
2469
- "intentStatus": "migration-pending",
2470
- "intent": null,
3033
+ "summary": "Aria-hidden atomic placeholder for preserving expected text, icon, or control geometry while structured content is pending.",
3034
+ "intentStatus": "complete",
3035
+ "intent": {
3036
+ "audience": "general",
3037
+ "status": "stable",
3038
+ "summary": "Aria-hidden atomic placeholder for preserving expected text, icon, or control geometry while structured content is pending.",
3039
+ "useWhen": [
3040
+ "A pending content region has a predictable structure whose geometry should remain stable while data loads.",
3041
+ "Text, icon, and control placeholder atoms can be composed to approximate the final hierarchy and arrangement.",
3042
+ "The owning region can expose busy state and contextual loading status independently."
3043
+ ],
3044
+ "avoidWhen": [
3045
+ "An action or operation is progressing without predictable content structure; use Loader.",
3046
+ "The final layout is unknown or likely to differ substantially from the placeholder composition.",
3047
+ "A complete card, list, or table preset is expected from one Skeleton; compose atomic shapes in the owner.",
3048
+ "The shimmer would be used as decoration after content is available."
3049
+ ],
3050
+ "alternatives": [
3051
+ {
3052
+ "when": "An indeterminate action or operation is in progress.",
3053
+ "component": "component:ds-loader",
3054
+ "reason": "Loader owns operation-level indeterminate progress."
3055
+ },
3056
+ {
3057
+ "when": "Real text content is already available.",
3058
+ "component": "component:ds-text",
3059
+ "reason": "Text should replace its placeholder as soon as content is ready."
3060
+ },
3061
+ {
3062
+ "when": "A real system glyph is available.",
3063
+ "component": "component:ds-icon",
3064
+ "reason": "Icon renders actual glyph content rather than loading geometry."
3065
+ }
3066
+ ],
3067
+ "commonlyComposedWith": [
3068
+ "component:ds-card",
3069
+ "component:ds-table",
3070
+ "component:ds-text",
3071
+ "component:ds-icon"
3072
+ ],
3073
+ "accessibility": [
3074
+ "Skeleton remains hidden from assistive technology because its shapes do not represent content.",
3075
+ "The owning content region exposes busy state and a contextual loading status when an announcement is needed.",
3076
+ "Do not announce every placeholder atom or duplicate status text across a composed skeleton layout.",
3077
+ "The owner preserves focus and meaningful reading order when replacing placeholders with real content."
3078
+ ],
3079
+ "states": [
3080
+ "Text, icon, and control variants are atomic metric canvases aligned to their corresponding design-system recipes.",
3081
+ "Compose approximate line count, hierarchy, widths, and control placement without simulating actual values.",
3082
+ "Shimmer is on by default and may be disabled for a static placeholder. Reduced motion always produces the static final shape.",
3083
+ "Rounded is an optional visual treatment for icon and control atoms rather than a semantic state.",
3084
+ "Omitted background is for primary and secondary surfaces. Explicit faint documents a faint parent while using the same standard base and shimmer tokens; other contexts use matching surface tokens.",
3085
+ "The owner decides whether to delay initial visibility and when to replace the complete composition."
3086
+ ],
3087
+ "responsiveBehavior": [
3088
+ "The owning layout changes placeholder count, width, visibility, and arrangement to match its real responsive content.",
3089
+ "Skeleton does not infer breakpoints or rearrange sibling atoms."
3090
+ ],
3091
+ "frameworkCaveats": {
3092
+ "customElements": [
3093
+ "Compose one element per placeholder atom and set aria-busy or loading status on the containing content region."
3094
+ ],
3095
+ "react": [
3096
+ "Render Skeleton and real content from one loading branch so placeholder geometry and region busy state settle together."
3097
+ ],
3098
+ "angular": [
3099
+ "Render Skeleton and real content from one loading branch so placeholder geometry and region busy state settle together."
3100
+ ]
3101
+ },
3102
+ "references": [
3103
+ {
3104
+ "label": "Storybook examples",
3105
+ "path": "src/wc/components/Skeleton/Skeleton.stories.ts"
3106
+ }
3107
+ ]
3108
+ },
2471
3109
  "api": {
2472
3110
  "props": {
3111
+ "background": {
3112
+ "type": "SkeletonBackground | undefined",
3113
+ "required": false
3114
+ },
2473
3115
  "controlSize": {
2474
3116
  "type": "ControlSize",
2475
3117
  "required": false
@@ -2486,10 +3128,6 @@
2486
3128
  "type": "boolean",
2487
3129
  "required": false
2488
3130
  },
2489
- "surface": {
2490
- "type": "SkeletonSurface",
2491
- "required": false
2492
- },
2493
3131
  "textVariant": {
2494
3132
  "type": "TextVariant",
2495
3133
  "required": false
@@ -2738,66 +3376,91 @@
2738
3376
  "tag": "ds-tab-group",
2739
3377
  "name": "tab-group",
2740
3378
  "title": "TabGroup",
2741
- "summary": "Horizontal or vertical tab list with roving keyboard focus and optional dividers between tab groups.",
2742
- "intentStatus": "migration-pending",
2743
- "intent": null,
2744
- "api": {
2745
- "props": {
2746
- "ariaLabel": {
2747
- "type": "string | null",
2748
- "required": false
2749
- },
2750
- "ariaLabelledby": {
2751
- "type": "string | undefined",
2752
- "required": false
2753
- },
2754
- "background": {
2755
- "type": "TabBackground | undefined",
2756
- "required": false
3379
+ "summary": "Horizontal single-selection tabs for switching adjacent local views or view modes, with uniform label, icon, or icon-label presentation and surface-aware selection.",
3380
+ "intentStatus": "complete",
3381
+ "intent": {
3382
+ "audience": "general",
3383
+ "status": "stable",
3384
+ "summary": "Horizontal single-selection tabs for switching adjacent local views or view modes, with uniform label, icon, or icon-label presentation and surface-aware selection.",
3385
+ "useWhen": [
3386
+ "Adjacent local content views or panels fit in a horizontal tab row.",
3387
+ "A compact horizontal selector switches between equivalent local view modes such as list and grid.",
3388
+ "A tab set needs concise labels, icons, or icon-label content with optional supplemental notification dots."
3389
+ ],
3390
+ "avoidWhen": [
3391
+ "The choices navigate application routes; use PanelNav or BarNav instead.",
3392
+ "The choices belong in a vertical panel or card side rail; use PanelSubNav instead.",
3393
+ "The choices are temporary commands or contextual options; use Menu instead.",
3394
+ "The row requires mixed content variants, subtext, nested levels, or multi-row wrapping.",
3395
+ "No enabled tab can remain selected while enabled choices exist."
3396
+ ],
3397
+ "alternatives": [
3398
+ {
3399
+ "when": "Local views need persistent vertical side-rail navigation.",
3400
+ "component": "component:ds-panel-sub-nav",
3401
+ "reason": "PanelSubNav owns the vertical local-view keyboard and selection model."
2757
3402
  },
2758
- "orientation": {
2759
- "type": "'horizontal' | 'vertical'",
2760
- "required": false
3403
+ {
3404
+ "when": "The choices are primary application destinations.",
3405
+ "component": "component:ds-panel-nav",
3406
+ "reason": "PanelNav owns application route selection in shell navigation."
2761
3407
  },
2762
- "tabs": {
2763
- "type": "TabItem[]",
2764
- "required": false
3408
+ {
3409
+ "when": "The choices are secondary application route sections.",
3410
+ "component": "component:ds-bar-nav",
3411
+ "reason": "BarNav owns route sections, overflow, and shell coordination."
2765
3412
  },
2766
- "value": {
2767
- "type": "string",
2768
- "required": false
3413
+ {
3414
+ "when": "The choices are transient actions or options.",
3415
+ "component": "component:ds-menu",
3416
+ "reason": "Menu owns temporary popup collections rather than persistent local views."
2769
3417
  }
3418
+ ],
3419
+ "commonlyComposedWith": [
3420
+ "component:ds-text",
3421
+ "component:ds-icon"
3422
+ ],
3423
+ "accessibility": [
3424
+ "Provide an accessible tab-list name with aria-label or aria-labelledby.",
3425
+ "Keep exactly one valid enabled tab selected whenever enabled tabs exist, and keep its controlled view synchronized.",
3426
+ "When tabs control tabpanels, give each tab the id of its panel and label each panel from its tab.",
3427
+ "ArrowLeft and ArrowRight move and activate selection; Home and End select the first and last available tabs.",
3428
+ "Icon-only tabs retain their required text label as the accessible name even though the label is not visible.",
3429
+ "Notification dots are supplemental status only and must never replace a label, state, or accessible name.",
3430
+ "Inactive tabs remain visible but cannot be focused or selected."
3431
+ ],
3432
+ "states": [
3433
+ "The parent owns the canonical selected value and adjacent view visibility, and should update both from dsChange.",
3434
+ "A missing, empty, inactive, or unknown selected value is invalid when enabled tabs exist; the component does not choose a fallback selection.",
3435
+ "Selection is singular and follows keyboard focus.",
3436
+ "Use one consistent content variant across every selectable tab in a group.",
3437
+ "Omitted background is for primary and secondary surfaces; pass the faint context explicitly on faint surfaces.",
3438
+ "Only the omitted default context emphasizes visible selected label text and keeps the filled track; explicit faint follows the other surface contexts with a transparent track, stable text weight, surface border, and neutral active fill.",
3439
+ "Dividers visually separate related subsets inside one tab list but do not create nested navigation or independent selection groups."
3440
+ ],
3441
+ "responsiveBehavior": [
3442
+ "The component remains a single horizontal row and does not become vertical or wrap.",
3443
+ "The consuming layout owns narrow-width placement and overflow, or replaces the row with a more suitable navigation pattern."
3444
+ ],
3445
+ "frameworkCaveats": {
3446
+ "customElements": [
3447
+ "Assign tabs as a JavaScript property because structured arrays are not represented by HTML attributes.",
3448
+ "Use one item variant consistently, keep value synchronized to an enabled item, and update controlled content from dsChange."
3449
+ ],
3450
+ "react": [
3451
+ "Pass tabs as an array through the generated wrapper, keep value controlled, and use onDsChange to synchronize the visible view."
3452
+ ],
3453
+ "angular": [
3454
+ "Bind tabs and a valid value as properties, and handle dsChange to synchronize the visible view."
3455
+ ]
2770
3456
  },
2771
- "events": [
3457
+ "references": [
2772
3458
  {
2773
- "name": "dsChange",
2774
- "detail": "string"
3459
+ "label": "Storybook examples",
3460
+ "path": "src/wc/components/TabGroup/TabGroup.stories.ts"
2775
3461
  }
2776
- ],
2777
- "slots": []
2778
- },
2779
- "exports": {
2780
- "customElement": "ds-tab-group",
2781
- "react": "DsTabGroup",
2782
- "angular": "DsTabGroup"
3462
+ ]
2783
3463
  },
2784
- "dependencies": [
2785
- "@ds-mo/ui",
2786
- "@ds-mo/tokens"
2787
- ],
2788
- "componentDependencies": [
2789
- "badge",
2790
- "text"
2791
- ]
2792
- },
2793
- {
2794
- "id": "component:ds-tab-group-nav",
2795
- "tag": "ds-tab-group-nav",
2796
- "name": "tab-group-nav",
2797
- "title": "TabGroupNav",
2798
- "summary": "Navigation-style tab list for primary and secondary navigation surfaces.",
2799
- "intentStatus": "migration-pending",
2800
- "intent": null,
2801
3464
  "api": {
2802
3465
  "props": {
2803
3466
  "ariaLabel": {
@@ -2809,23 +3472,11 @@
2809
3472
  "required": false
2810
3473
  },
2811
3474
  "background": {
2812
- "type": "TabGroupNavBackground | undefined",
2813
- "required": false
2814
- },
2815
- "orientation": {
2816
- "type": "'horizontal' | 'vertical'",
2817
- "required": false
2818
- },
2819
- "rovingEnabled": {
2820
- "type": "boolean",
2821
- "required": false
2822
- },
2823
- "selectionFollowsFocus": {
2824
- "type": "boolean",
3475
+ "type": "TabBackground | undefined",
2825
3476
  "required": false
2826
3477
  },
2827
3478
  "tabs": {
2828
- "type": "TabItem[]",
3479
+ "type": "TabGroupItem[]",
2829
3480
  "required": false
2830
3481
  },
2831
3482
  "value": {
@@ -2837,25 +3488,23 @@
2837
3488
  {
2838
3489
  "name": "dsChange",
2839
3490
  "detail": "string"
2840
- },
2841
- {
2842
- "name": "dsRovingExit",
2843
- "detail": "'start' | 'end'"
2844
3491
  }
2845
3492
  ],
2846
3493
  "slots": []
2847
3494
  },
2848
3495
  "exports": {
2849
- "customElement": "ds-tab-group-nav",
2850
- "react": "DsTabGroupNav",
2851
- "angular": "DsTabGroupNav"
3496
+ "customElement": "ds-tab-group",
3497
+ "react": "DsTabGroup",
3498
+ "angular": "DsTabGroup"
2852
3499
  },
2853
3500
  "dependencies": [
2854
3501
  "@ds-mo/ui",
2855
- "@ds-mo/tokens"
3502
+ "@ds-mo/tokens",
3503
+ "@ds-mo/icons"
2856
3504
  ],
2857
3505
  "componentDependencies": [
2858
3506
  "badge",
3507
+ "icon",
2859
3508
  "text"
2860
3509
  ]
2861
3510
  },
@@ -2957,19 +3606,117 @@
2957
3606
  "tag": "ds-tag",
2958
3607
  "name": "tag",
2959
3608
  "title": "Tag",
2960
- "summary": "Static metadata label with intent coloring and optional icon support. Uses control-density recipes for md/sm/xs.",
2961
- "intentStatus": "migration-pending",
2962
- "intent": null,
3609
+ "summary": "Compact metadata or semantic-status label on primary surfaces, optionally rendered as a controlled menu trigger with leading and fixed suffix icons.",
3610
+ "intentStatus": "complete",
3611
+ "intent": {
3612
+ "audience": "general",
3613
+ "status": "stable",
3614
+ "summary": "Compact metadata or semantic-status label on primary surfaces, optionally rendered as a controlled menu trigger with leading and fixed suffix icons.",
3615
+ "useWhen": [
3616
+ "A value needs a compact static metadata or category label.",
3617
+ "A status needs persistent semantic color and visible text without interaction.",
3618
+ "Product affiliation or AI-generated content needs an explicit labelled marker.",
3619
+ "A compact metadata value opens a related menu and needs a native button with controlled popup state."
3620
+ ],
3621
+ "avoidWhen": [
3622
+ "The value must be individually removable; use Chip.",
3623
+ "The element triggers an action other than opening a related menu; use the appropriate button or link.",
3624
+ "The element represents persistent selection or a toggle; use a control whose active state owns that meaning.",
3625
+ "A count or notification dot supplements another control; use Badge.",
3626
+ "The tag would be placed on a non-primary parent surface."
3627
+ ],
3628
+ "alternatives": [
3629
+ {
3630
+ "when": "A metadata value is individually removable.",
3631
+ "component": "component:ds-chip",
3632
+ "reason": "Chip owns dismiss interaction and parent-managed removal."
3633
+ },
3634
+ {
3635
+ "when": "A compact mark communicates unread count or notification presence.",
3636
+ "component": "component:ds-badge",
3637
+ "reason": "Badge owns supplemental notification indicators."
3638
+ },
3639
+ {
3640
+ "when": "The compact element triggers a non-menu action or toggle.",
3641
+ "component": "component:ds-button-unfilled",
3642
+ "reason": "ButtonUnfilled owns general actions, focus, and active state."
3643
+ }
3644
+ ],
3645
+ "commonlyComposedWith": [
3646
+ "component:ds-card",
3647
+ "component:ds-table",
3648
+ "component:ds-text",
3649
+ "component:ds-icon"
3650
+ ],
3651
+ "accessibility": [
3652
+ "The visible label provides Tag's accessible name; a separate aria-label is normally unnecessary.",
3653
+ "Leading icons reinforce the visible label and remain decorative. The fixed ChevronUpDown suffix is always decorative.",
3654
+ "Static Tag stays outside the tab order. Interactive Tag renders a native button with menu popup semantics.",
3655
+ "The owner controls expanded state, associates the menu with aria-controls when available, and moves focus according to the Menu contract.",
3656
+ "Do not communicate semantic intent by color alone; the label must remain understandable without color."
3657
+ ],
3658
+ "states": [
3659
+ "Intent describes the represented value's semantic meaning, never selection or interaction state.",
3660
+ "Neutral is ordinary metadata; brand marks Motive or product affiliation; AI marks AI-generated or AI-assisted content; positive, caution, warning, and negative communicate increasingly specific status meaning.",
3661
+ "Warning signals higher urgency or risk than caution, which asks for attention before a possible issue.",
3662
+ "Contrast changes visual prominence without changing semantic intent or parent surface context.",
3663
+ "Rounded is an optional visual style with no semantic difference.",
3664
+ "Labels stay on one line and truncate only when the owner supplies a maximum width.",
3665
+ "Omitted interactive renders static metadata with no focus, event, or suffix. Interactive adds the fixed ChevronUpDown suffix and emits dsClick without toggling expanded internally.",
3666
+ "isInactive disables only the interactive button and applies the shared inactive treatment."
3667
+ ],
3668
+ "responsiveBehavior": [
3669
+ "The owner selects md, sm, or xs density to match its local layout and owns collection wrapping, overflow, and condensation.",
3670
+ "Tag does not change size or behavior automatically at breakpoints."
3671
+ ],
3672
+ "frameworkCaveats": {
3673
+ "customElements": [
3674
+ "Listen for dsClick to open the associated menu, then update expanded as controlled state. Use the Tag host ID as the menu anchor when required."
3675
+ ],
3676
+ "react": [
3677
+ "Use a stable key and parent-owned layout for Tag collections. For interactive Tag, synchronize expanded and the associated menu from the same state."
3678
+ ],
3679
+ "angular": [
3680
+ "Use parent-owned layout for Tag collections. For interactive Tag, synchronize expanded and the associated menu from the same state."
3681
+ ]
3682
+ },
3683
+ "references": [
3684
+ {
3685
+ "label": "Storybook examples",
3686
+ "path": "src/wc/components/Tag/Tag.stories.ts"
3687
+ }
3688
+ ]
3689
+ },
2963
3690
  "api": {
2964
3691
  "props": {
3692
+ "ariaControls": {
3693
+ "type": "string | undefined",
3694
+ "required": false
3695
+ },
2965
3696
  "contrast": {
2966
3697
  "type": "TagContrast",
2967
3698
  "required": false
2968
3699
  },
3700
+ "expanded": {
3701
+ "type": "boolean",
3702
+ "required": false
3703
+ },
3704
+ "icon": {
3705
+ "type": "string",
3706
+ "required": false
3707
+ },
2969
3708
  "intent": {
2970
3709
  "type": "TagIntent",
2971
3710
  "required": false
2972
3711
  },
3712
+ "interactive": {
3713
+ "type": "boolean",
3714
+ "required": false
3715
+ },
3716
+ "isInactive": {
3717
+ "type": "boolean",
3718
+ "required": false
3719
+ },
2973
3720
  "label": {
2974
3721
  "type": "string",
2975
3722
  "required": true
@@ -2987,7 +3734,12 @@
2987
3734
  "required": false
2988
3735
  }
2989
3736
  },
2990
- "events": [],
3737
+ "events": [
3738
+ {
3739
+ "name": "dsClick",
3740
+ "detail": "MouseEvent"
3741
+ }
3742
+ ],
2991
3743
  "slots": []
2992
3744
  },
2993
3745
  "exports": {
@@ -2997,9 +3749,11 @@
2997
3749
  },
2998
3750
  "dependencies": [
2999
3751
  "@ds-mo/ui",
3000
- "@ds-mo/tokens"
3752
+ "@ds-mo/tokens",
3753
+ "@ds-mo/icons"
3001
3754
  ],
3002
3755
  "componentDependencies": [
3756
+ "icon",
3003
3757
  "text"
3004
3758
  ]
3005
3759
  },
@@ -3008,9 +3762,86 @@
3008
3762
  "tag": "ds-text",
3009
3763
  "name": "text",
3010
3764
  "title": "Text",
3011
- "summary": "Typography primitive supporting all design-system text variants, colors, truncation, wrapping, and optional loading shimmer.",
3012
- "intentStatus": "migration-pending",
3013
- "intent": null,
3765
+ "summary": "Semantic plain UI text with atomic tokenized typography recipes, measurable line boxes, and composition-owned wrapping and truncation.",
3766
+ "intentStatus": "complete",
3767
+ "intent": {
3768
+ "audience": "general",
3769
+ "status": "stable",
3770
+ "summary": "Semantic plain UI text with atomic tokenized typography recipes, measurable line boxes, and composition-owned wrapping and truncation.",
3771
+ "useWhen": [
3772
+ "Plain UI text needs a complete design-system typography recipe.",
3773
+ "Headings, paragraphs, labels, or inline phrasing need native HTML semantics independent from their visual scale.",
3774
+ "A component needs a stable measurable text box aligned to shared typography metrics.",
3775
+ "Changing numeric values need tabular glyph widths."
3776
+ ],
3777
+ "avoidWhen": [
3778
+ "Content is markdown, rich prose, or an arbitrary nested document structure.",
3779
+ "The element is interactive; use the correct native or design-system control and compose Text only for its label.",
3780
+ "Individual font metrics must be overridden instead of selecting an existing complete variant.",
3781
+ "Typography alone would be used to repair an incorrect heading hierarchy."
3782
+ ],
3783
+ "alternatives": [
3784
+ {
3785
+ "when": "Predictable text geometry is pending while content loads.",
3786
+ "component": "component:ds-skeleton",
3787
+ "reason": "Skeleton owns aria-hidden loading geometry aligned to Text line metrics."
3788
+ },
3789
+ {
3790
+ "when": "Compact static metadata or semantic status needs a contained treatment.",
3791
+ "component": "component:ds-tag",
3792
+ "reason": "Tag owns compact labelled metadata and intent surfaces."
3793
+ }
3794
+ ],
3795
+ "commonlyComposedWith": [
3796
+ "component:ds-icon",
3797
+ "component:ds-card",
3798
+ "component:ds-field",
3799
+ "component:ds-button-filled"
3800
+ ],
3801
+ "accessibility": [
3802
+ "Choose the native element from document meaning and hierarchy; choose the visual variant independently.",
3803
+ "Composition authors preserve logical h1–h6 order regardless of visual size.",
3804
+ "Visible content and the selected native element provide accessible meaning; avoid redundant roles and labels.",
3805
+ "Use label semantics and its for association only for a real form control.",
3806
+ "When truncating essential content, the owner provides an accessible way to obtain the omitted text.",
3807
+ "Use solid underline only when Text is composed inside a real link.",
3808
+ "Use dotted underline to signal hidden or supplemental interaction such as a tooltip; the owning trigger must provide focus, keyboard interaction, and accessible tooltip semantics."
3809
+ ],
3810
+ "states": [
3811
+ "A variant is atomic: font size, line height, weight, and letter spacing stay together and are not overridden by consumers.",
3812
+ "Emphasis selects the supported stronger recipe for local hierarchy; it does not independently mean selected or active.",
3813
+ "Omitted color inherits currentColor. Explicit semantic aliases or CSS-variable references are used only when Text has an independent color role.",
3814
+ "Line truncation and wrapping require an owner-supplied width constraint and content-aware composition decision.",
3815
+ "Solid underline communicates a real link; dotted underline communicates hidden or supplemental interaction such as a tooltip. Decoration does not make Text interactive by itself.",
3816
+ "Tabular numbers are for changing numeric values or aligned numeric columns where stable glyph width matters.",
3817
+ "Shimmer is reserved for visible generating/loading status text whose owner provides status semantics; reduced motion keeps static readable text."
3818
+ ],
3819
+ "responsiveBehavior": [
3820
+ "The composition owns width, wrapping, truncation, alignment, and any responsive variant change.",
3821
+ "Text preserves complete token recipes and does not scale fluidly or infer breakpoints."
3822
+ ],
3823
+ "frameworkCaveats": {
3824
+ "customElements": [
3825
+ "Set as explicitly for inline text, headings, and labels; omitted as renders a paragraph."
3826
+ ],
3827
+ "react": [
3828
+ "Keep semantic as choices aligned with the rendered document hierarchy rather than component styling."
3829
+ ],
3830
+ "angular": [
3831
+ "Use the for prop only when Text renders a label associated with a real control ID."
3832
+ ]
3833
+ },
3834
+ "references": [
3835
+ {
3836
+ "label": "Storybook examples",
3837
+ "path": "src/wc/components/Text/Text.stories.ts"
3838
+ },
3839
+ {
3840
+ "label": "Typography contract",
3841
+ "path": "AGENTS.md"
3842
+ }
3843
+ ]
3844
+ },
3014
3845
  "api": {
3015
3846
  "props": {
3016
3847
  "align": {
@@ -3022,7 +3853,7 @@
3022
3853
  "required": false
3023
3854
  },
3024
3855
  "color": {
3025
- "type": "TextColor | undefined",
3856
+ "type": "TextColor",
3026
3857
  "required": false
3027
3858
  },
3028
3859
  "decoration": {