@hirobius/design-system 0.18.0 → 0.19.1

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 (88) hide show
  1. package/CONSUMING.md +150 -0
  2. package/DESIGN.md +220 -0
  3. package/README.md +14 -2
  4. package/dist/chunks/{LanguageContext-CH_bwzCq.js → LanguageContext-BxdCwiFg.js} +20 -8
  5. package/dist/chunks/{TokenDisplayContext-evZi_214.js → TokenDisplayContext-DKYJMVWk.js} +10 -2
  6. package/dist/chunks/{activity-feed-C8_e-Btq.js → activity-feed-BGQ6v3wc.js} +5248 -3163
  7. package/dist/chunks/{form-DnGRy27o.js → form-COP3vK9_.js} +31 -29
  8. package/dist/contexts.js +4 -4
  9. package/dist/form.js +5 -5
  10. package/dist/hirobius-ui.js +2790 -3257
  11. package/dist/icons.js +53 -0
  12. package/dist/manifest.js +15 -14
  13. package/dist/patterns.js +284 -101
  14. package/dist/static.css +3 -3
  15. package/dist/styles.css +1 -1
  16. package/dist/tokens.css +1 -1
  17. package/dist/types/src/app/components/alert-dialog.d.ts +9 -1
  18. package/dist/types/src/app/components/alert.d.ts +4 -0
  19. package/dist/types/src/app/components/avatar.d.ts +4 -0
  20. package/dist/types/src/app/components/badge.d.ts +4 -0
  21. package/dist/types/src/app/components/box.d.ts +5 -0
  22. package/dist/types/src/app/components/breadcrumb.d.ts +4 -0
  23. package/dist/types/src/app/components/button-group.d.ts +4 -0
  24. package/dist/types/src/app/components/button.d.ts +3 -0
  25. package/dist/types/src/app/components/card.d.ts +9 -0
  26. package/dist/types/src/app/components/checkbox.d.ts +4 -0
  27. package/dist/types/src/app/components/combobox.d.ts +10 -0
  28. package/dist/types/src/app/components/command-palette.d.ts +3 -1
  29. package/dist/types/src/app/components/container.d.ts +5 -0
  30. package/dist/types/src/app/components/context-menu.d.ts +25 -2
  31. package/dist/types/src/app/components/data-table-section.d.ts +45 -0
  32. package/dist/types/src/app/components/destructive-section.d.ts +32 -0
  33. package/dist/types/src/app/components/dialog.d.ts +20 -2
  34. package/dist/types/src/app/components/disclosure.d.ts +3 -0
  35. package/dist/types/src/app/components/divider.d.ts +4 -0
  36. package/dist/types/src/app/components/empty-state.d.ts +4 -0
  37. package/dist/types/src/app/components/field.d.ts +4 -0
  38. package/dist/types/src/app/components/form-actions.d.ts +26 -0
  39. package/dist/types/src/app/components/grid.d.ts +4 -0
  40. package/dist/types/src/app/components/hds-tooltip.d.ts +14 -2
  41. package/dist/types/src/app/components/hover-card.d.ts +16 -1
  42. package/dist/types/src/app/components/icon.d.ts +4 -0
  43. package/dist/types/src/app/components/inline-link.d.ts +4 -0
  44. package/dist/types/src/app/components/input.d.ts +5 -0
  45. package/dist/types/src/app/components/kbd.d.ts +3 -0
  46. package/dist/types/src/app/components/menu.d.ts +26 -2
  47. package/dist/types/src/app/components/metric-tiles.d.ts +40 -0
  48. package/dist/types/src/app/components/page-header.d.ts +34 -0
  49. package/dist/types/src/app/components/pagination.d.ts +3 -0
  50. package/dist/types/src/app/components/popover.d.ts +14 -2
  51. package/dist/types/src/app/components/progress.d.ts +4 -0
  52. package/dist/types/src/app/components/radio.d.ts +5 -0
  53. package/dist/types/src/app/components/select.d.ts +16 -0
  54. package/dist/types/src/app/components/skeleton.d.ts +4 -0
  55. package/dist/types/src/app/components/slider.d.ts +3 -0
  56. package/dist/types/src/app/components/spinner.d.ts +4 -0
  57. package/dist/types/src/app/components/stack.d.ts +4 -0
  58. package/dist/types/src/app/components/stat.d.ts +4 -0
  59. package/dist/types/src/app/components/status-tile.d.ts +4 -0
  60. package/dist/types/src/app/components/table.d.ts +36 -4
  61. package/dist/types/src/app/components/tabs.d.ts +4 -0
  62. package/dist/types/src/app/components/tag.d.ts +3 -0
  63. package/dist/types/src/app/components/text.d.ts +4 -0
  64. package/dist/types/src/app/components/textarea.d.ts +3 -0
  65. package/dist/types/src/app/components/toast.d.ts +4 -0
  66. package/dist/types/src/app/components/toggle.d.ts +4 -0
  67. package/dist/types/src/app/components/tooltip.d.ts +1 -1
  68. package/dist/types/src/app/components/visually-hidden.d.ts +3 -0
  69. package/dist/types/src/app/context/hds-portal.d.ts +52 -0
  70. package/dist/types/src/app/context/hds-theme.d.ts +10 -0
  71. package/dist/types/src/app/data/manifest-types.d.ts +27 -0
  72. package/dist/types/src/app/design-system/generated-token-refs.d.ts +2 -0
  73. package/dist/types/src/icons.d.ts +13 -0
  74. package/dist/types/src/index.d.ts +20 -1
  75. package/dist/types/src/patterns.d.ts +5 -0
  76. package/dist/variables.css +4 -0
  77. package/docs/CONSUMING.md +758 -0
  78. package/hirobius.tokens.json +17 -0
  79. package/llms.txt +261 -0
  80. package/package.json +22 -4
  81. package/public/hds-manifest.json +1605 -105
  82. package/public/llms/components.txt +1090 -0
  83. package/public/llms/layout.txt +54 -0
  84. package/public/llms/scroll.txt +22 -0
  85. package/public/llms/tokens.txt +32 -0
  86. package/public/llms-full.txt +1561 -0
  87. package/public/llms.txt +261 -0
  88. package/src/app/data/component-api.json +6156 -0
@@ -2,11 +2,11 @@
2
2
  "name": "Hirobius Design System",
3
3
  "description": "Three-tier design token system for Adrian Milsap's portfolio site. Tokens flow primitive → semantic → component. All visual decisions trace back to hirobius.tokens.json.",
4
4
  "version": "1",
5
- "generated": "2026-09-28T00:14:31.544Z",
5
+ "generated": "2026-09-30T12:27:39.299Z",
6
6
  "source": "hirobius.tokens.json",
7
7
  "format": "W3C DTCG 2025.10",
8
- "docs": "https://adrianmilsap.com/hds",
9
- "llmsTxt": "https://adrianmilsap.com/llms.txt",
8
+ "docs": "https://hirobius-design-system.vercel.app/",
9
+ "llmsTxt": "https://hirobius-design-system.vercel.app/llms.txt",
10
10
  "systemSpecs": {
11
11
  "engine": "React + TypeScript",
12
12
  "icons": "Lucide React",
@@ -75,9 +75,11 @@
75
75
  "Container",
76
76
  "ContextMenu",
77
77
  "Cover",
78
+ "DataTableSection",
78
79
  "DateInput",
79
80
  "DateRangeInput",
80
81
  "DateTimeInput",
82
+ "DestructiveSection",
81
83
  "Dialog",
82
84
  "DialogClose",
83
85
  "DialogContent",
@@ -95,6 +97,7 @@
95
97
  "Field",
96
98
  "FileInput",
97
99
  "Form",
100
+ "FormActions",
98
101
  "FormField",
99
102
  "FormFieldShell",
100
103
  "FoundationSwatch",
@@ -114,11 +117,14 @@
114
117
  "Lightbox",
115
118
  "Menu",
116
119
  "MetadataList",
120
+ "MetricTile",
121
+ "MetricTiles",
117
122
  "MultiSelector",
118
123
  "NavGroup",
119
124
  "NavItem",
120
125
  "OverflowList",
121
126
  "Page",
127
+ "PageHeader",
122
128
  "Pagination",
123
129
  "Pin",
124
130
  "Popover",
@@ -240,7 +246,68 @@
240
246
  "monoSm"
241
247
  ]
242
248
  },
243
- "patternInventory": [],
249
+ "patternInventory": [
250
+ "DataTableSection",
251
+ "DestructiveSection",
252
+ "FormActions",
253
+ "MetricTiles",
254
+ "PageHeader"
255
+ ],
256
+ "iconSet": {
257
+ "subpath": "@hirobius/design-system/icons",
258
+ "names": [
259
+ "Archive",
260
+ "ArrowDown",
261
+ "ArrowLeft",
262
+ "ArrowRight",
263
+ "ArrowUp",
264
+ "Bell",
265
+ "Bookmark",
266
+ "Calendar",
267
+ "Check",
268
+ "ChevronDown",
269
+ "ChevronLeft",
270
+ "ChevronRight",
271
+ "ChevronUp",
272
+ "CircleAlert",
273
+ "CircleCheck",
274
+ "CircleHelp",
275
+ "Clock",
276
+ "Copy",
277
+ "Download",
278
+ "Ellipsis",
279
+ "EllipsisVertical",
280
+ "ExternalLink",
281
+ "Eye",
282
+ "EyeOff",
283
+ "FileText",
284
+ "Funnel",
285
+ "Heart",
286
+ "House",
287
+ "Image",
288
+ "Info",
289
+ "Link",
290
+ "Lock",
291
+ "LogIn",
292
+ "LogOut",
293
+ "Mail",
294
+ "Menu",
295
+ "Minus",
296
+ "Pencil",
297
+ "Plus",
298
+ "RefreshCw",
299
+ "Save",
300
+ "Search",
301
+ "Settings",
302
+ "Share",
303
+ "Star",
304
+ "Trash2",
305
+ "TriangleAlert",
306
+ "Upload",
307
+ "User",
308
+ "X"
309
+ ]
310
+ },
244
311
  "phases": [
245
312
  {
246
313
  "id": "foundation",
@@ -581,7 +648,7 @@
581
648
  ],
582
649
  "namespaceViolations": []
583
650
  },
584
- "agentEntrypoint": "CLAUDE.md",
651
+ "agentEntrypoint": "llms.txt",
585
652
  "breakingChangePolicy": "Version increments on any prop rename, token path rename, or removed component. Additions are non-breaking.",
586
653
  "componentSpecs": {
587
654
  "CaseStudyLayout": {
@@ -691,7 +758,12 @@
691
758
  "sizing": "panel"
692
759
  },
693
760
  "consumers": [
761
+ "src/app/components/badge.tsx",
762
+ "src/app/components/dialog.tsx",
763
+ "src/app/components/empty-state.tsx",
764
+ "src/app/components/toast.tsx",
694
765
  "src/app/data/hdsEditorial.tsx",
766
+ "src/stories/alert-dialog.stories.tsx",
695
767
  "src/stories/alert.stories.tsx",
696
768
  "src/stories/static-primitives.stories.tsx"
697
769
  ],
@@ -812,7 +884,21 @@
812
884
  "primitives-alert--success",
813
885
  "primitives-alert--warning",
814
886
  "primitives-alert--with-title"
815
- ]
887
+ ],
888
+ "usage": {
889
+ "when": "Show a persistent inline message with a severity, next to the content it concerns.",
890
+ "whenNot": "A brief confirmation that should disappear on its own, or a status label.",
891
+ "useInstead": [
892
+ {
893
+ "component": "ToastProvider",
894
+ "reason": "a brief confirmation that fades away"
895
+ },
896
+ {
897
+ "component": "Badge",
898
+ "reason": "a short status label"
899
+ }
900
+ ]
901
+ }
816
902
  },
817
903
  "CinematicLink": {
818
904
  "category": "Branding",
@@ -946,7 +1032,7 @@
946
1032
  "governedCategory": true,
947
1033
  "hidden": false,
948
1034
  "filePath": "src/app/components/container.tsx",
949
- "description": "Container — semantic width-constrained layout. semantic max-width scale, so agents stop hand-rolling `marginInline: auto` plus an ad hoc max-width pixel value for page shells. use the semantic width scale ('content' | 'max'), never a raw px value. Do NOT use the deprecated `padding` prop — it is a no-op; apply padding via Surface or a Stack instead. Do NOT import Container directly inside a page under src/app/pages — use Page, which wraps Container and owns vertical rhythm. Use Center instead when you also need a horizontal gutter, which Container does not support. Centers content horizontally and applies semantic max-width constraints. - maxWidth options: 'content' (760px prose) | 'max' (1200px full layout) - No arbitrary pixel values allowed Usage: <Container maxWidth=\"max\"> <div>...</div> </Container>",
1035
+ "description": "Container — semantic width-constrained layout. Centers content horizontally and applies semantic max-width constraints. - maxWidth options: 'content' (760px prose) | 'max' (1200px full layout) - No arbitrary pixel values allowed Usage: <Container maxWidth=\"max\"> <div>...</div> </Container>",
950
1036
  "figmaUrl": null,
951
1037
  "figmaId": null,
952
1038
  "preview": {
@@ -959,6 +1045,7 @@
959
1045
  "src/app/components/center.tsx",
960
1046
  "src/app/components/page.tsx",
961
1047
  "src/app/components/switcher.tsx",
1048
+ "src/app/context/__tests__/portal-scope.test.tsx",
962
1049
  "src/app/layouts/CaseStudyLayout.tsx",
963
1050
  "src/app/layouts/DocLayout.tsx",
964
1051
  "src/stories/box.stories.tsx",
@@ -1010,7 +1097,26 @@
1010
1097
  "storyIds": [
1011
1098
  "primitives-container--content-width",
1012
1099
  "primitives-container--max-width"
1013
- ]
1100
+ ],
1101
+ "usage": {
1102
+ "when": "Constrain a page region to the content or maximum width and centre it.",
1103
+ "whenNot": "Spacing between siblings, columns, or a surface with padding.",
1104
+ "useInstead": [
1105
+ {
1106
+ "component": "Stack",
1107
+ "reason": "spacing between siblings"
1108
+ },
1109
+ {
1110
+ "component": "Grid",
1111
+ "reason": "columns"
1112
+ },
1113
+ {
1114
+ "component": "Box",
1115
+ "reason": "one-off layout that no named primitive covers"
1116
+ }
1117
+ ]
1118
+ },
1119
+ "aiRules": "Reach for this named layout intent before Box/sx. maxWidth MUST use the semantic width scale ('content' | 'max'), never a raw px value. Do NOT use the deprecated `padding` prop — it is a no-op; apply padding via Surface or a Stack instead. Do NOT import Container directly inside a page under src/app/pages — use Page, which wraps Container and owns vertical rhythm. Use Center instead when you also need a horizontal gutter, which Container does not support."
1014
1120
  },
1015
1121
  "Disclosure": {
1016
1122
  "category": "Layout",
@@ -1027,6 +1133,7 @@
1027
1133
  },
1028
1134
  "consumers": [
1029
1135
  "src/app/components/nav-group.tsx",
1136
+ "src/app/components/tabs.tsx",
1030
1137
  "src/app/layouts/HdsDocsShell.tsx",
1031
1138
  "src/stories/disclosure.stories.tsx",
1032
1139
  "src/stories/nav-group.stories.tsx"
@@ -1134,7 +1241,17 @@
1134
1241
  "primitives-disclosure--multiple-items",
1135
1242
  "primitives-disclosure--open-by-default",
1136
1243
  "primitives-disclosure--panel"
1137
- ]
1244
+ ],
1245
+ "usage": {
1246
+ "when": "Hide optional explanatory content behind a heading that people can expand.",
1247
+ "whenNot": "Content people must see, or switching between panels.",
1248
+ "useInstead": [
1249
+ {
1250
+ "component": "Tabs",
1251
+ "reason": "switching between panels of content"
1252
+ }
1253
+ ]
1254
+ }
1138
1255
  },
1139
1256
  "Divider": {
1140
1257
  "category": "Layout",
@@ -1239,7 +1356,21 @@
1239
1356
  "primitives-divider--legacy-strong-prop",
1240
1357
  "primitives-divider--vertical",
1241
1358
  "primitives-divider--with-spacing"
1242
- ]
1359
+ ],
1360
+ "usage": {
1361
+ "when": "Separate two regions of content with a thin semantic rule.",
1362
+ "whenNot": "Spacing alone would do, or the separation needs a container.",
1363
+ "useInstead": [
1364
+ {
1365
+ "component": "Stack",
1366
+ "reason": "gap-based spacing between siblings"
1367
+ },
1368
+ {
1369
+ "component": "Surface",
1370
+ "reason": "a bounded region with its own background"
1371
+ }
1372
+ ]
1373
+ }
1243
1374
  },
1244
1375
  "DocLinkCard": {
1245
1376
  "category": "Navigation",
@@ -1411,6 +1542,7 @@
1411
1542
  "sizing": "full"
1412
1543
  },
1413
1544
  "consumers": [
1545
+ "src/stories/foundation-swatch.stories.test.ts",
1414
1546
  "src/stories/foundation-swatch.stories.tsx"
1415
1547
  ],
1416
1548
  "tokenMapping": {},
@@ -1543,8 +1675,11 @@
1543
1675
  "consumers": [
1544
1676
  "src/app/components/box.tsx",
1545
1677
  "src/app/components/cluster.tsx",
1678
+ "src/app/components/container.tsx",
1546
1679
  "src/app/components/foundation-swatch.tsx",
1547
1680
  "src/app/components/image-lightbox.tsx",
1681
+ "src/app/components/metric-tiles.test.tsx",
1682
+ "src/app/components/metric-tiles.tsx",
1548
1683
  "src/app/components/segmented-control.test.tsx",
1549
1684
  "src/app/components/sidebar.tsx",
1550
1685
  "src/app/components/stack.tsx",
@@ -1557,7 +1692,8 @@
1557
1692
  "src/stories/grid.stories.tsx",
1558
1693
  "src/stories/patterns-layout.stories.tsx",
1559
1694
  "src/stories/segmented-control.stories.tsx",
1560
- "src/stories/surface.stories.tsx"
1695
+ "src/stories/surface.stories.tsx",
1696
+ "src/stories/tile-grid.stories.tsx"
1561
1697
  ],
1562
1698
  "tokenMapping": {},
1563
1699
  "props": {
@@ -1658,7 +1794,22 @@
1658
1794
  "primitives-grid--auto-fit",
1659
1795
  "primitives-grid--three-column",
1660
1796
  "primitives-grid--two-column"
1661
- ]
1797
+ ],
1798
+ "usage": {
1799
+ "when": "Lay out content in responsive columns with token-governed gaps, or align nested content with subgrid.",
1800
+ "whenNot": "A single row or column, or styling a surface.",
1801
+ "useInstead": [
1802
+ {
1803
+ "component": "Stack",
1804
+ "reason": "a single row or column"
1805
+ },
1806
+ {
1807
+ "component": "Box",
1808
+ "reason": "one-off layout that no named primitive covers"
1809
+ }
1810
+ ]
1811
+ },
1812
+ "aiRules": "Use Grid for spatial layout, not for surface styling or content padding. Do NOT apply background, border, or internal padding directly to Grid to mimic a card. Do NOT use arbitrary CSS grid templates when fixed, auto-fit, or subgrid modes already express the layout. Do NOT use Grid for simple one-dimensional stacks where Stack is sufficient."
1662
1813
  },
1663
1814
  "Icon": {
1664
1815
  "category": "Display",
@@ -1677,6 +1828,7 @@
1677
1828
  "src/app/components/activity-feed.test.tsx",
1678
1829
  "src/app/components/activity-feed.tsx",
1679
1830
  "src/app/components/alert.tsx",
1831
+ "src/app/components/avatar.tsx",
1680
1832
  "src/app/components/breadcrumb.tsx",
1681
1833
  "src/app/components/checkbox.tsx",
1682
1834
  "src/app/components/code-block.tsx",
@@ -1823,7 +1975,21 @@
1823
1975
  "primitives-icon--semantic-color",
1824
1976
  "primitives-icon--semantic-colors",
1825
1977
  "primitives-icon--size-gallery"
1826
- ]
1978
+ ],
1979
+ "usage": {
1980
+ "when": "Draw a Lucide glyph at a size and colour from the design tokens.",
1981
+ "whenNot": "A control someone can activate, or a picture that carries content.",
1982
+ "useInstead": [
1983
+ {
1984
+ "component": "Button",
1985
+ "reason": "a clickable control, with iconOnly for an icon-only one"
1986
+ },
1987
+ {
1988
+ "component": "Avatar",
1989
+ "reason": "a picture of a person or entity"
1990
+ }
1991
+ ]
1992
+ }
1827
1993
  },
1828
1994
  "IconButton": {
1829
1995
  "category": "Actions",
@@ -1839,6 +2005,8 @@
1839
2005
  "sizing": "panel"
1840
2006
  },
1841
2007
  "consumers": [
2008
+ "src/app/components/button.test.tsx",
2009
+ "src/app/components/data-table-section.tsx",
1842
2010
  "src/app/components/hds-tooltip.tsx",
1843
2011
  "src/app/components/inline-code.tsx",
1844
2012
  "src/app/components/pagination.tsx",
@@ -1846,7 +2014,10 @@
1846
2014
  "src/app/data/hdsEditorial.tsx",
1847
2015
  "src/docs-tooling/page-footer.tsx",
1848
2016
  "src/docs-tooling/shell-controls.tsx",
1849
- "src/stories/icon-button.stories.tsx"
2017
+ "src/stories/data-table-section.stories.tsx",
2018
+ "src/stories/icon-button.stories.tsx",
2019
+ "src/stories/lib/usage-description.test.ts",
2020
+ "src/stories/patterns-client-detail.stories.tsx"
1850
2021
  ],
1851
2022
  "tokenMapping": {
1852
2023
  "Fill": "semantic.accent.rest",
@@ -1962,7 +2133,17 @@
1962
2133
  "primitives-icon-button--primary",
1963
2134
  "primitives-icon-button--size-gallery",
1964
2135
  "primitives-icon-button--tertiary"
1965
- ]
2136
+ ],
2137
+ "usage": {
2138
+ "when": "Trigger an action from a compact icon-only control, always with an accessible label.",
2139
+ "whenNot": "A control that needs a visible text label.",
2140
+ "useInstead": [
2141
+ {
2142
+ "component": "Button",
2143
+ "reason": "a control with a text label, or Button iconOnly (hds#254 folds IconButton into it)"
2144
+ }
2145
+ ]
2146
+ }
1966
2147
  },
1967
2148
  "InlineCode": {
1968
2149
  "category": "Display",
@@ -2044,10 +2225,13 @@
2044
2225
  "sizing": "panel"
2045
2226
  },
2046
2227
  "consumers": [
2228
+ "src/app/components/button.tsx",
2047
2229
  "src/app/components/hover-card.tsx",
2048
2230
  "src/app/components/image-lightbox.tsx",
2231
+ "src/app/components/text.tsx",
2049
2232
  "src/docs-tooling/lab/legacy-token-detail.tsx",
2050
- "src/stories/inline-link.stories.tsx"
2233
+ "src/stories/inline-link.stories.tsx",
2234
+ "src/stories/lib/usage-description.test.ts"
2051
2235
  ],
2052
2236
  "tokenMapping": {
2053
2237
  "Link text": "semantic.color.content.accent",
@@ -2095,7 +2279,21 @@
2095
2279
  "primitives-inline-link--external-no-icon",
2096
2280
  "primitives-inline-link--in-body-copy",
2097
2281
  "primitives-inline-link--internal-route"
2098
- ]
2282
+ ],
2283
+ "usage": {
2284
+ "when": "Link to a route or external URL from inside body copy.",
2285
+ "whenNot": "An action that changes something, or a control that needs button styling.",
2286
+ "useInstead": [
2287
+ {
2288
+ "component": "Button",
2289
+ "reason": "an action or a link that needs button styling"
2290
+ },
2291
+ {
2292
+ "component": "Text",
2293
+ "reason": "unlinked body copy"
2294
+ }
2295
+ ]
2296
+ }
2099
2297
  },
2100
2298
  "Input": {
2101
2299
  "category": "Inputs",
@@ -2111,17 +2309,25 @@
2111
2309
  "sizing": "panel"
2112
2310
  },
2113
2311
  "consumers": [
2312
+ "src/app/components/field.tsx",
2114
2313
  "src/app/components/form.tsx",
2115
2314
  "src/app/components/segmented-control.tsx",
2315
+ "src/app/components/slider.tsx",
2116
2316
  "src/app/components/stepper-field.tsx",
2117
2317
  "src/app/components/textarea.tsx",
2118
2318
  "src/app/components/time-input.tsx",
2119
2319
  "src/app/data/hdsEditorial.tsx",
2120
2320
  "src/app/design-system/generated-token-descriptions.ts",
2121
2321
  "src/stories/combobox.stories.tsx",
2322
+ "src/stories/date-input.stories.tsx",
2323
+ "src/stories/date-range-input.stories.tsx",
2324
+ "src/stories/date-time-input.stories.tsx",
2325
+ "src/stories/file-input.stories.tsx",
2326
+ "src/stories/input-group.stories.tsx",
2122
2327
  "src/stories/input.stories.tsx",
2123
2328
  "src/stories/patterns-layout.stories.tsx",
2124
- "src/stories/textarea.stories.tsx"
2329
+ "src/stories/textarea.stories.tsx",
2330
+ "src/stories/time-input.stories.tsx"
2125
2331
  ],
2126
2332
  "tokenMapping": {
2127
2333
  "Surface fill": "role.background",
@@ -2349,7 +2555,25 @@
2349
2555
  "primitives-input--size-variants",
2350
2556
  "primitives-input--with-error",
2351
2557
  "primitives-input--with-helper"
2352
- ]
2558
+ ],
2559
+ "usage": {
2560
+ "when": "Collect a single line of text, a number, an email or a password, with label, helper and error slots.",
2561
+ "whenNot": "Multi-line text, or choosing from a fixed list of options.",
2562
+ "useInstead": [
2563
+ {
2564
+ "component": "Textarea",
2565
+ "reason": "multi-line text"
2566
+ },
2567
+ {
2568
+ "component": "Select",
2569
+ "reason": "a short fixed list"
2570
+ },
2571
+ {
2572
+ "component": "Combobox",
2573
+ "reason": "a long fixed list that needs search"
2574
+ }
2575
+ ]
2576
+ }
2353
2577
  },
2354
2578
  "NavGroup": {
2355
2579
  "category": "Navigation",
@@ -2569,7 +2793,10 @@
2569
2793
  "sizing": "panel"
2570
2794
  },
2571
2795
  "consumers": [
2796
+ "src/app/components/button-group.tsx",
2797
+ "src/app/components/radio.tsx",
2572
2798
  "src/app/components/segmented-control.test.tsx",
2799
+ "src/app/components/tabs.tsx",
2573
2800
  "src/app/data/hdsEditorial.tsx",
2574
2801
  "src/app/hooks/useInteractionState.ts",
2575
2802
  "src/docs-tooling/TokenDisplayToggle.tsx",
@@ -2660,7 +2887,25 @@
2660
2887
  "primitives-segmented-control--full-width",
2661
2888
  "primitives-segmented-control--primary",
2662
2889
  "primitives-segmented-control--secondary"
2663
- ]
2890
+ ],
2891
+ "usage": {
2892
+ "when": "Switch between two to five mutually exclusive views or modes in a compact row.",
2893
+ "whenNot": "A form choice that submits with the form, or more than five options.",
2894
+ "useInstead": [
2895
+ {
2896
+ "component": "Radio",
2897
+ "reason": "a form choice that submits with the form"
2898
+ },
2899
+ {
2900
+ "component": "Tabs",
2901
+ "reason": "switching between panels of content"
2902
+ },
2903
+ {
2904
+ "component": "Select",
2905
+ "reason": "more than five options"
2906
+ }
2907
+ ]
2908
+ }
2664
2909
  },
2665
2910
  "Sketch": {
2666
2911
  "category": "Layout",
@@ -2676,6 +2921,7 @@
2676
2921
  "sizing": "panel"
2677
2922
  },
2678
2923
  "consumers": [
2924
+ "src/stories/sketch.stories.test.tsx",
2679
2925
  "src/stories/sketch.stories.tsx"
2680
2926
  ],
2681
2927
  "tokenMapping": {},
@@ -2756,10 +3002,13 @@
2756
3002
  "consumers": [
2757
3003
  "src/app/components/activity-feed.tsx",
2758
3004
  "src/app/components/box.tsx",
3005
+ "src/app/components/button-group.tsx",
2759
3006
  "src/app/components/cluster.tsx",
2760
3007
  "src/app/components/container.tsx",
2761
3008
  "src/app/components/cover.tsx",
3009
+ "src/app/components/data-table-section.tsx",
2762
3010
  "src/app/components/disclosure.tsx",
3011
+ "src/app/components/divider.tsx",
2763
3012
  "src/app/components/error-boundary.tsx",
2764
3013
  "src/app/components/error-pattern.tsx",
2765
3014
  "src/app/components/foundation-swatch.tsx",
@@ -2767,8 +3016,11 @@
2767
3016
  "src/app/components/heading-stack.tsx",
2768
3017
  "src/app/components/image-lightbox.tsx",
2769
3018
  "src/app/components/nav-group.tsx",
3019
+ "src/app/components/page-header.tsx",
2770
3020
  "src/app/components/page.tsx",
2771
3021
  "src/app/components/sketch.tsx",
3022
+ "src/app/components/surface.tsx",
3023
+ "src/app/components/table.tsx",
2772
3024
  "src/app/components/tooltip.tsx",
2773
3025
  "src/app/data/hdsEditorial.tsx",
2774
3026
  "src/app/layouts/CaseStudyLayout.tsx",
@@ -2781,7 +3033,9 @@
2781
3033
  "src/stories/box.stories.tsx",
2782
3034
  "src/stories/code-block.stories.tsx",
2783
3035
  "src/stories/grid.stories.tsx",
3036
+ "src/stories/heading-stack.stories.tsx",
2784
3037
  "src/stories/page.stories.tsx",
3038
+ "src/stories/patterns-client-detail.stories.tsx",
2785
3039
  "src/stories/patterns-layout.stories.tsx",
2786
3040
  "src/stories/stack.stories.tsx"
2787
3041
  ],
@@ -2936,7 +3190,22 @@
2936
3190
  "primitives-stack--space-between",
2937
3191
  "primitives-stack--spacious-gap",
2938
3192
  "primitives-stack--tight-gap"
2939
- ]
3193
+ ],
3194
+ "usage": {
3195
+ "when": "Space a row or column of content with token gaps and simple flex alignment.",
3196
+ "whenNot": "Multi-column layout, or giving content a background or padding.",
3197
+ "useInstead": [
3198
+ {
3199
+ "component": "Grid",
3200
+ "reason": "multi-column layout"
3201
+ },
3202
+ {
3203
+ "component": "Surface",
3204
+ "reason": "content that needs a background or padding"
3205
+ }
3206
+ ]
3207
+ },
3208
+ "aiRules": "Use Stack for flow spacing and simple flex alignment only. Do NOT use Stack to create card chrome, internal surface padding, or page-width constraints. Do NOT apply arbitrary margins to Stack to fake spacing between children when the gap prop should own that rhythm. Do NOT use Stack for true two-dimensional layouts that require Grid."
2940
3209
  },
2941
3210
  "StepperField": {
2942
3211
  "category": "Inputs",
@@ -2952,6 +3221,7 @@
2952
3221
  "sizing": "panel"
2953
3222
  },
2954
3223
  "consumers": [
3224
+ "src/app/components/stepper-field.test.tsx",
2955
3225
  "src/stories/stepper-field.stories.tsx"
2956
3226
  ],
2957
3227
  "tokenMapping": {},
@@ -3052,10 +3322,13 @@
3052
3322
  "sizing": "full"
3053
3323
  },
3054
3324
  "consumers": [
3325
+ "src/app/components/data-table-section.tsx",
3055
3326
  "src/app/components/table.test.tsx",
3056
3327
  "src/app/data/hdsEditorial.tsx",
3328
+ "src/app/data/manifest-types.ts",
3057
3329
  "src/docs-tooling/api-reference.tsx",
3058
3330
  "src/docs-tooling/propTableUtils.tsx",
3331
+ "src/stories/data-table-section.stories.tsx",
3059
3332
  "src/stories/nav-group.stories.tsx",
3060
3333
  "src/stories/nav-item.stories.tsx",
3061
3334
  "src/stories/segmented-control.stories.tsx",
@@ -3131,10 +3404,25 @@
3131
3404
  "primitives-table--density-comfortable",
3132
3405
  "primitives-table--density-compact",
3133
3406
  "primitives-table--flush",
3407
+ "primitives-table--follows-density-dial",
3134
3408
  "primitives-table--sortable",
3135
3409
  "primitives-table--with-badge-slots",
3136
3410
  "primitives-table--with-caption"
3137
- ]
3411
+ ],
3412
+ "usage": {
3413
+ "when": "Show rows of structured data in aligned columns, with optional sorting.",
3414
+ "whenNot": "A single record, a short list of links, or content that reflows as cards.",
3415
+ "useInstead": [
3416
+ {
3417
+ "component": "Field",
3418
+ "reason": "one record as label and value pairs"
3419
+ },
3420
+ {
3421
+ "component": "Stack",
3422
+ "reason": "a short list of items"
3423
+ }
3424
+ ]
3425
+ }
3138
3426
  },
3139
3427
  "Tag": {
3140
3428
  "category": "Inputs",
@@ -3303,7 +3591,17 @@
3303
3591
  "primitives-tag--filter-row",
3304
3592
  "primitives-tag--interactive",
3305
3593
  "primitives-tag--state-matrix"
3306
- ]
3594
+ ],
3595
+ "usage": {
3596
+ "when": "Show an interactive filter or category chip that people can toggle.",
3597
+ "whenNot": "A read-only status or count label.",
3598
+ "useInstead": [
3599
+ {
3600
+ "component": "Badge",
3601
+ "reason": "a read-only status or count"
3602
+ }
3603
+ ]
3604
+ }
3307
3605
  },
3308
3606
  "Token": {
3309
3607
  "category": "Display",
@@ -3480,7 +3778,7 @@
3480
3778
  "governedCategory": true,
3481
3779
  "hidden": false,
3482
3780
  "filePath": "src/app/components/surface.tsx",
3483
- "description": "Surface — governed inset surface primitive. Enforces the \"Surface Inset\" rule: backgrounds MUST have internal padding. - Default padding: px24 (cards) | px16 (items) - Default border: none (elevation model — use shadow for lift) - Fixed radius: var(--component-card-radius) - shadow prop: applies a two-layer elevation shadow for card lift Usage: <Surface>Card content</Surface> <Surface padding=\"item\">Compact item</Surface> <Surface shadow>Lifted card with elevation shadow.</Surface>",
3781
+ "description": "Surface — governed inset surface primitive. Enforces the \"Surface Inset\" rule: backgrounds MUST have internal padding. - Default padding: px24 (cards) | px16 (items) - Default border: none (elevation model — use shadow for lift) - Radius: `rounded-lg` (role radius + 4px), the one container radius shared with Card - shadow prop: applies a two-layer elevation shadow for card lift Usage: <Surface>Card content</Surface> <Surface padding=\"item\">Compact item</Surface> <Surface shadow>Lifted card with elevation shadow.</Surface>",
3484
3782
  "figmaUrl": "https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-27",
3485
3783
  "figmaId": null,
3486
3784
  "preview": {
@@ -3488,23 +3786,28 @@
3488
3786
  "sizing": "panel"
3489
3787
  },
3490
3788
  "consumers": [
3789
+ "src/app/components/card.tsx",
3491
3790
  "src/app/components/container.tsx",
3492
3791
  "src/app/components/dialog.tsx",
3493
3792
  "src/app/components/disclosure.tsx",
3793
+ "src/app/components/divider.tsx",
3494
3794
  "src/app/components/empty-state.tsx",
3495
3795
  "src/app/components/error-boundary.tsx",
3496
3796
  "src/app/components/error-pattern.tsx",
3497
3797
  "src/app/components/foundation-swatch.tsx",
3498
3798
  "src/app/components/image-lightbox.tsx",
3799
+ "src/app/components/metric-tiles.tsx",
3499
3800
  "src/app/components/popover.tsx",
3500
3801
  "src/app/components/sketch.tsx",
3501
3802
  "src/app/components/slider.tsx",
3803
+ "src/app/components/stack.tsx",
3502
3804
  "src/app/components/stepper-field.tsx",
3503
3805
  "src/app/components/surface-padding.ts",
3504
3806
  "src/app/components/table.tsx",
3505
3807
  "src/app/components/tokenTableUtils.ts",
3506
3808
  "src/app/components/tokenUtils.ts",
3507
3809
  "src/app/components/tooltip.tsx",
3810
+ "src/app/context/hds-theme.tsx",
3508
3811
  "src/app/data/hdsEditorial.tsx",
3509
3812
  "src/app/layouts/CaseStudyLayout.tsx",
3510
3813
  "src/docs-tooling/api-reference.tsx",
@@ -3573,7 +3876,22 @@
3573
3876
  "primitives-surface--forced-dark",
3574
3877
  "primitives-surface--item-padding",
3575
3878
  "primitives-surface--with-shadow"
3576
- ]
3879
+ ],
3880
+ "usage": {
3881
+ "when": "Wrap content in a padded, background-bearing inset surface with no header or footer anatomy.",
3882
+ "whenNot": "Page layout, section spacing, width constraints, or content that needs slots.",
3883
+ "useInstead": [
3884
+ {
3885
+ "component": "Card",
3886
+ "reason": "content that needs header, body or footer slots"
3887
+ },
3888
+ {
3889
+ "component": "Stack",
3890
+ "reason": "spacing between siblings"
3891
+ }
3892
+ ]
3893
+ },
3894
+ "aiRules": "Use Surface only when content needs a background-bearing inset wrapper. Do NOT use Surface for macro page layouts, section spacing, or pure width constraints. Do NOT nest extra padded wrappers inside Surface to simulate another card. Do NOT recreate surface behavior with raw div padding, backgroundColor, or border styles elsewhere."
3577
3895
  },
3578
3896
  "Card": {
3579
3897
  "category": "Display",
@@ -3585,18 +3903,31 @@
3585
3903
  "figmaUrl": "https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=39-11",
3586
3904
  "figmaId": null,
3587
3905
  "consumers": [
3906
+ "src/app/components/card-progress.test.tsx",
3907
+ "src/app/components/card.test.tsx",
3908
+ "src/app/components/destructive-section.tsx",
3588
3909
  "src/app/components/doc-link-card.tsx",
3589
3910
  "src/app/components/empty-state.tsx",
3911
+ "src/app/components/field.tsx",
3590
3912
  "src/app/components/grid.tsx",
3591
3913
  "src/app/components/metadata-list.tsx",
3914
+ "src/app/components/metric-tiles.tsx",
3592
3915
  "src/app/components/radio.test.tsx",
3593
3916
  "src/app/components/stacked-card-rail.tsx",
3917
+ "src/app/components/stat.tsx",
3918
+ "src/app/components/status-tile.tsx",
3594
3919
  "src/app/components/surface-padding.ts",
3595
3920
  "src/app/components/surface.tsx",
3596
3921
  "src/app/data/hdsEditorial.tsx",
3597
3922
  "src/app/design-system/generated-token-descriptions.ts",
3598
3923
  "src/stories/card.stories.tsx",
3924
+ "src/stories/doc-link-card.stories.tsx",
3599
3925
  "src/stories/grid.stories.tsx",
3926
+ "src/stories/history-card.stories.tsx",
3927
+ "src/stories/hover-card.stories.tsx",
3928
+ "src/stories/metric-tiles.stories.tsx",
3929
+ "src/stories/selectable-card.stories.tsx",
3930
+ "src/stories/stacked-card-rail.stories.tsx",
3600
3931
  "src/stories/static-primitives.stories.tsx"
3601
3932
  ],
3602
3933
  "tokenMapping": {
@@ -3821,7 +4152,21 @@
3821
4152
  "primitives-card--padding-variants",
3822
4153
  "primitives-card--progress-slot",
3823
4154
  "primitives-card--variant-accent"
3824
- ]
4155
+ ],
4156
+ "usage": {
4157
+ "when": "Group related content on a raised surface with header, body, footer and metric slots.",
4158
+ "whenNot": "A bare padded background with no slot anatomy, or a single headline figure.",
4159
+ "useInstead": [
4160
+ {
4161
+ "component": "Surface",
4162
+ "reason": "a padded background without slot anatomy"
4163
+ },
4164
+ {
4165
+ "component": "Card.Metric",
4166
+ "reason": "a single headline figure"
4167
+ }
4168
+ ]
4169
+ }
3825
4170
  },
3826
4171
  "ComponentInstanceMatrix": {
3827
4172
  "category": "Utilities",
@@ -4195,17 +4540,22 @@
4195
4540
  "src/app/components/alert-dialog.tsx",
4196
4541
  "src/app/components/animated-label.tsx",
4197
4542
  "src/app/components/card.tsx",
4543
+ "src/app/components/data-table-section.tsx",
4198
4544
  "src/app/components/date-input.tsx",
4199
4545
  "src/app/components/date-time-input.tsx",
4546
+ "src/app/components/destructive-section.tsx",
4200
4547
  "src/app/components/dialog.tsx",
4201
4548
  "src/app/components/error-pattern.tsx",
4202
4549
  "src/app/components/foundation-swatch.tsx",
4203
4550
  "src/app/components/hds-tooltip.tsx",
4551
+ "src/app/components/inline-link.tsx",
4552
+ "src/app/components/kbd.tsx",
4204
4553
  "src/app/components/nav-item.tsx",
4205
4554
  "src/app/components/table.tsx",
4206
4555
  "src/app/components/text-lockup.tsx",
4207
4556
  "src/app/components/tokenTableUtils.ts",
4208
4557
  "src/app/components/toolbar.test.tsx",
4558
+ "src/app/components/visually-hidden.tsx",
4209
4559
  "src/app/design-system/generated-token-descriptions.ts",
4210
4560
  "src/brand/overlay.ts",
4211
4561
  "src/docs-tooling/preview-frame.tsx",
@@ -4220,6 +4570,7 @@
4220
4570
  "src/stories/skeleton.stories.tsx",
4221
4571
  "src/stories/sketch.stories.tsx",
4222
4572
  "src/stories/surface.stories.tsx",
4573
+ "src/stories/text-lockup.stories.tsx",
4223
4574
  "src/stories/text.stories.tsx",
4224
4575
  "src/stories/toolbar.stories.tsx"
4225
4576
  ],
@@ -4246,7 +4597,21 @@
4246
4597
  "primitives-text--heading-3",
4247
4598
  "primitives-text--technical",
4248
4599
  "primitives-text--ui"
4249
- ]
4600
+ ],
4601
+ "usage": {
4602
+ "when": "Set any text on the type ramp, with the element chosen by `as`.",
4603
+ "whenNot": "Navigation links, or a keyboard hint.",
4604
+ "useInstead": [
4605
+ {
4606
+ "component": "InlineLink",
4607
+ "reason": "a link inside body copy"
4608
+ },
4609
+ {
4610
+ "component": "Kbd",
4611
+ "reason": "a keyboard key hint"
4612
+ }
4613
+ ]
4614
+ }
4250
4615
  },
4251
4616
  "Dialog": {
4252
4617
  "category": "Overlays",
@@ -4268,14 +4633,20 @@
4268
4633
  "src/app/components/alert-dialog.tsx",
4269
4634
  "src/app/components/command-palette.tsx",
4270
4635
  "src/app/components/dialog.test.tsx",
4636
+ "src/app/components/hover-card.tsx",
4271
4637
  "src/app/components/image-lightbox.test.tsx",
4272
4638
  "src/app/components/image-lightbox.tsx",
4273
4639
  "src/app/components/menu.tsx",
4274
4640
  "src/app/components/popover.tsx",
4641
+ "src/app/components/toast.tsx",
4642
+ "src/app/context/__tests__/portal-hydration.test.tsx",
4643
+ "src/app/context/__tests__/portal-scope.test.tsx",
4644
+ "src/stories/alert-dialog.stories.tsx",
4275
4645
  "src/stories/alert.stories.tsx",
4276
4646
  "src/stories/combobox.stories.tsx",
4277
4647
  "src/stories/dialog.stories.tsx",
4278
- "src/stories/table.stories.tsx"
4648
+ "src/stories/table.stories.tsx",
4649
+ "src/styles/__tests__/scrim-and-color-scheme.test.ts"
4279
4650
  ],
4280
4651
  "tokenMapping": {},
4281
4652
  "variantAxes": [
@@ -4402,6 +4773,11 @@
4402
4773
  "tokenBinding": {
4403
4774
  "fill": "role.muted-foreground"
4404
4775
  }
4776
+ },
4777
+ {
4778
+ "name": "trigger",
4779
+ "description": "The element that opens the dialog (Dialog.Trigger).",
4780
+ "source": "jsdoc"
4405
4781
  }
4406
4782
  ],
4407
4783
  "allowedChildren": [
@@ -4447,10 +4823,47 @@
4447
4823
  "src/stories/dialog.stories.tsx"
4448
4824
  ],
4449
4825
  "storyIds": [
4826
+ "primitives-dialog--dark-scope",
4450
4827
  "primitives-dialog--default",
4451
4828
  "primitives-dialog--destructive",
4452
4829
  "primitives-dialog--information",
4453
4830
  "primitives-dialog--no-close-affordance"
4831
+ ],
4832
+ "usage": {
4833
+ "when": "Interrupt the page with a modal that needs a decision or focused input before people continue.",
4834
+ "whenNot": "A preview on hover, a message that needs no reply, or content that can stay inline.",
4835
+ "useInstead": [
4836
+ {
4837
+ "component": "HoverCard",
4838
+ "reason": "a preview on hover or focus"
4839
+ },
4840
+ {
4841
+ "component": "Alert",
4842
+ "reason": "a message that needs no reply"
4843
+ },
4844
+ {
4845
+ "component": "ToastProvider",
4846
+ "reason": "a brief confirmation"
4847
+ }
4848
+ ]
4849
+ },
4850
+ "keyboard": [
4851
+ {
4852
+ "keys": "Enter/Space",
4853
+ "effect": "Opens the dialog from the trigger and moves focus inside it."
4854
+ },
4855
+ {
4856
+ "keys": "Escape",
4857
+ "effect": "Closes the dialog and returns focus to the trigger."
4858
+ },
4859
+ {
4860
+ "keys": "Tab",
4861
+ "effect": "Cycles focus inside the open dialog."
4862
+ },
4863
+ {
4864
+ "keys": "Shift+Tab",
4865
+ "effect": "Cycles focus backwards inside the open dialog."
4866
+ }
4454
4867
  ]
4455
4868
  },
4456
4869
  "StackedCardRail": {
@@ -4470,6 +4883,7 @@
4470
4883
  "sizing": "panel"
4471
4884
  },
4472
4885
  "consumers": [
4886
+ "src/app/components/stacked-card-rail.test.tsx",
4473
4887
  "src/index.ts",
4474
4888
  "src/stories/stacked-card-rail.stories.tsx"
4475
4889
  ],
@@ -4519,13 +4933,21 @@
4519
4933
  "src/app/components/animated-label.tsx",
4520
4934
  "src/app/components/button-group.test.tsx",
4521
4935
  "src/app/components/button-group.tsx",
4936
+ "src/app/components/button.test.tsx",
4937
+ "src/app/components/card.test.tsx",
4522
4938
  "src/app/components/card.tsx",
4939
+ "src/app/components/command-palette.tsx",
4940
+ "src/app/components/data-table-section.tsx",
4941
+ "src/app/components/destructive-section.tsx",
4523
4942
  "src/app/components/dialog.tsx",
4524
4943
  "src/app/components/error-boundary.tsx",
4525
4944
  "src/app/components/error-pattern.tsx",
4945
+ "src/app/components/form-actions.tsx",
4526
4946
  "src/app/components/form.tsx",
4527
4947
  "src/app/components/icon-button.tsx",
4948
+ "src/app/components/icon.tsx",
4528
4949
  "src/app/components/image-lightbox.tsx",
4950
+ "src/app/components/inline-link.tsx",
4529
4951
  "src/app/components/menu.tsx",
4530
4952
  "src/app/components/multi-selector.tsx",
4531
4953
  "src/app/components/pagination.tsx",
@@ -4547,19 +4969,25 @@
4547
4969
  "src/stories/button.stories.tsx",
4548
4970
  "src/stories/code-block.stories.tsx",
4549
4971
  "src/stories/combobox.stories.tsx",
4972
+ "src/stories/data-table-section.stories.tsx",
4550
4973
  "src/stories/dialog.stories.tsx",
4974
+ "src/stories/form-actions.stories.tsx",
4551
4975
  "src/stories/form.stories.tsx",
4552
4976
  "src/stories/hds-tooltip.stories.tsx",
4553
4977
  "src/stories/icon-button.stories.tsx",
4554
4978
  "src/stories/image-lightbox.stories.tsx",
4555
4979
  "src/stories/inline-code.stories.tsx",
4980
+ "src/stories/lib/usage-description.test.ts",
4556
4981
  "src/stories/menu.stories.tsx",
4557
4982
  "src/stories/nav-group.stories.tsx",
4983
+ "src/stories/page-header.stories.tsx",
4984
+ "src/stories/patterns-client-detail.stories.tsx",
4558
4985
  "src/stories/patterns-layout.stories.tsx",
4559
4986
  "src/stories/popover.stories.tsx",
4560
4987
  "src/stories/table.stories.tsx",
4561
4988
  "src/stories/text-lockup.stories.tsx",
4562
4989
  "src/stories/toast.stories.tsx",
4990
+ "src/stories/toggle-button.stories.tsx",
4563
4991
  "src/stories/toolbar.stories.tsx",
4564
4992
  "src/stories/top-nav.stories.tsx"
4565
4993
  ],
@@ -4743,7 +5171,17 @@
4743
5171
  "primitives-button--secondary",
4744
5172
  "primitives-button--small",
4745
5173
  "primitives-button--tertiary"
4746
- ]
5174
+ ],
5175
+ "usage": {
5176
+ "when": "Trigger an action (submit, save, open a dialog) with a text label and optional icons; for an icon-only control pass iconOnly with iconLeft.",
5177
+ "whenNot": "Navigating to another page, where a link is the correct element.",
5178
+ "useInstead": [
5179
+ {
5180
+ "component": "InlineLink",
5181
+ "reason": "navigation to another page"
5182
+ }
5183
+ ]
5184
+ }
4747
5185
  },
4748
5186
  "Callout": {
4749
5187
  "category": "Feedback",
@@ -4829,7 +5267,7 @@
4829
5267
  "hidden": false,
4830
5268
  "docExempt": false,
4831
5269
  "filePath": "src/app/components/empty-state.tsx",
4832
- "description": "EmptyState — consistent no-data placeholder for lists, grids, and sections. communicate \"no data yet\" with consistent muted typography instead of agents inventing one-off `<p>No items.</p>` lines. use for full-page errors (use ErrorPage) or for loading states (use a skeleton). Do NOT wrap in Surface or Card — the empty state is a typographic message, not a chrome-bearing container.",
5270
+ "description": "EmptyState — consistent no-data placeholder for lists, grids, and sections.",
4833
5271
  "figmaUrl": "https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-352",
4834
5272
  "figmaId": null,
4835
5273
  "figmaLink": "https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-352",
@@ -4839,7 +5277,9 @@
4839
5277
  "sizing": "panel"
4840
5278
  },
4841
5279
  "consumers": [
5280
+ "src/app/components/data-table-section.tsx",
4842
5281
  "src/docs-tooling/lab/legacy-token-detail.tsx",
5282
+ "src/stories/data-table-section.stories.tsx",
4843
5283
  "src/stories/empty-state.stories.tsx",
4844
5284
  "src/stories/patterns-layout.stories.tsx"
4845
5285
  ],
@@ -4873,7 +5313,22 @@
4873
5313
  "primitives-empty-state--in-grid",
4874
5314
  "primitives-empty-state--title-only",
4875
5315
  "primitives-empty-state--with-description"
4876
- ]
5316
+ ],
5317
+ "usage": {
5318
+ "when": "Say that a list, grid or section has no data yet, with a title and an optional description.",
5319
+ "whenNot": "Content that is still loading, or a full-page error.",
5320
+ "useInstead": [
5321
+ {
5322
+ "component": "Skeleton",
5323
+ "reason": "content that is still loading"
5324
+ },
5325
+ {
5326
+ "component": "Alert",
5327
+ "reason": "a message about something that went wrong"
5328
+ }
5329
+ ]
5330
+ },
5331
+ "aiRules": "Use only for inline empty states inside an existing section. Do NOT use for full-page errors (use ErrorPage) or for loading states (use a skeleton). Do NOT wrap in Surface or Card — the empty state is a typographic message, not a chrome-bearing container."
4877
5332
  },
4878
5333
  "Field": {
4879
5334
  "category": "Display",
@@ -4895,11 +5350,13 @@
4895
5350
  "src/app/components/combobox.tsx",
4896
5351
  "src/app/components/form.tsx",
4897
5352
  "src/app/components/input.tsx",
5353
+ "src/app/components/table.tsx",
4898
5354
  "src/app/components/textarea.tsx",
4899
5355
  "src/form/hds-form.tsx",
4900
5356
  "src/stories/field.stories.tsx",
4901
5357
  "src/stories/patterns-layout.stories.tsx",
4902
- "src/stories/sketch.stories.tsx"
5358
+ "src/stories/sketch.stories.tsx",
5359
+ "src/stories/stepper-field.stories.tsx"
4903
5360
  ],
4904
5361
  "tokenMapping": {},
4905
5362
  "variantAxes": [],
@@ -4969,7 +5426,21 @@
4969
5426
  "primitives-field--success",
4970
5427
  "primitives-field--warning",
4971
5428
  "primitives-field--with-children"
4972
- ]
5429
+ ],
5430
+ "usage": {
5431
+ "when": "Show a labelled read-only value, such as a name and its value in a detail view.",
5432
+ "whenNot": "Editable input, or a single headline figure.",
5433
+ "useInstead": [
5434
+ {
5435
+ "component": "Input",
5436
+ "reason": "an editable single-line value"
5437
+ },
5438
+ {
5439
+ "component": "Card.Metric",
5440
+ "reason": "a headline figure inside a Card"
5441
+ }
5442
+ ]
5443
+ }
4973
5444
  },
4974
5445
  "Page": {
4975
5446
  "category": "Layout",
@@ -4992,6 +5463,7 @@
4992
5463
  "src/app/components/not-found-pattern.tsx",
4993
5464
  "src/app/components/pagination.test.tsx",
4994
5465
  "src/app/components/pagination.tsx",
5466
+ "src/app/components/surface.tsx",
4995
5467
  "src/app/components/toast.tsx",
4996
5468
  "src/app/design-system/generated-token-descriptions.ts",
4997
5469
  "src/brand/overlay.ts",
@@ -5072,6 +5544,8 @@
5072
5544
  "sizing": "panel"
5073
5545
  },
5074
5546
  "consumers": [
5547
+ "src/app/components/metric-tiles.tsx",
5548
+ "src/stories/metric-tiles.stories.tsx",
5075
5549
  "src/stories/stat.stories.tsx"
5076
5550
  ],
5077
5551
  "tokenMapping": {},
@@ -5134,7 +5608,21 @@
5134
5608
  "primitives-stat--success",
5135
5609
  "primitives-stat--warning",
5136
5610
  "primitives-stat--with-sub"
5137
- ]
5611
+ ],
5612
+ "usage": {
5613
+ "when": "Show one standalone headline figure with its label and an optional sub-line.",
5614
+ "whenNot": "A figure inside a Card, or a status with a trailing badge.",
5615
+ "useInstead": [
5616
+ {
5617
+ "component": "Card.Metric",
5618
+ "reason": "a figure inside a Card (hds#254 folds Stat into the Card slot)"
5619
+ },
5620
+ {
5621
+ "component": "StatusTile",
5622
+ "reason": "a titled status with notes and a trailing badge"
5623
+ }
5624
+ ]
5625
+ }
5138
5626
  },
5139
5627
  "StatusListItem": {
5140
5628
  "category": "Display",
@@ -5154,6 +5642,7 @@
5154
5642
  },
5155
5643
  "consumers": [
5156
5644
  "src/app/components/status-tile.tsx",
5645
+ "src/stories/status-list-item.stories.test.tsx",
5157
5646
  "src/stories/status-list-item.stories.tsx"
5158
5647
  ],
5159
5648
  "tokenMapping": {},
@@ -5234,7 +5723,11 @@
5234
5723
  "sizing": "panel"
5235
5724
  },
5236
5725
  "consumers": [
5726
+ "src/app/components/metric-tiles.tsx",
5727
+ "src/app/components/stat.tsx",
5728
+ "src/stories/metric-tiles.stories.tsx",
5237
5729
  "src/stories/status-list-item.stories.tsx",
5730
+ "src/stories/status-tile.stories.test.tsx",
5238
5731
  "src/stories/status-tile.stories.tsx"
5239
5732
  ],
5240
5733
  "tokenMapping": {},
@@ -5279,7 +5772,21 @@
5279
5772
  "primitives-status-tile--tile-grid",
5280
5773
  "primitives-status-tile--warning",
5281
5774
  "primitives-status-tile--with-trailing-badge"
5282
- ]
5775
+ ],
5776
+ "usage": {
5777
+ "when": "Show a titled status block with optional notes and a trailing badge or affordance.",
5778
+ "whenNot": "A single headline figure, or a row inside a list.",
5779
+ "useInstead": [
5780
+ {
5781
+ "component": "Card.Metric",
5782
+ "reason": "a headline figure (hds#254 folds StatusTile into the Card slot)"
5783
+ },
5784
+ {
5785
+ "component": "StatusListItem",
5786
+ "reason": "a status row inside a list"
5787
+ }
5788
+ ]
5789
+ }
5283
5790
  },
5284
5791
  "TileGrid": {
5285
5792
  "category": "Layout",
@@ -5298,6 +5805,7 @@
5298
5805
  "sizing": "panel"
5299
5806
  },
5300
5807
  "consumers": [
5808
+ "src/stories/status-tile.stories.test.tsx",
5301
5809
  "src/stories/status-tile.stories.tsx",
5302
5810
  "src/stories/tile-grid.stories.tsx"
5303
5811
  ],
@@ -5375,7 +5883,10 @@
5375
5883
  },
5376
5884
  "consumers": [
5377
5885
  "src/app/components/alert.tsx",
5886
+ "src/app/components/avatar.tsx",
5378
5887
  "src/app/components/card.tsx",
5888
+ "src/app/components/page-header.tsx",
5889
+ "src/app/components/tag.tsx",
5379
5890
  "src/app/data/hdsEditorial.tsx",
5380
5891
  "src/app/design-system/generated-token-descriptions.ts",
5381
5892
  "src/docs-tooling/lab/legacy-token-detail.tsx",
@@ -5384,9 +5895,16 @@
5384
5895
  "src/stories/code-block.stories.tsx",
5385
5896
  "src/stories/combobox.stories.tsx",
5386
5897
  "src/stories/component-instance-matrix.stories.tsx",
5898
+ "src/stories/data-table-section.stories.tsx",
5387
5899
  "src/stories/nav-group.stories.tsx",
5900
+ "src/stories/page-header.stories.tsx",
5901
+ "src/stories/patterns-client-detail.stories.tsx",
5388
5902
  "src/stories/patterns-layout.stories.tsx",
5389
5903
  "src/stories/static-primitives.stories.tsx",
5904
+ "src/stories/status-list-item.stories.test.tsx",
5905
+ "src/stories/status-list-item.stories.tsx",
5906
+ "src/stories/status-tile.stories.test.tsx",
5907
+ "src/stories/status-tile.stories.tsx",
5390
5908
  "src/stories/table.stories.tsx"
5391
5909
  ],
5392
5910
  "tokenMapping": {},
@@ -5400,7 +5918,21 @@
5400
5918
  "primitives-badge--neutral",
5401
5919
  "primitives-badge--success",
5402
5920
  "primitives-badge--warning"
5403
- ]
5921
+ ],
5922
+ "usage": {
5923
+ "when": "Label a status, state or count with a compact neutral or semantic chip.",
5924
+ "whenNot": "A chip people can toggle, or a message that needs a sentence.",
5925
+ "useInstead": [
5926
+ {
5927
+ "component": "Tag",
5928
+ "reason": "an interactive filter or category chip"
5929
+ },
5930
+ {
5931
+ "component": "Alert",
5932
+ "reason": "a message that needs a sentence"
5933
+ }
5934
+ ]
5935
+ }
5404
5936
  },
5405
5937
  "TextLockup": {
5406
5938
  "variantAxes": [
@@ -5469,7 +6001,8 @@
5469
6001
  "primitives-text-lockup--numbered",
5470
6002
  "primitives-text-lockup--section",
5471
6003
  "primitives-text-lockup--with-eyebrow"
5472
- ]
6004
+ ],
6005
+ "aiRules": "Use TextLockup when content is a semantic title lockup with optional eyebrow and supporting text. Do NOT use TextLockup for arbitrary prose groups, data tables, or freeform mixed layouts. Do NOT restyle the internal type pairing with custom heading stacks when an existing size already fits. Do NOT use TextLockup to replace standalone body text or labels that do not form a title-description unit."
5473
6006
  },
5474
6007
  "AssetImg": {
5475
6008
  "category": "Display",
@@ -5488,6 +6021,7 @@
5488
6021
  "sizing": "panel"
5489
6022
  },
5490
6023
  "consumers": [
6024
+ "src/app/components/asset-img.test.tsx",
5491
6025
  "src/app/components/hds-tooltip.tsx",
5492
6026
  "src/app/components/image-lightbox.tsx",
5493
6027
  "src/app/components/tooltip.tsx",
@@ -5663,7 +6197,11 @@
5663
6197
  "sizing": "panel"
5664
6198
  },
5665
6199
  "consumers": [
6200
+ "src/app/components/breadcrumb.tsx",
6201
+ "src/app/components/disclosure.tsx",
6202
+ "src/app/components/segmented-control.tsx",
5666
6203
  "src/stories/combobox.stories.tsx",
6204
+ "src/stories/patterns-client-detail.stories.tsx",
5667
6205
  "src/stories/tabs.stories.tsx"
5668
6206
  ],
5669
6207
  "tokenMapping": {},
@@ -5689,7 +6227,21 @@
5689
6227
  "primitives-tabs--default",
5690
6228
  "primitives-tabs--many-tabs",
5691
6229
  "primitives-tabs--with-disabled-tab"
5692
- ]
6230
+ ],
6231
+ "usage": {
6232
+ "when": "Switch between panels of related content in the same place, one visible at a time.",
6233
+ "whenNot": "A compact mode switch with no panels, or content that must all be visible.",
6234
+ "useInstead": [
6235
+ {
6236
+ "component": "SegmentedControl",
6237
+ "reason": "a compact switch with no panels"
6238
+ },
6239
+ {
6240
+ "component": "Disclosure",
6241
+ "reason": "optional content that expands in place"
6242
+ }
6243
+ ]
6244
+ }
5693
6245
  },
5694
6246
  "TabsContent": {
5695
6247
  "category": "Navigation",
@@ -5708,6 +6260,7 @@
5708
6260
  "sizing": "panel"
5709
6261
  },
5710
6262
  "consumers": [
6263
+ "src/stories/patterns-client-detail.stories.tsx",
5711
6264
  "src/stories/tabs.stories.tsx"
5712
6265
  ],
5713
6266
  "tokenMapping": {},
@@ -5752,6 +6305,7 @@
5752
6305
  "sizing": "panel"
5753
6306
  },
5754
6307
  "consumers": [
6308
+ "src/stories/patterns-client-detail.stories.tsx",
5755
6309
  "src/stories/tabs.stories.tsx"
5756
6310
  ],
5757
6311
  "tokenMapping": {},
@@ -5796,6 +6350,7 @@
5796
6350
  "sizing": "panel"
5797
6351
  },
5798
6352
  "consumers": [
6353
+ "src/stories/patterns-client-detail.stories.tsx",
5799
6354
  "src/stories/tabs.stories.tsx"
5800
6355
  ],
5801
6356
  "tokenMapping": {},
@@ -5839,6 +6394,8 @@
5839
6394
  "consumers": [
5840
6395
  "src/app/components/checkbox.tsx",
5841
6396
  "src/app/components/radio.test.tsx",
6397
+ "src/app/components/segmented-control.tsx",
6398
+ "src/app/components/toggle.tsx",
5842
6399
  "src/app/hooks/useInteractionState.test.ts",
5843
6400
  "src/app/hooks/useInteractionState.ts",
5844
6401
  "src/index.ts",
@@ -5889,7 +6446,25 @@
5889
6446
  "primitives-radio--disabled-selected",
5890
6447
  "primitives-radio--group",
5891
6448
  "primitives-radio--selected"
5892
- ]
6449
+ ],
6450
+ "usage": {
6451
+ "when": "Choose exactly one option from a small set that should stay visible together.",
6452
+ "whenNot": "Independent yes/no options, or a long list of options.",
6453
+ "useInstead": [
6454
+ {
6455
+ "component": "Checkbox",
6456
+ "reason": "independent options that can be ticked together"
6457
+ },
6458
+ {
6459
+ "component": "Select",
6460
+ "reason": "a long list that can collapse into a dropdown"
6461
+ },
6462
+ {
6463
+ "component": "SegmentedControl",
6464
+ "reason": "a compact switch between two to five views or modes"
6465
+ }
6466
+ ]
6467
+ }
5893
6468
  },
5894
6469
  "Select": {
5895
6470
  "category": "Inputs",
@@ -5911,9 +6486,15 @@
5911
6486
  "src/app/components/date-range-input.test.tsx",
5912
6487
  "src/app/components/date-range-input.tsx",
5913
6488
  "src/app/components/form.tsx",
6489
+ "src/app/components/input.tsx",
6490
+ "src/app/components/menu.tsx",
5914
6491
  "src/app/components/multi-selector.test.tsx",
5915
6492
  "src/app/components/multi-selector.tsx",
6493
+ "src/app/components/radio.tsx",
6494
+ "src/app/components/segmented-control.tsx",
5916
6495
  "src/app/components/select.test.tsx",
6496
+ "src/app/context/__tests__/portal-hydration.test.tsx",
6497
+ "src/app/context/__tests__/portal-scope.test.tsx",
5917
6498
  "src/app/data/hdsEditorial.tsx",
5918
6499
  "src/docs-tooling/lab/legacy-token-detail.tsx",
5919
6500
  "src/index.ts",
@@ -5964,6 +6545,50 @@
5964
6545
  "storyIds": [
5965
6546
  "primitives-select--default",
5966
6547
  "primitives-select--no-label"
6548
+ ],
6549
+ "usage": {
6550
+ "when": "Choose one value from a short list of options in a form field.",
6551
+ "whenNot": "Firing actions, or choosing from a list long enough to need search.",
6552
+ "useInstead": [
6553
+ {
6554
+ "component": "Menu",
6555
+ "reason": "firing actions from a trigger"
6556
+ },
6557
+ {
6558
+ "component": "Combobox",
6559
+ "reason": "a long list that needs search"
6560
+ }
6561
+ ]
6562
+ },
6563
+ "keyboard": [
6564
+ {
6565
+ "keys": "Enter/Space/ArrowDown",
6566
+ "effect": "Opens the listbox from the trigger with the selected option highlighted."
6567
+ },
6568
+ {
6569
+ "keys": "ArrowDown/ArrowUp",
6570
+ "effect": "Moves the highlight."
6571
+ },
6572
+ {
6573
+ "keys": "Home/End",
6574
+ "effect": "Jumps to the first or last option."
6575
+ },
6576
+ {
6577
+ "keys": "Character",
6578
+ "effect": "Highlights the option that matches the typed letters."
6579
+ },
6580
+ {
6581
+ "keys": "Enter",
6582
+ "effect": "Commits the highlighted option and returns focus to the trigger."
6583
+ },
6584
+ {
6585
+ "keys": "Escape",
6586
+ "effect": "Closes the listbox and returns focus to the trigger."
6587
+ },
6588
+ {
6589
+ "keys": "Tab",
6590
+ "effect": "Does not leave the open listbox."
6591
+ }
5967
6592
  ]
5968
6593
  },
5969
6594
  "Slider": {
@@ -6029,7 +6654,17 @@
6029
6654
  "primitives-slider--default",
6030
6655
  "primitives-slider--stepped",
6031
6656
  "primitives-slider--typography-controls"
6032
- ]
6657
+ ],
6658
+ "usage": {
6659
+ "when": "Pick a number within a known range by dragging, when the exact value matters less than the position.",
6660
+ "whenNot": "A precise number the person must type or read exactly.",
6661
+ "useInstead": [
6662
+ {
6663
+ "component": "Input",
6664
+ "reason": "a precise typed value (type=\"number\")"
6665
+ }
6666
+ ]
6667
+ }
6033
6668
  },
6034
6669
  "Toggle": {
6035
6670
  "category": "Inputs",
@@ -6054,6 +6689,7 @@
6054
6689
  "src/app/hooks/useInteractionState.ts",
6055
6690
  "src/docs-tooling/shell-controls.tsx",
6056
6691
  "src/index.ts",
6692
+ "src/stories/toggle-button.stories.tsx",
6057
6693
  "src/stories/toggle.stories.tsx"
6058
6694
  ],
6059
6695
  "tokenMapping": {
@@ -6101,7 +6737,21 @@
6101
6737
  "primitives-toggle--disabled-on",
6102
6738
  "primitives-toggle--on",
6103
6739
  "primitives-toggle--settings-group"
6104
- ]
6740
+ ],
6741
+ "usage": {
6742
+ "when": "Switch one setting on or off, with the effect applying immediately.",
6743
+ "whenNot": "A choice that only takes effect after submitting a form, or picking from several options.",
6744
+ "useInstead": [
6745
+ {
6746
+ "component": "Checkbox",
6747
+ "reason": "a form option confirmed on submit"
6748
+ },
6749
+ {
6750
+ "component": "Radio",
6751
+ "reason": "one choice from a set"
6752
+ }
6753
+ ]
6754
+ }
6105
6755
  },
6106
6756
  "Avatar": {
6107
6757
  "category": "Display",
@@ -6123,6 +6773,7 @@
6123
6773
  "src/app/components/avatar-group.test.tsx",
6124
6774
  "src/app/components/avatar-group.tsx",
6125
6775
  "src/app/components/avatar.test.tsx",
6776
+ "src/app/components/icon.tsx",
6126
6777
  "src/app/design-system/generated-token-descriptions.ts",
6127
6778
  "src/stories/avatar-group.stories.tsx",
6128
6779
  "src/stories/avatar.stories.tsx"
@@ -6170,7 +6821,21 @@
6170
6821
  "primitives-avatar--large",
6171
6822
  "primitives-avatar--small",
6172
6823
  "primitives-avatar--with-image"
6173
- ]
6824
+ ],
6825
+ "usage": {
6826
+ "when": "Show a person or entity as an image with an initials fallback.",
6827
+ "whenNot": "A generic pictogram, or a status marker.",
6828
+ "useInstead": [
6829
+ {
6830
+ "component": "Icon",
6831
+ "reason": "a generic pictogram"
6832
+ },
6833
+ {
6834
+ "component": "Badge",
6835
+ "reason": "a status marker"
6836
+ }
6837
+ ]
6838
+ }
6174
6839
  },
6175
6840
  "Progress": {
6176
6841
  "category": "Feedback",
@@ -6189,8 +6854,12 @@
6189
6854
  "sizing": "panel"
6190
6855
  },
6191
6856
  "consumers": [
6857
+ "src/app/components/card-progress.test.tsx",
6858
+ "src/app/components/card.test.tsx",
6192
6859
  "src/app/components/card.tsx",
6193
6860
  "src/app/components/progress.test.tsx",
6861
+ "src/app/components/skeleton.tsx",
6862
+ "src/app/components/spinner.tsx",
6194
6863
  "src/stories/card.stories.tsx",
6195
6864
  "src/stories/circular-progress.stories.tsx",
6196
6865
  "src/stories/progress.stories.tsx",
@@ -6232,7 +6901,21 @@
6232
6901
  "primitives-progress--complete",
6233
6902
  "primitives-progress--default",
6234
6903
  "primitives-progress--indeterminate"
6235
- ]
6904
+ ],
6905
+ "usage": {
6906
+ "when": "Show how far a task has got, as a bar that is determinate or indeterminate.",
6907
+ "whenNot": "A wait of unknown length with no bar, or content that is still loading.",
6908
+ "useInstead": [
6909
+ {
6910
+ "component": "Spinner",
6911
+ "reason": "a wait of unknown length"
6912
+ },
6913
+ {
6914
+ "component": "Skeleton",
6915
+ "reason": "placeholder shapes for loading content"
6916
+ }
6917
+ ]
6918
+ }
6236
6919
  },
6237
6920
  "Skeleton": {
6238
6921
  "category": "Feedback",
@@ -6251,7 +6934,10 @@
6251
6934
  "sizing": "panel"
6252
6935
  },
6253
6936
  "consumers": [
6937
+ "src/app/components/empty-state.tsx",
6938
+ "src/app/components/progress.tsx",
6254
6939
  "src/app/components/skeleton.test.tsx",
6940
+ "src/app/components/spinner.tsx",
6255
6941
  "src/stories/patterns-layout.stories.tsx",
6256
6942
  "src/stories/patterns-scroll.stories.tsx",
6257
6943
  "src/stories/skeleton.stories.tsx"
@@ -6293,7 +6979,21 @@
6293
6979
  "primitives-skeleton--circular",
6294
6980
  "primitives-skeleton--default",
6295
6981
  "primitives-skeleton--text"
6296
- ]
6982
+ ],
6983
+ "usage": {
6984
+ "when": "Reserve the shape of content that is still loading, so the layout does not jump.",
6985
+ "whenNot": "A task with measurable progress, or a wait with no layout to reserve.",
6986
+ "useInstead": [
6987
+ {
6988
+ "component": "Progress",
6989
+ "reason": "a task with measurable progress"
6990
+ },
6991
+ {
6992
+ "component": "Spinner",
6993
+ "reason": "a short wait with no layout to reserve"
6994
+ }
6995
+ ]
6996
+ }
6297
6997
  },
6298
6998
  "Spinner": {
6299
6999
  "category": "Feedback",
@@ -6312,6 +7012,8 @@
6312
7012
  "sizing": "panel"
6313
7013
  },
6314
7014
  "consumers": [
7015
+ "src/app/components/progress.tsx",
7016
+ "src/app/components/skeleton.tsx",
6315
7017
  "src/app/components/spinner.test.tsx",
6316
7018
  "src/stories/spinner.stories.tsx"
6317
7019
  ],
@@ -6349,7 +7051,21 @@
6349
7051
  "primitives-spinner--default",
6350
7052
  "primitives-spinner--large",
6351
7053
  "primitives-spinner--small"
6352
- ]
7054
+ ],
7055
+ "usage": {
7056
+ "when": "Show that something is loading when the wait is short or has no measurable end.",
7057
+ "whenNot": "A task with measurable progress, or a region whose layout is known.",
7058
+ "useInstead": [
7059
+ {
7060
+ "component": "Progress",
7061
+ "reason": "a task with measurable progress"
7062
+ },
7063
+ {
7064
+ "component": "Skeleton",
7065
+ "reason": "a region whose layout is known"
7066
+ }
7067
+ ]
7068
+ }
6353
7069
  },
6354
7070
  "Breadcrumb": {
6355
7071
  "category": "Navigation",
@@ -6369,8 +7085,12 @@
6369
7085
  },
6370
7086
  "consumers": [
6371
7087
  "src/app/components/breadcrumb.test.tsx",
7088
+ "src/app/components/page-header.tsx",
7089
+ "src/app/components/pagination.tsx",
6372
7090
  "src/app/components/table.tsx",
6373
- "src/stories/breadcrumb.stories.tsx"
7091
+ "src/stories/breadcrumb.stories.tsx",
7092
+ "src/stories/page-header.stories.tsx",
7093
+ "src/stories/patterns-client-detail.stories.tsx"
6374
7094
  ],
6375
7095
  "tokenMapping": {},
6376
7096
  "variantAxes": [],
@@ -6399,7 +7119,21 @@
6399
7119
  "primitives-breadcrumb--default",
6400
7120
  "primitives-breadcrumb--shallow-trail",
6401
7121
  "primitives-breadcrumb--single-crumb"
6402
- ]
7122
+ ],
7123
+ "usage": {
7124
+ "when": "Show where the current page sits in a hierarchy and link back up it.",
7125
+ "whenNot": "Switching between sibling views, or stepping through pages of results.",
7126
+ "useInstead": [
7127
+ {
7128
+ "component": "Tabs",
7129
+ "reason": "switching between sibling views"
7130
+ },
7131
+ {
7132
+ "component": "Pagination",
7133
+ "reason": "stepping through pages of results"
7134
+ }
7135
+ ]
7136
+ }
6403
7137
  },
6404
7138
  "Pagination": {
6405
7139
  "category": "Navigation",
@@ -6418,6 +7152,7 @@
6418
7152
  "sizing": "panel"
6419
7153
  },
6420
7154
  "consumers": [
7155
+ "src/app/components/breadcrumb.tsx",
6421
7156
  "src/app/components/pagination.test.tsx",
6422
7157
  "src/stories/pagination.stories.tsx"
6423
7158
  ],
@@ -6458,7 +7193,17 @@
6458
7193
  "primitives-pagination--last-page",
6459
7194
  "primitives-pagination--middle-page",
6460
7195
  "primitives-pagination--wide-siblings"
6461
- ]
7196
+ ],
7197
+ "usage": {
7198
+ "when": "Move between pages of a long result set, with truncated page numbers.",
7199
+ "whenNot": "A hierarchy trail, or a short list that fits on one page.",
7200
+ "useInstead": [
7201
+ {
7202
+ "component": "Breadcrumb",
7203
+ "reason": "a hierarchy trail"
7204
+ }
7205
+ ]
7206
+ }
6462
7207
  },
6463
7208
  "ToastProvider": {
6464
7209
  "category": "Feedback",
@@ -6477,6 +7222,8 @@
6477
7222
  "sizing": "panel"
6478
7223
  },
6479
7224
  "consumers": [
7225
+ "src/app/components/alert.tsx",
7226
+ "src/app/components/dialog.tsx",
6480
7227
  "src/app/components/toast.test.tsx",
6481
7228
  "src/stories/toast.stories.tsx"
6482
7229
  ],
@@ -6508,7 +7255,21 @@
6508
7255
  "primitives-toast--info",
6509
7256
  "primitives-toast--success",
6510
7257
  "primitives-toast--warning"
6511
- ]
7258
+ ],
7259
+ "usage": {
7260
+ "when": "Confirm an action with a brief message that appears and dismisses itself, through useToast.",
7261
+ "whenNot": "A message people must act on or that must stay next to its content.",
7262
+ "useInstead": [
7263
+ {
7264
+ "component": "Alert",
7265
+ "reason": "a message that stays next to its content"
7266
+ },
7267
+ {
7268
+ "component": "Dialog",
7269
+ "reason": "a message that needs a decision"
7270
+ }
7271
+ ]
7272
+ }
6512
7273
  },
6513
7274
  "Combobox": {
6514
7275
  "category": "Inputs",
@@ -6530,7 +7291,9 @@
6530
7291
  "src/app/components/combobox.test.tsx",
6531
7292
  "src/app/components/date-range-input.tsx",
6532
7293
  "src/app/components/form.tsx",
7294
+ "src/app/components/input.tsx",
6533
7295
  "src/app/components/multi-selector.tsx",
7296
+ "src/app/components/select.tsx",
6534
7297
  "src/stories/combobox.stories.tsx",
6535
7298
  "src/stories/popover.stories.tsx"
6536
7299
  ],
@@ -6587,6 +7350,46 @@
6587
7350
  "primitives-combobox--few-options",
6588
7351
  "primitives-combobox--pre-selected",
6589
7352
  "primitives-combobox--with-disabled-option"
7353
+ ],
7354
+ "usage": {
7355
+ "when": "Pick one value from a long list of options, with a search field that filters as you type.",
7356
+ "whenNot": "A short list that needs no search, or an action list.",
7357
+ "useInstead": [
7358
+ {
7359
+ "component": "Select",
7360
+ "reason": "a short list without search"
7361
+ },
7362
+ {
7363
+ "component": "Menu",
7364
+ "reason": "firing actions from a trigger"
7365
+ }
7366
+ ]
7367
+ },
7368
+ "keyboard": [
7369
+ {
7370
+ "keys": "Enter/Space",
7371
+ "effect": "Opens the list from the trigger and moves focus to the search field."
7372
+ },
7373
+ {
7374
+ "keys": "ArrowDown/ArrowUp",
7375
+ "effect": "Moves the active option and wraps at the ends."
7376
+ },
7377
+ {
7378
+ "keys": "Character",
7379
+ "effect": "Filters the options to those matching the typed text."
7380
+ },
7381
+ {
7382
+ "keys": "Enter",
7383
+ "effect": "Commits the active option and closes the list."
7384
+ },
7385
+ {
7386
+ "keys": "Escape",
7387
+ "effect": "Closes the list."
7388
+ },
7389
+ {
7390
+ "keys": "Tab",
7391
+ "effect": "Stays inside the open list."
7392
+ }
6590
7393
  ]
6591
7394
  },
6592
7395
  "Form": {
@@ -6606,12 +7409,14 @@
6606
7409
  "sizing": "panel"
6607
7410
  },
6608
7411
  "consumers": [
7412
+ "src/app/components/form-actions.tsx",
6609
7413
  "src/app/components/form.test.tsx",
6610
7414
  "src/app/data/hdsEditorial.tsx",
6611
7415
  "src/form/hds-form.tsx",
6612
7416
  "src/form/index.ts",
6613
7417
  "src/form/use-hds-form.ts",
6614
7418
  "src/index.ts",
7419
+ "src/stories/form-actions.stories.tsx",
6615
7420
  "src/stories/form.stories.tsx",
6616
7421
  "src/stories/patterns-layout.stories.tsx"
6617
7422
  ],
@@ -6788,6 +7593,9 @@
6788
7593
  },
6789
7594
  "consumers": [
6790
7595
  "src/app/context/__tests__/context.test.tsx",
7596
+ "src/app/context/__tests__/portal-hydration.test.tsx",
7597
+ "src/app/context/__tests__/portal-scope.test.tsx",
7598
+ "src/app/context/hds-portal.tsx",
6791
7599
  "src/index.ts"
6792
7600
  ],
6793
7601
  "tokenMapping": {},
@@ -6842,7 +7650,17 @@
6842
7650
  "requiredProps": [],
6843
7651
  "a11yRules": [],
6844
7652
  "storyFiles": [],
6845
- "storyIds": []
7653
+ "storyIds": [],
7654
+ "usage": {
7655
+ "when": "Wrap an app or region once to set theme, density and other root attributes for everything inside it.",
7656
+ "whenNot": "Styling a single component, or per-component overrides.",
7657
+ "useInstead": [
7658
+ {
7659
+ "component": "Surface",
7660
+ "reason": "a single region with its own background"
7661
+ }
7662
+ ]
7663
+ }
6846
7664
  },
6847
7665
  "AvatarGroup": {
6848
7666
  "category": "Display",
@@ -6993,7 +7811,21 @@
6993
7811
  "storyIds": [
6994
7812
  "primitives-button-group--default",
6995
7813
  "primitives-button-group--vertical"
6996
- ]
7814
+ ],
7815
+ "usage": {
7816
+ "when": "Attach related Buttons into one segmented row or column that reads as a single control.",
7817
+ "whenNot": "Buttons that are unrelated, or choosing one of several views.",
7818
+ "useInstead": [
7819
+ {
7820
+ "component": "SegmentedControl",
7821
+ "reason": "choosing one of several views"
7822
+ },
7823
+ {
7824
+ "component": "Stack",
7825
+ "reason": "loosely spaced buttons"
7826
+ }
7827
+ ]
7828
+ }
6997
7829
  },
6998
7830
  "InputGroup": {
6999
7831
  "category": "Inputs",
@@ -7073,6 +7905,7 @@
7073
7905
  },
7074
7906
  "consumers": [
7075
7907
  "src/app/components/kbd.test.tsx",
7908
+ "src/app/components/text.tsx",
7076
7909
  "src/stories/kbd.stories.tsx"
7077
7910
  ],
7078
7911
  "tokenMapping": {},
@@ -7102,7 +7935,17 @@
7102
7935
  "primitives-kbd--combination",
7103
7936
  "primitives-kbd--default",
7104
7937
  "primitives-kbd--sizes"
7105
- ]
7938
+ ],
7939
+ "usage": {
7940
+ "when": "Show a keyboard key or shortcut hint inline, as a native kbd element.",
7941
+ "whenNot": "Code samples, or a control that runs the shortcut.",
7942
+ "useInstead": [
7943
+ {
7944
+ "component": "Text",
7945
+ "reason": "inline code and other typography"
7946
+ }
7947
+ ]
7948
+ }
7106
7949
  },
7107
7950
  "StatusDot": {
7108
7951
  "category": "Feedback",
@@ -7269,7 +8112,17 @@
7269
8112
  ],
7270
8113
  "storyIds": [
7271
8114
  "primitives-visually-hidden--default"
7272
- ]
8115
+ ],
8116
+ "usage": {
8117
+ "when": "Give assistive technology a label or description that sighted people do not need to see.",
8118
+ "whenNot": "Text everyone should read, or hiding an element from assistive technology too.",
8119
+ "useInstead": [
8120
+ {
8121
+ "component": "Text",
8122
+ "reason": "text that everyone should read"
8123
+ }
8124
+ ]
8125
+ }
7273
8126
  },
7274
8127
  "CircularProgress": {
7275
8128
  "category": "Feedback",
@@ -7441,6 +8294,8 @@
7441
8294
  },
7442
8295
  "consumers": [
7443
8296
  "src/app/components/image-lightbox.test.tsx",
8297
+ "src/app/context/__tests__/portal-hydration.test.tsx",
8298
+ "src/app/context/__tests__/portal-scope.test.tsx",
7444
8299
  "src/app/data/hdsEditorial.tsx",
7445
8300
  "src/index.ts",
7446
8301
  "src/stories/asset-img.stories.tsx",
@@ -7938,6 +8793,7 @@
7938
8793
  "consumers": [
7939
8794
  "src/app/components/stepper.test.tsx",
7940
8795
  "src/index.ts",
8796
+ "src/stories/stepper-field.stories.tsx",
7941
8797
  "src/stories/stepper.stories.tsx"
7942
8798
  ],
7943
8799
  "tokenMapping": {},
@@ -7990,6 +8846,7 @@
7990
8846
  "sizing": "panel"
7991
8847
  },
7992
8848
  "consumers": [
8849
+ "src/app/components/data-table-section.tsx",
7993
8850
  "src/app/components/toolbar.test.tsx",
7994
8851
  "src/index.ts",
7995
8852
  "src/stories/toolbar.stories.tsx"
@@ -8085,7 +8942,12 @@
8085
8942
  },
8086
8943
  "consumers": [
8087
8944
  "src/app/components/alert-dialog.test.tsx",
8088
- "src/stories/alert-dialog.stories.tsx"
8945
+ "src/app/components/destructive-section.tsx",
8946
+ "src/app/context/__tests__/portal-hydration.test.tsx",
8947
+ "src/app/context/__tests__/portal-scope.test.tsx",
8948
+ "src/stories/alert-dialog.stories.tsx",
8949
+ "src/stories/destructive-section.stories.tsx",
8950
+ "src/styles/__tests__/scrim-and-color-scheme.test.ts"
8089
8951
  ],
8090
8952
  "tokenMapping": {},
8091
8953
  "variantAxes": [],
@@ -8101,6 +8963,7 @@
8101
8963
  "src/stories/alert-dialog.stories.tsx"
8102
8964
  ],
8103
8965
  "storyIds": [
8966
+ "primitives-alert-dialog--dark-scope",
8104
8967
  "primitives-alert-dialog--default"
8105
8968
  ]
8106
8969
  },
@@ -8216,6 +9079,8 @@
8216
9079
  },
8217
9080
  "consumers": [
8218
9081
  "src/app/components/context-menu.test.tsx",
9082
+ "src/app/context/__tests__/portal-hydration.test.tsx",
9083
+ "src/app/context/__tests__/portal-scope.test.tsx",
8219
9084
  "src/stories/context-menu.stories.tsx"
8220
9085
  ],
8221
9086
  "tokenMapping": {},
@@ -8233,6 +9098,54 @@
8233
9098
  ],
8234
9099
  "storyIds": [
8235
9100
  "primitives-context-menu--default"
9101
+ ],
9102
+ "slots": [
9103
+ {
9104
+ "name": "trigger",
9105
+ "description": "The area that opens the menu on right-click (ContextMenu.Trigger).",
9106
+ "source": "jsdoc"
9107
+ },
9108
+ {
9109
+ "name": "content",
9110
+ "description": "The popup holding the items (ContextMenu.Content).",
9111
+ "source": "jsdoc"
9112
+ }
9113
+ ],
9114
+ "usage": {
9115
+ "when": "Offer actions for an item on right-click, or the equivalent keyboard gesture.",
9116
+ "whenNot": "The only way to reach an action, or actions from a visible trigger.",
9117
+ "useInstead": [
9118
+ {
9119
+ "component": "Menu",
9120
+ "reason": "actions from a visible trigger"
9121
+ }
9122
+ ]
9123
+ },
9124
+ "keyboard": [
9125
+ {
9126
+ "keys": "ArrowDown/ArrowUp",
9127
+ "effect": "Moves the highlight and stops at the first and last item."
9128
+ },
9129
+ {
9130
+ "keys": "End",
9131
+ "effect": "Jumps to the last item."
9132
+ },
9133
+ {
9134
+ "keys": "Character",
9135
+ "effect": "Highlights the next item that starts with the typed letter."
9136
+ },
9137
+ {
9138
+ "keys": "Enter",
9139
+ "effect": "Selects the highlighted item and closes the menu."
9140
+ },
9141
+ {
9142
+ "keys": "Escape",
9143
+ "effect": "Closes the menu without leaving focus inside the removed content."
9144
+ },
9145
+ {
9146
+ "keys": "Tab",
9147
+ "effect": "Does not leave the open menu."
9148
+ }
8236
9149
  ]
8237
9150
  },
8238
9151
  "DateInput": {
@@ -8454,7 +9367,10 @@
8454
9367
  "sizing": "panel"
8455
9368
  },
8456
9369
  "consumers": [
9370
+ "src/app/components/dialog.tsx",
8457
9371
  "src/app/components/hover-card.test.tsx",
9372
+ "src/app/context/__tests__/portal-hydration.test.tsx",
9373
+ "src/app/context/__tests__/portal-scope.test.tsx",
8458
9374
  "src/stories/hover-card.stories.tsx"
8459
9375
  ],
8460
9376
  "tokenMapping": {},
@@ -8472,6 +9388,46 @@
8472
9388
  ],
8473
9389
  "storyIds": [
8474
9390
  "primitives-hover-card--default"
9391
+ ],
9392
+ "slots": [
9393
+ {
9394
+ "name": "trigger",
9395
+ "description": "The link or element that opens the card (HoverCard.Trigger).",
9396
+ "source": "jsdoc"
9397
+ },
9398
+ {
9399
+ "name": "content",
9400
+ "description": "The preview (HoverCard.Content).",
9401
+ "source": "jsdoc"
9402
+ }
9403
+ ],
9404
+ "usage": {
9405
+ "when": "Preview extra detail about a link or mention when it is hovered or focused, without navigating.",
9406
+ "whenNot": "Content people must reach, or a label for an interactive control.",
9407
+ "useInstead": [
9408
+ {
9409
+ "component": "Dialog",
9410
+ "reason": "content people must act on"
9411
+ },
9412
+ {
9413
+ "component": "Tooltip",
9414
+ "reason": "a short label for a control"
9415
+ }
9416
+ ]
9417
+ },
9418
+ "keyboard": [
9419
+ {
9420
+ "keys": "Focus",
9421
+ "effect": "Opens the card when the trigger receives keyboard focus."
9422
+ },
9423
+ {
9424
+ "keys": "Escape",
9425
+ "effect": "Closes the card and keeps focus on the trigger."
9426
+ },
9427
+ {
9428
+ "keys": "Tab",
9429
+ "effect": "Moves on to the next element and closes the card."
9430
+ }
8475
9431
  ]
8476
9432
  },
8477
9433
  "MultiSelector": {
@@ -8653,7 +9609,7 @@
8653
9609
  "hidden": false,
8654
9610
  "docExempt": false,
8655
9611
  "filePath": "src/app/components/box.tsx",
8656
- "description": "Box — polymorphic layout primitive with a token-first `sx` engine. named primitive covers, without inviting ad hoc inline styles or raw hex/px values back into the system — the `sx` engine only accepts HDS token keys and a small, deliberate CSS subset. Box `sx` ONLY for genuinely one-off layout. sx colors/spacing MUST use token keys, not raw hex/px. Prefer named layout primitives over ad-hoc flex. `sx` is a deliberate SUBSET of MUI's sx — not all of CSS-in-JS is a feature: - Spacing shorthands (m/p/gap family) resolve numbers off the 4px HDS scale (`--primitive-space-<n>`) and named steps ('tight'|'normal'|'inset'|'spacious') off `--semantic-space-layout-*`. - `color`/`bgcolor`/`borderColor`/`fill`/`stroke` resolve dotted token keys ('content.primary', 'surface.raised', 'border.subtle', 'accent', 'accent.hover', 'feedback.success', …) to the matching semantic CSS var. - Responsive `{ xs, sm, md, lg, xl }` objects compile to `min-width` media queries off the HDS breakpoint scale. - `&`-prefixed keys ('&:hover', '& > *', '&[data-state=open]') nest a selector, composable with responsive values. - Everything else passes through as a plain camelCase→kebab-case CSS declaration (numbers get `px` unless in the unitless allowlist). See `box-sx.ts` for the pure resolver + hashing/injection engine.",
9612
+ "description": "Box — polymorphic layout primitive with a token-first `sx` engine. `sx` is a deliberate SUBSET of MUI's sx — not all of CSS-in-JS is a feature: - Spacing shorthands (m/p/gap family) resolve numbers off the 4px HDS scale (`--primitive-space-<n>`) and named steps ('tight'|'normal'|'inset'|'spacious') off `--semantic-space-layout-*`. - `color`/`bgcolor`/`borderColor`/`fill`/`stroke` resolve dotted token keys ('content.primary', 'surface.raised', 'border.subtle', 'accent', 'accent.hover', 'feedback.success', …) to the matching semantic CSS var. - Responsive `{ xs, sm, md, lg, xl }` objects compile to `min-width` media queries off the HDS breakpoint scale. - `&`-prefixed keys ('&:hover', '& > *', '&[data-state=open]') nest a selector, composable with responsive values. - Everything else passes through as a plain camelCase→kebab-case CSS declaration (numbers get `px` unless in the unitless allowlist). See `box-sx.ts` for the pure resolver + hashing/injection engine.",
8657
9613
  "figmaUrl": null,
8658
9614
  "figmaId": null,
8659
9615
  "figmaLink": null,
@@ -8671,6 +9627,7 @@
8671
9627
  "src/app/components/container.tsx",
8672
9628
  "src/app/components/cover.tsx",
8673
9629
  "src/app/components/frame.tsx",
9630
+ "src/app/components/grid.tsx",
8674
9631
  "src/app/components/sidebar.tsx",
8675
9632
  "src/app/components/switcher.tsx",
8676
9633
  "src/app/components/toggle.tsx",
@@ -8710,7 +9667,26 @@
8710
9667
  "primitives-box--responsive-values",
8711
9668
  "primitives-box--spacing-shorthands",
8712
9669
  "primitives-box--token-colors"
8713
- ]
9670
+ ],
9671
+ "usage": {
9672
+ "when": "Build one-off layout that no named layout primitive covers, using token keys through `sx`.",
9673
+ "whenNot": "Ordinary vertical or horizontal spacing, columns, or page-width constraint.",
9674
+ "useInstead": [
9675
+ {
9676
+ "component": "Stack",
9677
+ "reason": "a row or column of content with even gaps"
9678
+ },
9679
+ {
9680
+ "component": "Grid",
9681
+ "reason": "multi-column layout"
9682
+ },
9683
+ {
9684
+ "component": "Container",
9685
+ "reason": "a width-constrained page region"
9686
+ }
9687
+ ]
9688
+ },
9689
+ "aiRules": "Reach for Stack/Grid/Container/the every-layout primitives first. Use Box `sx` ONLY for genuinely one-off layout. sx colors/spacing MUST use token keys, not raw hex/px. Prefer named layout primitives over ad-hoc flex."
8714
9690
  },
8715
9691
  "Bleed": {
8716
9692
  "category": "Layout",
@@ -8719,7 +9695,7 @@
8719
9695
  "hidden": false,
8720
9696
  "docExempt": false,
8721
9697
  "filePath": "src/app/components/bleed.tsx",
8722
- "description": "Bleed — controlled negative-margin full-bleed within a padded container. padding\" (a full-width image inside a padded card, a divider that should touch both edges) with a single tokenized negative-margin wrapper, so agents stop hand-rolling `margin: -24px` guesses that drift from the parent's actual padding token. use a semantic space step, never raw px, and MUST match the ancestor padding it is meant to cancel out. Do NOT use Bleed to fake extra spacing — its only job is canceling a specific known padding value on a specific axis. Every Layout reference: https://every-layout.dev/layouts/the-stack/ (bleed is the inverse of a padded Center/Container — HDS names it separately since \"every-layout\" itself does not ship a dedicated Bleed recipe).",
9698
+ "description": "Bleed — controlled negative-margin full-bleed within a padded container. Every Layout reference: https://every-layout.dev/layouts/the-stack/ (bleed is the inverse of a padded Center/Container — HDS names it separately since \"every-layout\" itself does not ship a dedicated Bleed recipe).",
8723
9699
  "figmaUrl": null,
8724
9700
  "figmaId": null,
8725
9701
  "figmaLink": null,
@@ -8783,7 +9759,8 @@
8783
9759
  "storyIds": [
8784
9760
  "primitives-bleed--bleed-both",
8785
9761
  "primitives-bleed--bleed-x"
8786
- ]
9762
+ ],
9763
+ "aiRules": "Reach for this named layout intent before Box/sx. amount MUST use a semantic space step, never raw px, and MUST match the ancestor padding it is meant to cancel out. Do NOT use Bleed to fake extra spacing — its only job is canceling a specific known padding value on a specific axis."
8787
9764
  },
8788
9765
  "Center": {
8789
9766
  "category": "Layout",
@@ -8792,7 +9769,7 @@
8792
9769
  "hidden": false,
8793
9770
  "docExempt": false,
8794
9771
  "filePath": "src/app/components/center.tsx",
8795
- "description": "Center — max-width column, auto-centered horizontally. max-width box with auto horizontal margins and, optionally, matching horizontal gutters — so agents stop hand-rolling `marginInline: auto` plus an ad hoc max-width value. use the semantic width scale ('content' | 'max'), never a raw px value. gutter, when set, MUST use a semantic space step, never raw px. Do NOT use Center for full-bleed page shells — use Container. Do NOT use Center when you need the deprecated Container padding prop — gutter replaces it. Every Layout reference: https://every-layout.dev/layouts/center/",
9772
+ "description": "Center — max-width column, auto-centered horizontally. Every Layout reference: https://every-layout.dev/layouts/center/",
8796
9773
  "figmaUrl": null,
8797
9774
  "figmaId": null,
8798
9775
  "figmaLink": null,
@@ -8860,7 +9837,8 @@
8860
9837
  "primitives-center--content-width",
8861
9838
  "primitives-center--max-width",
8862
9839
  "primitives-center--with-gutter"
8863
- ]
9840
+ ],
9841
+ "aiRules": "Reach for this named layout intent before Box/sx. maxWidth MUST use the semantic width scale ('content' | 'max'), never a raw px value. gutter, when set, MUST use a semantic space step, never raw px. Do NOT use Center for full-bleed page shells — use Container. Do NOT use Center when you need the deprecated Container padding prop — gutter replaces it."
8864
9842
  },
8865
9843
  "Cluster": {
8866
9844
  "category": "Layout",
@@ -8869,7 +9847,7 @@
8869
9847
  "hidden": false,
8870
9848
  "docExempt": false,
8871
9849
  "filePath": "src/app/components/cluster.tsx",
8872
- "description": "Cluster — wrapping horizontal group with even gaps. (tag rows, button groups, chip lists, filter pills) with a single flex-wrap wrapper and a tokenized gap in both axes, so agents stop hand-rolling `flexWrap` + `gap` + alignment combinations inline. horizontal groups that should wrap as a unit. Spacing MUST use semantic steps, never raw px. Do NOT use Cluster for a strict single-line row — use Stack with `direction=\"row\"` when wrapping is never desired. Do NOT use Cluster for two-dimensional grid layouts — use Grid. Every Layout reference: https://every-layout.dev/layouts/cluster/",
9850
+ "description": "Cluster — wrapping horizontal group with even gaps. Every Layout reference: https://every-layout.dev/layouts/cluster/",
8873
9851
  "figmaUrl": null,
8874
9852
  "figmaId": null,
8875
9853
  "figmaLink": null,
@@ -8880,6 +9858,11 @@
8880
9858
  },
8881
9859
  "consumers": [
8882
9860
  "src/app/components/cluster.test.tsx",
9861
+ "src/app/components/data-table-section.tsx",
9862
+ "src/app/components/destructive-section.tsx",
9863
+ "src/app/components/form-actions.test.tsx",
9864
+ "src/app/components/form-actions.tsx",
9865
+ "src/app/components/page-header.tsx",
8883
9866
  "src/app/components/switcher.tsx",
8884
9867
  "src/stories/cluster.stories.tsx",
8885
9868
  "src/stories/patterns-layout.stories.tsx"
@@ -8947,7 +9930,8 @@
8947
9930
  "primitives-cluster--default",
8948
9931
  "primitives-cluster--space-between",
8949
9932
  "primitives-cluster--spacious-gap"
8950
- ]
9933
+ ],
9934
+ "aiRules": "Reach for this named layout intent before Box/sx. Use Cluster for horizontal groups that should wrap as a unit. Spacing MUST use semantic steps, never raw px. Do NOT use Cluster for a strict single-line row — use Stack with `direction=\"row\"` when wrapping is never desired. Do NOT use Cluster for two-dimensional grid layouts — use Grid."
8951
9935
  },
8952
9936
  "Cover": {
8953
9937
  "category": "Layout",
@@ -8956,7 +9940,7 @@
8956
9940
  "hidden": false,
8957
9941
  "docExempt": false,
8958
9942
  "filePath": "src/app/components/cover.tsx",
8959
- "description": "Cover — vertical shell with an auto-centered main region. centered hero/main region that absorbs the remaining space, and an optional footer\" problem via the flex auto-margin centering technique, so agents stop hand-rolling `position: absolute` centering or a fixed 50vh split. semantic space step, never raw px. minHeight is a CSS length dimension (not spacing) — defaults to '100svh' (small viewport height, safe against mobile browser chrome). Pass minHeight=\"100vh\" explicitly if you need the classic viewport unit for a target that predates svh support. Do NOT use Cover for ordinary page content flow — use Stack. Every Layout reference: https://every-layout.dev/layouts/cover/",
9943
+ "description": "Cover — vertical shell with an auto-centered main region. Every Layout reference: https://every-layout.dev/layouts/cover/",
8960
9944
  "figmaUrl": null,
8961
9945
  "figmaId": null,
8962
9946
  "figmaLink": null,
@@ -9031,7 +10015,8 @@
9031
10015
  "primitives-cover--header-main-footer",
9032
10016
  "primitives-cover--header-only",
9033
10017
  "primitives-cover--main-only"
9034
- ]
10018
+ ],
10019
+ "aiRules": "Reach for this named layout intent before Box/sx. gap MUST use a semantic space step, never raw px. minHeight is a CSS length dimension (not spacing) — defaults to '100svh' (small viewport height, safe against mobile browser chrome). Pass minHeight=\"100vh\" explicitly if you need the classic viewport unit for a target that predates svh support. Do NOT use Cover for ordinary page content flow — use Stack."
9035
10020
  },
9036
10021
  "Frame": {
9037
10022
  "category": "Layout",
@@ -9040,7 +10025,7 @@
9040
10025
  "hidden": false,
9041
10026
  "docExempt": false,
9042
10027
  "filePath": "src/app/components/frame.tsx",
9043
- "description": "Frame — aspect-ratio-locked, token-clipped media box. cause layout shift while it loads, cropped to a token-governed corner radius\" — a thin, token-skinned wrapper over `AspectRatio` (`@radix-ui/react-aspect-ratio`), which already owns the ratio-lock mechanics. Frame adds the overflow-hidden clip and semantic radius that a bare media frame needs and `AspectRatio` deliberately leaves undecorated. media (image, video, embed, map tile). radius MUST use a semantic borderRadius token, never a raw px value. Do NOT reach for bare `AspectRatio` in product code just to add a border-radius by hand — use Frame. Do NOT use Frame for non-media layout — it exists purely as a media clipping frame. Every Layout reference: https://every-layout.dev/layouts/frame/",
10028
+ "description": "Frame — aspect-ratio-locked, token-clipped media box. Every Layout reference: https://every-layout.dev/layouts/frame/",
9044
10029
  "figmaUrl": null,
9045
10030
  "figmaId": null,
9046
10031
  "figmaLink": null,
@@ -9101,7 +10086,8 @@
9101
10086
  "primitives-frame--no-radius",
9102
10087
  "primitives-frame--square",
9103
10088
  "primitives-frame--widescreen"
9104
- ]
10089
+ ],
10090
+ "aiRules": "Reach for this named layout intent before Box/sx when framing media (image, video, embed, map tile). radius MUST use a semantic borderRadius token, never a raw px value. Do NOT reach for bare `AspectRatio` in product code just to add a border-radius by hand — use Frame. Do NOT use Frame for non-media layout — it exists purely as a media clipping frame."
9105
10091
  },
9106
10092
  "Sidebar": {
9107
10093
  "category": "Layout",
@@ -9110,7 +10096,7 @@
9110
10096
  "hidden": false,
9111
10097
  "docExempt": false,
9112
10098
  "filePath": "src/app/components/sidebar.tsx",
9113
- "description": "Sidebar — fixed-width rail beside fluid content, no media query. problem with the flex-basis/flex-grow disparity technique — the rail holds `sideWidth` and the content flex-basis 0 with an overwhelming flex-grow, so the pair wraps to stacked automatically once the container can no longer fit both without squeezing content below `contentMin`. No CSS media query, no JS resize observer. EXACTLY two children — the rail and the content — passed in that order. `side` controls which one visually renders as the rail; DOM order is unchanged. gap MUST use a semantic space step, never raw px. sideWidth and contentMin are CSS length dimensions (not spacing) — a length string like '16rem' or '50%' is expected, matching the check-hardcoded-spacing gate's own dimension-prop exemption. Do NOT use Sidebar for more than two regions — use Grid. Every Layout reference: https://every-layout.dev/layouts/sidebar/",
10099
+ "description": "Sidebar — fixed-width rail beside fluid content, no media query. Every Layout reference: https://every-layout.dev/layouts/sidebar/",
9114
10100
  "figmaUrl": null,
9115
10101
  "figmaId": null,
9116
10102
  "figmaLink": null,
@@ -9189,7 +10175,8 @@
9189
10175
  "primitives-sidebar--narrow-container-stacks",
9190
10176
  "primitives-sidebar--rail-end",
9191
10177
  "primitives-sidebar--rail-start"
9192
- ]
10178
+ ],
10179
+ "aiRules": "Reach for this named layout intent before Box/sx. Sidebar expects EXACTLY two children — the rail and the content — passed in that order. `side` controls which one visually renders as the rail; DOM order is unchanged. gap MUST use a semantic space step, never raw px. sideWidth and contentMin are CSS length dimensions (not spacing) — a length string like '16rem' or '50%' is expected, matching the check-hardcoded-spacing gate's own dimension-prop exemption. Do NOT use Sidebar for more than two regions — use Grid."
9193
10180
  },
9194
10181
  "Switcher": {
9195
10182
  "category": "Layout",
@@ -9198,7 +10185,7 @@
9198
10185
  "hidden": false,
9199
10186
  "docExempt": false,
9200
10187
  "filePath": "src/app/components/switcher.tsx",
9201
- "description": "Switcher — flips a row to a column below a width threshold, no media query. vertical stack once the container gets narrow\" without a breakpoint or a resize observer, using the flex-basis calc() technique: each item's flex-basis resolves to a huge negative or huge positive number depending on whether the container is above or below `threshold`, forcing every item onto its own line once it flips. semantic space step, never raw px. threshold is a CSS length dimension (not spacing), e.g. '30rem'. `limit` unconditionally forces the stacked (column) layout once there are more than `limit` children, regardless of container width — use it to stop a row from thinning out into an unreadable N-up strip. Do NOT use Switcher for content that should always wrap in place — use Cluster. Every Layout reference: https://every-layout.dev/layouts/the-switcher/",
10188
+ "description": "Switcher — flips a row to a column below a width threshold, no media query. Every Layout reference: https://every-layout.dev/layouts/the-switcher/",
9202
10189
  "figmaUrl": null,
9203
10190
  "figmaId": null,
9204
10191
  "figmaLink": null,
@@ -9262,7 +10249,8 @@
9262
10249
  "primitives-switcher--default",
9263
10250
  "primitives-switcher--limit-forces-stacked",
9264
10251
  "primitives-switcher--narrow-container-stacks"
9265
- ]
10252
+ ],
10253
+ "aiRules": "Reach for this named layout intent before Box/sx. gap MUST use a semantic space step, never raw px. threshold is a CSS length dimension (not spacing), e.g. '30rem'. `limit` unconditionally forces the stacked (column) layout once there are more than `limit` children, regardless of container width — use it to stop a row from thinning out into an unreadable N-up strip. Do NOT use Switcher for content that should always wrap in place — use Cluster."
9266
10254
  },
9267
10255
  "Pin": {
9268
10256
  "category": "Layout",
@@ -9271,7 +10259,7 @@
9271
10259
  "hidden": false,
9272
10260
  "docExempt": false,
9273
10261
  "filePath": "src/app/components/pin.tsx",
9274
- "description": "Pin — sticky-pin an element within its scroll region. section scrolls — the dependency-free basis for pinned scroll scenes (the \"tall section + sticky child\" pattern that GSAP's `pin: true` solves imperatively). Reach for this before hand-rolling sticky positioning. Give the pinned element a TALLER scrolling parent so it has room to travel. For the scroll-scrubbed animation inside a pinned scene, use CSS `animation-timeline` (see Reveal) or `useScrollProgress` from `@hirobius/design-system/scroll`. See ADR-021.",
10262
+ "description": "Pin — sticky-pin an element within its scroll region.",
9275
10263
  "figmaUrl": null,
9276
10264
  "figmaId": null,
9277
10265
  "figmaLink": null,
@@ -9281,6 +10269,7 @@
9281
10269
  "sizing": "panel"
9282
10270
  },
9283
10271
  "consumers": [
10272
+ "src/app/components/form-actions.tsx",
9284
10273
  "src/app/components/pin.test.tsx",
9285
10274
  "src/stories/patterns-scroll.stories.tsx",
9286
10275
  "src/stories/pin.stories.tsx",
@@ -9321,7 +10310,8 @@
9321
10310
  ],
9322
10311
  "storyIds": [
9323
10312
  "primitives-pin--sidebar"
9324
- ]
10313
+ ],
10314
+ "aiRules": "`top` is a CSS length offset (a dimension, not a spacing step). Give the pinned element a TALLER scrolling parent so it has room to travel. For the scroll-scrubbed animation inside a pinned scene, use CSS `animation-timeline` (see Reveal) or `useScrollProgress` from `@hirobius/design-system/scroll`. See ADR-021."
9325
10315
  },
9326
10316
  "Reveal": {
9327
10317
  "category": "Motion",
@@ -9330,7 +10320,7 @@
9330
10320
  "hidden": false,
9331
10321
  "docExempt": false,
9332
10322
  "filePath": "src/app/components/reveal.tsx",
9333
- "description": "Reveal — reveal-on-scroll primitive via CSS scroll-driven animation. purely by scroll position (`animation-timeline: view()`) — no JS, no deps, no IntersectionObserver. Reach for this before hand-rolling reveal logic. `animation-timeline` is supported AND the user has not requested reduced motion (both fall back to visible, never stuck hidden). Pick `animation` from the fixed set — do not hand-roll keyframes. For momentum/inertia scrolling wrap the app in `SmoothScroll`; for a scroll-progress value in JS use `useScrollProgress` — both from `@hirobius/design-system/scroll`. See ADR-021.",
10323
+ "description": "Reveal — reveal-on-scroll primitive via CSS scroll-driven animation.",
9334
10324
  "figmaUrl": null,
9335
10325
  "figmaId": null,
9336
10326
  "figmaLink": null,
@@ -9392,7 +10382,8 @@
9392
10382
  "patterns-scroll--simple-parallax",
9393
10383
  "primitives-reveal--animations",
9394
10384
  "primitives-reveal--scale-reveal-scene"
9395
- ]
10385
+ ],
10386
+ "aiRules": "Content is fully visible by DEFAULT; the effect applies only where `animation-timeline` is supported AND the user has not requested reduced motion (both fall back to visible, never stuck hidden). Pick `animation` from the fixed set — do not hand-roll keyframes. For momentum/inertia scrolling wrap the app in `SmoothScroll`; for a scroll-progress value in JS use `useScrollProgress` — both from `@hirobius/design-system/scroll`. See ADR-021."
9396
10387
  },
9397
10388
  "Textarea": {
9398
10389
  "category": "Inputs",
@@ -9411,6 +10402,8 @@
9411
10402
  "sizing": "panel"
9412
10403
  },
9413
10404
  "consumers": [
10405
+ "src/app/components/input.tsx",
10406
+ "src/stories/patterns-client-detail.stories.tsx",
9414
10407
  "src/stories/textarea.stories.tsx"
9415
10408
  ],
9416
10409
  "tokenMapping": {},
@@ -9465,7 +10458,17 @@
9465
10458
  "primitives-textarea--disabled",
9466
10459
  "primitives-textarea--error",
9467
10460
  "primitives-textarea--with-helper"
9468
- ]
10461
+ ],
10462
+ "usage": {
10463
+ "when": "Collect multi-line free text such as a message, note or description.",
10464
+ "whenNot": "A single line of text, or choosing from a list.",
10465
+ "useInstead": [
10466
+ {
10467
+ "component": "Input",
10468
+ "reason": "a single line of text"
10469
+ }
10470
+ ]
10471
+ }
9469
10472
  },
9470
10473
  "CardBody": {
9471
10474
  "category": "Display",
@@ -9483,7 +10486,9 @@
9483
10486
  "exportName": "CardBody",
9484
10487
  "sizing": "panel"
9485
10488
  },
9486
- "consumers": [],
10489
+ "consumers": [
10490
+ "src/app/components/card.test.tsx"
10491
+ ],
9487
10492
  "tokenMapping": {},
9488
10493
  "variantAxes": [],
9489
10494
  "componentProperties": [],
@@ -9526,7 +10531,9 @@
9526
10531
  "exportName": "CardDescription",
9527
10532
  "sizing": "panel"
9528
10533
  },
9529
- "consumers": [],
10534
+ "consumers": [
10535
+ "src/app/components/card.test.tsx"
10536
+ ],
9530
10537
  "tokenMapping": {},
9531
10538
  "variantAxes": [],
9532
10539
  "componentProperties": [],
@@ -9569,7 +10576,9 @@
9569
10576
  "exportName": "CardFooter",
9570
10577
  "sizing": "panel"
9571
10578
  },
9572
- "consumers": [],
10579
+ "consumers": [
10580
+ "src/app/components/card.test.tsx"
10581
+ ],
9573
10582
  "tokenMapping": {},
9574
10583
  "variantAxes": [],
9575
10584
  "componentProperties": [],
@@ -9612,7 +10621,9 @@
9612
10621
  "exportName": "CardHeader",
9613
10622
  "sizing": "panel"
9614
10623
  },
9615
- "consumers": [],
10624
+ "consumers": [
10625
+ "src/app/components/card.test.tsx"
10626
+ ],
9616
10627
  "tokenMapping": {},
9617
10628
  "variantAxes": [],
9618
10629
  "componentProperties": [],
@@ -9651,7 +10662,7 @@
9651
10662
  "hidden": false,
9652
10663
  "docExempt": false,
9653
10664
  "filePath": "src/app/components/card.tsx",
9654
- "description": "Card — surface container with slot anatomy (12d-card-anatomy). Slot anatomy (DESIGN.md §\"Card Anatomy\"). Status, progress, and metadata are layout-bearing — they live in slots, never inline next to prose. <Card variant=\"accent\"> <Card.Header metadata={<Badge tone=\"warning\">in-progress</Badge>}> <Card.Title>Discovery phase</Card.Title> <Card.Description>Stakeholder interviews and audit prep.</Card.Description> </Card.Header> <Card.Progress value={42} max={100} label=\"5 / 12 tasks\" /> <Card.Metric label=\"Retainer\" value=\"$3,500\" sub=\"Active\" /> <Card.Body>…</Card.Body> <Card.Footer>…</Card.Footer> </Card> Slot reservations: - Header: title (h3) + optional description (caption) + optional metadata zone (right-aligned, holds <Badge> / <Tag> for status, never raw spans). - Progress: full-width 4px bar in a reserved 16px vertical rail. Owns its spacing — never crowds adjacent prose. - Metric: single label-uppercase + big value (h2) + optional sub-line. Reserved vertical block. Use multiple side-by-side via flex/grid container. - Body: prose, lists, structured content. NO inline status, progress, or thin colored bars. Group sections via separate <Card.Body> blocks. - Footer: actions, secondary metadata, timestamps. `variant`: 'default' (borderless) | 'accent' (2px accent border) — the structural axis, for highlighted entries like \"recommended package\". `tone`: neutral | danger | success | warning | info — the fixed feedback axis (#60 variant contract), for status-driven cards where the border IS the signal. `variant`/`tone` together replace hand-rolled `pkgHighlight`-style overrides. Legacy props (padding / gap / noPadding / as / style) are retained. Existing callers that pass raw children continue to work; new callers should prefer compound parts + `padding=\"none\"`. Depth comes from semantic.color.border.default (role.border) at rest; elevation tokens are not bound by default — pass `className=\"shadow-...\"` for a hover/floating treatment on interactive cards.",
10665
+ "description": "Card.Metric — one uppercase label, a large value and an optional sub-line inside a Card.",
9655
10666
  "figmaUrl": null,
9656
10667
  "figmaId": null,
9657
10668
  "figmaLink": null,
@@ -9660,7 +10671,9 @@
9660
10671
  "exportName": "CardMetric",
9661
10672
  "sizing": "panel"
9662
10673
  },
9663
- "consumers": [],
10674
+ "consumers": [
10675
+ "src/app/components/card.test.tsx"
10676
+ ],
9664
10677
  "tokenMapping": {},
9665
10678
  "variantAxes": [],
9666
10679
  "componentProperties": [],
@@ -9707,7 +10720,11 @@
9707
10720
  "primitives-card--padding-variants",
9708
10721
  "primitives-card--progress-slot",
9709
10722
  "primitives-card--variant-accent"
9710
- ]
10723
+ ],
10724
+ "usage": {
10725
+ "when": "Show one headline figure (a KPI, a count, a total) with its label inside a Card.",
10726
+ "whenNot": "A metric outside a Card, or several figures that share one label."
10727
+ }
9711
10728
  },
9712
10729
  "CardProgress": {
9713
10730
  "category": "Display",
@@ -9725,7 +10742,9 @@
9725
10742
  "exportName": "CardProgress",
9726
10743
  "sizing": "panel"
9727
10744
  },
9728
- "consumers": [],
10745
+ "consumers": [
10746
+ "src/app/components/card.test.tsx"
10747
+ ],
9729
10748
  "tokenMapping": {},
9730
10749
  "variantAxes": [],
9731
10750
  "componentProperties": [],
@@ -9791,7 +10810,9 @@
9791
10810
  "exportName": "CardTitle",
9792
10811
  "sizing": "panel"
9793
10812
  },
9794
- "consumers": [],
10813
+ "consumers": [
10814
+ "src/app/components/card.test.tsx"
10815
+ ],
9795
10816
  "tokenMapping": {},
9796
10817
  "variantAxes": [],
9797
10818
  "componentProperties": [],
@@ -9825,7 +10846,7 @@
9825
10846
  "hidden": false,
9826
10847
  "docExempt": true,
9827
10848
  "filePath": "src/app/components/dialog.tsx",
9828
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10849
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
9829
10850
  "figmaUrl": null,
9830
10851
  "figmaId": null,
9831
10852
  "figmaLink": null,
@@ -9834,7 +10855,9 @@
9834
10855
  "exportName": "DialogClose",
9835
10856
  "sizing": "panel"
9836
10857
  },
9837
- "consumers": [],
10858
+ "consumers": [
10859
+ "src/app/components/dialog.test.tsx"
10860
+ ],
9838
10861
  "tokenMapping": {},
9839
10862
  "variantAxes": [],
9840
10863
  "componentProperties": [],
@@ -9854,6 +10877,7 @@
9854
10877
  "src/stories/dialog.stories.tsx"
9855
10878
  ],
9856
10879
  "storyIds": [
10880
+ "primitives-dialog--dark-scope",
9857
10881
  "primitives-dialog--default",
9858
10882
  "primitives-dialog--destructive",
9859
10883
  "primitives-dialog--information",
@@ -9867,7 +10891,7 @@
9867
10891
  "hidden": false,
9868
10892
  "docExempt": true,
9869
10893
  "filePath": "src/app/components/dialog.tsx",
9870
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10894
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
9871
10895
  "figmaUrl": null,
9872
10896
  "figmaId": null,
9873
10897
  "figmaLink": null,
@@ -9876,7 +10900,9 @@
9876
10900
  "exportName": "DialogContent",
9877
10901
  "sizing": "panel"
9878
10902
  },
9879
- "consumers": [],
10903
+ "consumers": [
10904
+ "src/app/components/dialog.test.tsx"
10905
+ ],
9880
10906
  "tokenMapping": {},
9881
10907
  "variantAxes": [],
9882
10908
  "componentProperties": [],
@@ -9900,6 +10926,7 @@
9900
10926
  "src/stories/dialog.stories.tsx"
9901
10927
  ],
9902
10928
  "storyIds": [
10929
+ "primitives-dialog--dark-scope",
9903
10930
  "primitives-dialog--default",
9904
10931
  "primitives-dialog--destructive",
9905
10932
  "primitives-dialog--information",
@@ -9913,7 +10940,7 @@
9913
10940
  "hidden": false,
9914
10941
  "docExempt": true,
9915
10942
  "filePath": "src/app/components/dialog.tsx",
9916
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10943
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
9917
10944
  "figmaUrl": null,
9918
10945
  "figmaId": null,
9919
10946
  "figmaLink": null,
@@ -9922,7 +10949,9 @@
9922
10949
  "exportName": "DialogDescription",
9923
10950
  "sizing": "panel"
9924
10951
  },
9925
- "consumers": [],
10952
+ "consumers": [
10953
+ "src/app/components/dialog.test.tsx"
10954
+ ],
9926
10955
  "tokenMapping": {},
9927
10956
  "variantAxes": [],
9928
10957
  "componentProperties": [],
@@ -9942,6 +10971,7 @@
9942
10971
  "src/stories/dialog.stories.tsx"
9943
10972
  ],
9944
10973
  "storyIds": [
10974
+ "primitives-dialog--dark-scope",
9945
10975
  "primitives-dialog--default",
9946
10976
  "primitives-dialog--destructive",
9947
10977
  "primitives-dialog--information",
@@ -9955,7 +10985,7 @@
9955
10985
  "hidden": false,
9956
10986
  "docExempt": true,
9957
10987
  "filePath": "src/app/components/dialog.tsx",
9958
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10988
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
9959
10989
  "figmaUrl": null,
9960
10990
  "figmaId": null,
9961
10991
  "figmaLink": null,
@@ -9964,7 +10994,9 @@
9964
10994
  "exportName": "DialogFooter",
9965
10995
  "sizing": "panel"
9966
10996
  },
9967
- "consumers": [],
10997
+ "consumers": [
10998
+ "src/app/components/dialog.test.tsx"
10999
+ ],
9968
11000
  "tokenMapping": {},
9969
11001
  "variantAxes": [],
9970
11002
  "componentProperties": [],
@@ -9979,6 +11011,7 @@
9979
11011
  "src/stories/dialog.stories.tsx"
9980
11012
  ],
9981
11013
  "storyIds": [
11014
+ "primitives-dialog--dark-scope",
9982
11015
  "primitives-dialog--default",
9983
11016
  "primitives-dialog--destructive",
9984
11017
  "primitives-dialog--information",
@@ -9992,7 +11025,7 @@
9992
11025
  "hidden": false,
9993
11026
  "docExempt": true,
9994
11027
  "filePath": "src/app/components/dialog.tsx",
9995
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
11028
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
9996
11029
  "figmaUrl": null,
9997
11030
  "figmaId": null,
9998
11031
  "figmaLink": null,
@@ -10001,7 +11034,9 @@
10001
11034
  "exportName": "DialogHeader",
10002
11035
  "sizing": "panel"
10003
11036
  },
10004
- "consumers": [],
11037
+ "consumers": [
11038
+ "src/app/components/dialog.test.tsx"
11039
+ ],
10005
11040
  "tokenMapping": {},
10006
11041
  "variantAxes": [],
10007
11042
  "componentProperties": [],
@@ -10016,6 +11051,7 @@
10016
11051
  "src/stories/dialog.stories.tsx"
10017
11052
  ],
10018
11053
  "storyIds": [
11054
+ "primitives-dialog--dark-scope",
10019
11055
  "primitives-dialog--default",
10020
11056
  "primitives-dialog--destructive",
10021
11057
  "primitives-dialog--information",
@@ -10029,7 +11065,7 @@
10029
11065
  "hidden": false,
10030
11066
  "docExempt": true,
10031
11067
  "filePath": "src/app/components/dialog.tsx",
10032
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
11068
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10033
11069
  "figmaUrl": null,
10034
11070
  "figmaId": null,
10035
11071
  "figmaLink": null,
@@ -10038,7 +11074,9 @@
10038
11074
  "exportName": "DialogOverlay",
10039
11075
  "sizing": "panel"
10040
11076
  },
10041
- "consumers": [],
11077
+ "consumers": [
11078
+ "src/app/components/dialog.test.tsx"
11079
+ ],
10042
11080
  "tokenMapping": {},
10043
11081
  "variantAxes": [],
10044
11082
  "componentProperties": [],
@@ -10058,6 +11096,7 @@
10058
11096
  "src/stories/dialog.stories.tsx"
10059
11097
  ],
10060
11098
  "storyIds": [
11099
+ "primitives-dialog--dark-scope",
10061
11100
  "primitives-dialog--default",
10062
11101
  "primitives-dialog--destructive",
10063
11102
  "primitives-dialog--information",
@@ -10071,7 +11110,7 @@
10071
11110
  "hidden": false,
10072
11111
  "docExempt": true,
10073
11112
  "filePath": "src/app/components/dialog.tsx",
10074
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
11113
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10075
11114
  "figmaUrl": null,
10076
11115
  "figmaId": null,
10077
11116
  "figmaLink": null,
@@ -10080,7 +11119,9 @@
10080
11119
  "exportName": "DialogPortal",
10081
11120
  "sizing": "panel"
10082
11121
  },
10083
- "consumers": [],
11122
+ "consumers": [
11123
+ "src/app/components/dialog.test.tsx"
11124
+ ],
10084
11125
  "tokenMapping": {},
10085
11126
  "variantAxes": [],
10086
11127
  "componentProperties": [],
@@ -10095,6 +11136,7 @@
10095
11136
  "src/stories/dialog.stories.tsx"
10096
11137
  ],
10097
11138
  "storyIds": [
11139
+ "primitives-dialog--dark-scope",
10098
11140
  "primitives-dialog--default",
10099
11141
  "primitives-dialog--destructive",
10100
11142
  "primitives-dialog--information",
@@ -10108,7 +11150,7 @@
10108
11150
  "hidden": false,
10109
11151
  "docExempt": true,
10110
11152
  "filePath": "src/app/components/dialog.tsx",
10111
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
11153
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10112
11154
  "figmaUrl": null,
10113
11155
  "figmaId": null,
10114
11156
  "figmaLink": null,
@@ -10117,7 +11159,9 @@
10117
11159
  "exportName": "DialogTitle",
10118
11160
  "sizing": "panel"
10119
11161
  },
10120
- "consumers": [],
11162
+ "consumers": [
11163
+ "src/app/components/dialog.test.tsx"
11164
+ ],
10121
11165
  "tokenMapping": {},
10122
11166
  "variantAxes": [],
10123
11167
  "componentProperties": [],
@@ -10137,6 +11181,7 @@
10137
11181
  "src/stories/dialog.stories.tsx"
10138
11182
  ],
10139
11183
  "storyIds": [
11184
+ "primitives-dialog--dark-scope",
10140
11185
  "primitives-dialog--default",
10141
11186
  "primitives-dialog--destructive",
10142
11187
  "primitives-dialog--information",
@@ -10150,7 +11195,7 @@
10150
11195
  "hidden": false,
10151
11196
  "docExempt": true,
10152
11197
  "filePath": "src/app/components/dialog.tsx",
10153
- "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is a foreground/80 wash so it picks up the theme without a hardcoded black. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
11198
+ "description": "Dialog — modal dialog (shadcn baseline, compound parts). shadcn-baseline implementation (8s-7): Radix Dialog primitive (@radix-ui/react-dialog) themed with role tokens. Provides focus trap, scroll lock, ESC-to-close, backdrop scrim, and portal mounting out of the box. <Dialog> <Dialog.Trigger asChild> <Button>Open</Button> </Dialog.Trigger> <Dialog.Content> <Dialog.Header> <Dialog.Title>Confirm</Dialog.Title> <Dialog.Description>Are you sure?</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close asChild> <Button variant=\"secondary\">Cancel</Button> </Dialog.Close> </Dialog.Footer> </Dialog.Content> </Dialog> Surface uses role.popover (semantic.color.surface.overlay) + shadow-overlay (semantic.shadow.overlay from 8e-1). The scrim is role.scrim (semantic.color.surface.scrim) at 60% alpha: dark in both themes, black in dark mode. The overlay portals into the nearest `data-hds` scope so it inherits the active theme; pass `container` to override. The close affordance is rendered as an absolutely-positioned X inside Content; pass `hideClose` to opt out for fully-custom layouts.",
10154
11199
  "figmaUrl": null,
10155
11200
  "figmaId": null,
10156
11201
  "figmaLink": null,
@@ -10159,7 +11204,9 @@
10159
11204
  "exportName": "DialogTrigger",
10160
11205
  "sizing": "panel"
10161
11206
  },
10162
- "consumers": [],
11207
+ "consumers": [
11208
+ "src/app/components/dialog.test.tsx"
11209
+ ],
10163
11210
  "tokenMapping": {},
10164
11211
  "variantAxes": [],
10165
11212
  "componentProperties": [],
@@ -10179,6 +11226,7 @@
10179
11226
  "src/stories/dialog.stories.tsx"
10180
11227
  ],
10181
11228
  "storyIds": [
11229
+ "primitives-dialog--dark-scope",
10182
11230
  "primitives-dialog--default",
10183
11231
  "primitives-dialog--destructive",
10184
11232
  "primitives-dialog--information",
@@ -10203,6 +11251,8 @@
10203
11251
  "consumers": [
10204
11252
  "src/app/components/asset-img.tsx",
10205
11253
  "src/app/components/hover-card.tsx",
11254
+ "src/app/context/__tests__/portal-hydration.test.tsx",
11255
+ "src/app/context/__tests__/portal-scope.test.tsx",
10206
11256
  "src/app/data/hdsEditorial.tsx",
10207
11257
  "src/index.ts",
10208
11258
  "src/stories/hds-tooltip.stories.tsx"
@@ -10243,13 +11293,19 @@
10243
11293
  "sizing": "panel"
10244
11294
  },
10245
11295
  "consumers": [
11296
+ "src/app/components/combobox.tsx",
10246
11297
  "src/app/components/command-palette.tsx",
10247
11298
  "src/app/components/context-menu.tsx",
11299
+ "src/app/components/data-table-section.tsx",
10248
11300
  "src/app/components/date-range-input.tsx",
10249
11301
  "src/app/components/hover-card.tsx",
10250
11302
  "src/app/components/menu.test.tsx",
10251
11303
  "src/app/components/multi-selector.tsx",
11304
+ "src/app/components/select.tsx",
11305
+ "src/app/context/__tests__/portal-hydration.test.tsx",
11306
+ "src/app/context/__tests__/portal-scope.test.tsx",
10252
11307
  "src/docs-tooling/shell-controls.tsx",
11308
+ "src/stories/context-menu.stories.tsx",
10253
11309
  "src/stories/menu.stories.tsx"
10254
11310
  ],
10255
11311
  "tokenMapping": {},
@@ -10270,6 +11326,58 @@
10270
11326
  "primitives-menu--with-checkbox-items",
10271
11327
  "primitives-menu--with-radio-group",
10272
11328
  "primitives-menu--with-submenu"
11329
+ ],
11330
+ "slots": [
11331
+ {
11332
+ "name": "trigger",
11333
+ "description": "The element that opens the menu (Menu.Trigger).",
11334
+ "source": "jsdoc"
11335
+ },
11336
+ {
11337
+ "name": "content",
11338
+ "description": "The popup holding the items (Menu.Content).",
11339
+ "source": "jsdoc"
11340
+ }
11341
+ ],
11342
+ "usage": {
11343
+ "when": "Offer a list of actions from a trigger, closed until opened.",
11344
+ "whenNot": "Choosing one value for a form field, or a set of options that must stay visible.",
11345
+ "useInstead": [
11346
+ {
11347
+ "component": "Select",
11348
+ "reason": "choosing a value for a form field"
11349
+ }
11350
+ ]
11351
+ },
11352
+ "keyboard": [
11353
+ {
11354
+ "keys": "Enter/Space/ArrowDown",
11355
+ "effect": "Opens the menu from the trigger and highlights the first item."
11356
+ },
11357
+ {
11358
+ "keys": "ArrowDown/ArrowUp",
11359
+ "effect": "Moves the highlight; it stops at the first and last item."
11360
+ },
11361
+ {
11362
+ "keys": "Home/End",
11363
+ "effect": "Jumps to the first or last item."
11364
+ },
11365
+ {
11366
+ "keys": "Character",
11367
+ "effect": "Highlights the next item that starts with the typed letter."
11368
+ },
11369
+ {
11370
+ "keys": "Enter",
11371
+ "effect": "Selects the highlighted item and closes the menu."
11372
+ },
11373
+ {
11374
+ "keys": "Escape",
11375
+ "effect": "Closes the menu and returns focus to the trigger."
11376
+ },
11377
+ {
11378
+ "keys": "Tab",
11379
+ "effect": "Does not leave the open menu."
11380
+ }
10273
11381
  ]
10274
11382
  },
10275
11383
  "Popover": {
@@ -10303,6 +11411,8 @@
10303
11411
  "src/app/components/multi-selector.test.tsx",
10304
11412
  "src/app/components/multi-selector.tsx",
10305
11413
  "src/app/components/popover.test.tsx",
11414
+ "src/app/context/__tests__/portal-hydration.test.tsx",
11415
+ "src/app/context/__tests__/portal-scope.test.tsx",
10306
11416
  "src/app/design-system/generated-token-descriptions.ts",
10307
11417
  "src/stories/combobox.stories.tsx",
10308
11418
  "src/stories/date-input.stories.tsx",
@@ -10416,6 +11526,7 @@
10416
11526
  "consumers": [
10417
11527
  "src/app/components/checkbox.test.tsx",
10418
11528
  "src/app/components/radio.tsx",
11529
+ "src/app/components/toggle.tsx",
10419
11530
  "src/index.ts",
10420
11531
  "src/stories/checkbox.stories.tsx"
10421
11532
  ],
@@ -10453,6 +11564,393 @@
10453
11564
  "primitives-checkbox--disabled-checked",
10454
11565
  "primitives-checkbox--group",
10455
11566
  "primitives-checkbox--indeterminate"
11567
+ ],
11568
+ "usage": {
11569
+ "when": "Let people tick one or more independent options, or a parent choice that is partly selected.",
11570
+ "whenNot": "An immediate on/off setting, or a choice of exactly one option from a set.",
11571
+ "useInstead": [
11572
+ {
11573
+ "component": "Toggle",
11574
+ "reason": "a setting that applies as soon as it flips"
11575
+ },
11576
+ {
11577
+ "component": "Radio",
11578
+ "reason": "exactly one choice from a set"
11579
+ }
11580
+ ]
11581
+ }
11582
+ },
11583
+ "FormActions": {
11584
+ "category": "Actions",
11585
+ "categorySource": "jsdoc",
11586
+ "governedCategory": true,
11587
+ "hidden": false,
11588
+ "docExempt": false,
11589
+ "filePath": "src/app/components/form-actions.tsx",
11590
+ "description": "Form footer with one fixed order: destructive (far left, if any), then secondary, then primary last and right-most. Gap is the tight layout token.",
11591
+ "figmaUrl": null,
11592
+ "figmaId": null,
11593
+ "figmaLink": null,
11594
+ "tier": "pattern",
11595
+ "preview": {
11596
+ "exportName": "FormActions",
11597
+ "sizing": "panel"
11598
+ },
11599
+ "consumers": [
11600
+ "src/app/components/form-actions.test.tsx",
11601
+ "src/stories/form-actions.stories.tsx",
11602
+ "src/stories/patterns-client-detail.stories.tsx"
11603
+ ],
11604
+ "tokenMapping": {},
11605
+ "variantAxes": [],
11606
+ "componentProperties": [],
11607
+ "props": {
11608
+ "destructive": {
11609
+ "type": "ReactNode",
11610
+ "optional": true
11611
+ },
11612
+ "primary": {
11613
+ "type": "ReactNode"
11614
+ },
11615
+ "secondary": {
11616
+ "type": "ReactNode",
11617
+ "optional": true
11618
+ },
11619
+ "sticky": {
11620
+ "type": "boolean",
11621
+ "default": false
11622
+ }
11623
+ },
11624
+ "allowedChildren": [
11625
+ "*"
11626
+ ],
11627
+ "propConstraints": {},
11628
+ "requiredProps": [],
11629
+ "a11yRules": [],
11630
+ "storyFiles": [
11631
+ "src/stories/form-actions.stories.tsx"
11632
+ ],
11633
+ "storyIds": [
11634
+ "patterns-formactions--primary-only",
11635
+ "patterns-formactions--sticky",
11636
+ "patterns-formactions--with-destructive",
11637
+ "patterns-formactions--with-secondary"
11638
+ ]
11639
+ },
11640
+ "MetricTile": {
11641
+ "category": "Display",
11642
+ "categorySource": "jsdoc",
11643
+ "governedCategory": true,
11644
+ "hidden": false,
11645
+ "docExempt": false,
11646
+ "filePath": "src/app/components/metric-tiles.tsx",
11647
+ "description": "One metric tile: eyebrow label, `heading2` value, caption sub line, on a raised surface at one fixed min-height. Wraps `Card.Metric` (the sibling with the eyebrow / h2 / caption scale) and adds the surface and the fixed height, so a tile needs no enclosing `Card`.",
11648
+ "figmaUrl": null,
11649
+ "figmaId": null,
11650
+ "figmaLink": null,
11651
+ "tier": "pattern",
11652
+ "preview": {
11653
+ "exportName": "MetricTile",
11654
+ "sizing": "panel"
11655
+ },
11656
+ "consumers": [
11657
+ "src/app/components/metric-tiles.test.tsx",
11658
+ "src/stories/metric-tiles.stories.tsx",
11659
+ "src/stories/patterns-client-detail.stories.tsx"
11660
+ ],
11661
+ "tokenMapping": {},
11662
+ "variantAxes": [],
11663
+ "componentProperties": [],
11664
+ "props": {
11665
+ "label": {
11666
+ "type": "ReactNode"
11667
+ },
11668
+ "sub": {
11669
+ "type": "ReactNode",
11670
+ "optional": true
11671
+ },
11672
+ "tone": {
11673
+ "type": "enum",
11674
+ "values": [
11675
+ "neutral",
11676
+ "success",
11677
+ "warning",
11678
+ "danger",
11679
+ "info"
11680
+ ],
11681
+ "default": "neutral"
11682
+ },
11683
+ "value": {
11684
+ "type": "ReactNode"
11685
+ }
11686
+ },
11687
+ "allowedChildren": [
11688
+ "*"
11689
+ ],
11690
+ "propConstraints": {},
11691
+ "requiredProps": [],
11692
+ "a11yRules": [],
11693
+ "storyFiles": [
11694
+ "src/stories/metric-tiles.stories.tsx"
11695
+ ],
11696
+ "storyIds": [
11697
+ "patterns-metrictiles--four-tiles",
11698
+ "patterns-metrictiles--sub-line-optional",
11699
+ "patterns-metrictiles--three-tiles",
11700
+ "patterns-metrictiles--tones"
11701
+ ]
11702
+ },
11703
+ "MetricTiles": {
11704
+ "category": "Display",
11705
+ "categorySource": "jsdoc",
11706
+ "governedCategory": true,
11707
+ "hidden": false,
11708
+ "docExempt": false,
11709
+ "filePath": "src/app/components/metric-tiles.tsx",
11710
+ "description": "A row of `MetricTile`s. The grid has `min(tiles, 4)` columns, so three tiles fill three columns and never leave an empty fourth. The default for any row of headline numbers on a screen; use `Stat` only for an inline number inside prose or a dense list, `Card.Metric` only inside an existing `Card`, and `StatusTile` for state with notes (never a number).",
11711
+ "figmaUrl": null,
11712
+ "figmaId": null,
11713
+ "figmaLink": null,
11714
+ "tier": "pattern",
11715
+ "preview": {
11716
+ "exportName": "MetricTiles",
11717
+ "sizing": "panel"
11718
+ },
11719
+ "consumers": [
11720
+ "src/app/components/metric-tiles.test.tsx",
11721
+ "src/stories/metric-tiles.stories.tsx",
11722
+ "src/stories/patterns-client-detail.stories.tsx"
11723
+ ],
11724
+ "tokenMapping": {},
11725
+ "variantAxes": [],
11726
+ "componentProperties": [],
11727
+ "props": {
11728
+ "children": {
11729
+ "type": "ReactNode"
11730
+ }
11731
+ },
11732
+ "allowedChildren": [
11733
+ "*"
11734
+ ],
11735
+ "propConstraints": {},
11736
+ "requiredProps": [],
11737
+ "a11yRules": [],
11738
+ "storyFiles": [
11739
+ "src/stories/metric-tiles.stories.tsx"
11740
+ ],
11741
+ "storyIds": [
11742
+ "patterns-metrictiles--four-tiles",
11743
+ "patterns-metrictiles--sub-line-optional",
11744
+ "patterns-metrictiles--three-tiles",
11745
+ "patterns-metrictiles--tones"
11746
+ ]
11747
+ },
11748
+ "PageHeader": {
11749
+ "category": "Layout",
11750
+ "categorySource": "jsdoc",
11751
+ "governedCategory": true,
11752
+ "hidden": false,
11753
+ "docExempt": false,
11754
+ "filePath": "src/app/components/page-header.tsx",
11755
+ "description": "Screen header: breadcrumb slot, the title at the one canonical page-title size (`heading2`), a status slot and an actions slot. Every screen has exactly one. `display` and `h1` type are reserved for marketing and landing surfaces. Distinct from the docs-only page header in `src/docs-tooling`.",
11756
+ "figmaUrl": null,
11757
+ "figmaId": null,
11758
+ "figmaLink": null,
11759
+ "tier": "pattern",
11760
+ "preview": {
11761
+ "exportName": "PageHeader",
11762
+ "sizing": "panel"
11763
+ },
11764
+ "consumers": [
11765
+ "src/app/components/page-header.test.tsx",
11766
+ "src/stories/page-header.stories.tsx",
11767
+ "src/stories/patterns-client-detail.stories.tsx"
11768
+ ],
11769
+ "tokenMapping": {},
11770
+ "variantAxes": [],
11771
+ "componentProperties": [],
11772
+ "props": {
11773
+ "actions": {
11774
+ "type": "ReactNode",
11775
+ "optional": true
11776
+ },
11777
+ "breadcrumb": {
11778
+ "type": "ReactNode",
11779
+ "optional": true
11780
+ },
11781
+ "level": {
11782
+ "type": "PageHeaderLevel",
11783
+ "default": 1
11784
+ },
11785
+ "status": {
11786
+ "type": "ReactNode",
11787
+ "optional": true
11788
+ },
11789
+ "title": {
11790
+ "type": "ReactNode"
11791
+ }
11792
+ },
11793
+ "allowedChildren": [
11794
+ "*"
11795
+ ],
11796
+ "propConstraints": {},
11797
+ "requiredProps": [],
11798
+ "a11yRules": [],
11799
+ "storyFiles": [
11800
+ "src/stories/page-header.stories.tsx",
11801
+ "src/stories/patterns-client-detail.stories.tsx"
11802
+ ],
11803
+ "storyIds": [
11804
+ "patterns-client-detail-screen--compact",
11805
+ "patterns-client-detail-screen--dark",
11806
+ "patterns-client-detail-screen--light",
11807
+ "patterns-client-detail-screen--phone-390",
11808
+ "patterns-pageheader--default",
11809
+ "patterns-pageheader--long-title-wraps",
11810
+ "patterns-pageheader--nested-level",
11811
+ "patterns-pageheader--title-only",
11812
+ "patterns-pageheader--with-actions"
11813
+ ]
11814
+ },
11815
+ "DataTableSection": {
11816
+ "category": "Display",
11817
+ "categorySource": "jsdoc",
11818
+ "governedCategory": true,
11819
+ "hidden": false,
11820
+ "docExempt": false,
11821
+ "filePath": "src/app/components/data-table-section.tsx",
11822
+ "description": "Section heading and toolbar over a `Table`. Row actions are consumer nodes in a trailing column, the table scrolls horizontally on narrow widths without a `minWidth` from the caller, and zero rows shows an `EmptyState`.",
11823
+ "figmaUrl": null,
11824
+ "figmaId": null,
11825
+ "figmaLink": null,
11826
+ "tier": "pattern",
11827
+ "preview": {
11828
+ "exportName": "DataTableSection",
11829
+ "sizing": "panel"
11830
+ },
11831
+ "consumers": [
11832
+ "src/app/components/data-table-section.test.tsx",
11833
+ "src/stories/data-table-section.stories.tsx",
11834
+ "src/stories/patterns-client-detail.stories.tsx"
11835
+ ],
11836
+ "tokenMapping": {},
11837
+ "variantAxes": [],
11838
+ "componentProperties": [],
11839
+ "props": {
11840
+ "actionsLabel": {
11841
+ "type": "string",
11842
+ "default": "Actions"
11843
+ },
11844
+ "columns": {
11845
+ "type": "TableColumn[]"
11846
+ },
11847
+ "emptyDescription": {
11848
+ "type": "ReactNode",
11849
+ "optional": true
11850
+ },
11851
+ "emptyTitle": {
11852
+ "type": "ReactNode",
11853
+ "default": "Nothing here yet"
11854
+ },
11855
+ "level": {
11856
+ "type": "2 | 3 | 4 | 5 | 6",
11857
+ "default": 2
11858
+ },
11859
+ "rows": {
11860
+ "type": "DataTableSectionRow[]"
11861
+ },
11862
+ "title": {
11863
+ "type": "ReactNode"
11864
+ },
11865
+ "toolbar": {
11866
+ "type": "ReactNode",
11867
+ "optional": true
11868
+ }
11869
+ },
11870
+ "allowedChildren": [
11871
+ "*"
11872
+ ],
11873
+ "propConstraints": {},
11874
+ "requiredProps": [],
11875
+ "a11yRules": [],
11876
+ "storyFiles": [
11877
+ "src/stories/data-table-section.stories.tsx"
11878
+ ],
11879
+ "storyIds": [
11880
+ "patterns-datatablesection--dark",
11881
+ "patterns-datatablesection--default",
11882
+ "patterns-datatablesection--empty",
11883
+ "patterns-datatablesection--phone-390",
11884
+ "patterns-datatablesection--without-row-actions"
11885
+ ]
11886
+ },
11887
+ "DestructiveSection": {
11888
+ "category": "Actions",
11889
+ "categorySource": "jsdoc",
11890
+ "governedCategory": true,
11891
+ "hidden": false,
11892
+ "docExempt": false,
11893
+ "filePath": "src/app/components/destructive-section.tsx",
11894
+ "description": "Titled danger zone: a title, an explanation, and one danger `Button` that opens an `AlertDialog`. Pressing the button never runs the action; only the dialog's confirm does. Place it last on the screen, below the form.",
11895
+ "figmaUrl": null,
11896
+ "figmaId": null,
11897
+ "figmaLink": null,
11898
+ "tier": "pattern",
11899
+ "preview": {
11900
+ "exportName": "DestructiveSection",
11901
+ "sizing": "panel"
11902
+ },
11903
+ "consumers": [
11904
+ "src/app/components/destructive-section.test.tsx",
11905
+ "src/stories/destructive-section.stories.tsx",
11906
+ "src/stories/patterns-client-detail.stories.tsx"
11907
+ ],
11908
+ "tokenMapping": {},
11909
+ "variantAxes": [],
11910
+ "componentProperties": [],
11911
+ "props": {
11912
+ "actionLabel": {
11913
+ "type": "ReactNode",
11914
+ "optional": true
11915
+ },
11916
+ "cancelLabel": {
11917
+ "type": "string",
11918
+ "default": "Cancel"
11919
+ },
11920
+ "confirmBody": {
11921
+ "type": "ReactNode"
11922
+ },
11923
+ "confirmLabel": {
11924
+ "type": "string"
11925
+ },
11926
+ "description": {
11927
+ "type": "ReactNode"
11928
+ },
11929
+ "level": {
11930
+ "type": "2 | 3 | 4 | 5 | 6",
11931
+ "default": 2
11932
+ },
11933
+ "onConfirm": {
11934
+ "type": "() => void"
11935
+ },
11936
+ "title": {
11937
+ "type": "ReactNode"
11938
+ }
11939
+ },
11940
+ "allowedChildren": [
11941
+ "*"
11942
+ ],
11943
+ "propConstraints": {},
11944
+ "requiredProps": [],
11945
+ "a11yRules": [],
11946
+ "storyFiles": [
11947
+ "src/stories/destructive-section.stories.tsx"
11948
+ ],
11949
+ "storyIds": [
11950
+ "patterns-destructivesection--dark",
11951
+ "patterns-destructivesection--default",
11952
+ "patterns-destructivesection--phone",
11953
+ "patterns-destructivesection--separate-button-label"
10456
11954
  ]
10457
11955
  },
10458
11956
  "HdsPhosphor": {
@@ -11443,7 +12941,7 @@
11443
12941
  "governedCategory": true,
11444
12942
  "hidden": false,
11445
12943
  "filePath": "src/docs-tooling/lab/legacy-token-list.tsx",
11446
- "description": "LegacyTokenList - legacy token grouping list retained for lab-side maintenance workflows. architecture per TASKS.md \"Stale / Superseded\" → \"Live token inspector UI\". Pruning deferred until /hds/tokens is retired or rewritten — see docs/archive/work/2026-05-01-token-explorer-prune-deferred.md.",
12944
+ "description": "LegacyTokenList - legacy token grouping list retained for lab-side maintenance workflows.",
11447
12945
  "figmaUrl": null,
11448
12946
  "figmaId": null,
11449
12947
  "preview": {
@@ -11487,7 +12985,7 @@
11487
12985
  "governedCategory": true,
11488
12986
  "hidden": false,
11489
12987
  "filePath": "src/docs-tooling/lab/token-collection-list.tsx",
11490
- "description": "TokenCollectionList - grouped token inventory list for lab and explorer maintenance. architecture per TASKS.md \"Stale / Superseded\" → \"Live token inspector UI\". Pruning deferred until /hds/tokens is retired or rewritten — see docs/archive/work/2026-05-01-token-explorer-prune-deferred.md.",
12988
+ "description": "TokenCollectionList - grouped token inventory list for lab and explorer maintenance.",
11491
12989
  "figmaUrl": null,
11492
12990
  "figmaId": null,
11493
12991
  "preview": {
@@ -11720,7 +13218,9 @@
11720
13218
  },
11721
13219
  "consumers": [
11722
13220
  "src/app/components/asset-img.tsx",
11723
- "src/app/components/hds-tooltip.tsx"
13221
+ "src/app/components/hds-tooltip.tsx",
13222
+ "src/app/context/__tests__/portal-hydration.test.tsx",
13223
+ "src/app/context/__tests__/portal-scope.test.tsx"
11724
13224
  ],
11725
13225
  "tokenMapping": {},
11726
13226
  "variantAxes": [],