@hirobius/design-system 0.19.1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CONSUMING.md +9 -6
  2. package/DESIGN.md +7 -5
  3. package/README.md +14 -11
  4. package/codemods/hds-prefix.mjs +231 -0
  5. package/codemods/jsx-fold.mjs +515 -0
  6. package/codemods/not-found-pattern.mjs +71 -0
  7. package/codemods/patterns-subpath.mjs +242 -81
  8. package/codemods/patterns-subpath.names.json +41 -15
  9. package/codemods/removed-0.20.json +194 -0
  10. package/codemods/tile-grid.mjs +283 -0
  11. package/codemods/unrewritable.mjs +291 -0
  12. package/dist/chunks/DemoStateContext-Cz5TmrYu.js +32 -0
  13. package/dist/chunks/empty-state-BBqhCx0S.js +1217 -0
  14. package/dist/contexts.js +157 -78
  15. package/dist/hirobius-ui.js +1517 -5270
  16. package/dist/manifest.js +12 -13
  17. package/dist/patterns.js +780 -513
  18. package/dist/styles.css +1 -1
  19. package/dist/tokens.css +1 -1
  20. package/dist/tokens.js +29 -8
  21. package/dist/types/src/app/components/avatar-group.d.ts +1 -2
  22. package/dist/types/src/app/components/badge.d.ts +8 -3
  23. package/dist/types/src/app/components/blockquote.d.ts +1 -2
  24. package/dist/types/src/app/components/box-sx.d.ts +110 -13
  25. package/dist/types/src/app/components/box.d.ts +6 -3
  26. package/dist/types/src/app/components/breadcrumb.d.ts +0 -5
  27. package/dist/types/src/app/components/button.d.ts +33 -4
  28. package/dist/types/src/app/components/card.d.ts +7 -8
  29. package/dist/types/src/app/components/combobox.d.ts +47 -11
  30. package/dist/types/src/app/components/container.d.ts +2 -2
  31. package/dist/types/src/app/components/data-table-section.d.ts +1 -1
  32. package/dist/types/src/app/components/dialog.d.ts +7 -1
  33. package/dist/types/src/app/components/disclosure.d.ts +1 -5
  34. package/dist/types/src/app/components/field.d.ts +1 -2
  35. package/dist/types/src/app/components/grid.d.ts +10 -6
  36. package/dist/types/src/app/components/hds-tooltip.d.ts +12 -2
  37. package/dist/types/src/app/components/inline-code.d.ts +1 -2
  38. package/dist/types/src/app/components/input.d.ts +8 -5
  39. package/dist/types/src/app/components/kbd.d.ts +1 -2
  40. package/dist/types/src/app/components/metadata-list.d.ts +1 -2
  41. package/dist/types/src/app/components/page-header.d.ts +0 -2
  42. package/dist/types/src/app/components/popover.d.ts +8 -0
  43. package/dist/types/src/app/components/progress.d.ts +33 -6
  44. package/dist/types/src/app/components/segmented-control.d.ts +2 -26
  45. package/dist/types/src/app/components/select.d.ts +10 -1
  46. package/dist/types/src/app/components/skeleton.d.ts +2 -3
  47. package/dist/types/src/app/components/spinner.d.ts +1 -2
  48. package/dist/types/src/app/components/stack.d.ts +4 -1
  49. package/dist/types/src/app/components/stat.d.ts +1 -2
  50. package/dist/types/src/app/components/status-dot.d.ts +18 -4
  51. package/dist/types/src/app/components/status-list-item.d.ts +1 -2
  52. package/dist/types/src/app/components/surface.d.ts +2 -3
  53. package/dist/types/src/app/components/switcher.d.ts +1 -1
  54. package/dist/types/src/app/components/table.d.ts +1 -15
  55. package/dist/types/src/app/components/tag.d.ts +0 -6
  56. package/dist/types/src/app/components/text.d.ts +1 -2
  57. package/dist/types/src/app/components/textarea.d.ts +1 -2
  58. package/dist/types/src/app/components/toast.d.ts +1 -2
  59. package/dist/types/src/app/components/tooltip.d.ts +1 -1
  60. package/dist/types/src/app/context/DemoStateContext.d.ts +1 -1
  61. package/dist/types/src/app/context/RouterContext.d.ts +5 -5
  62. package/dist/types/src/app/data/manifest-types.d.ts +6 -5
  63. package/dist/types/src/app/design-system/generated-token-refs.d.ts +8 -0
  64. package/dist/types/src/app/design-system/generated-token-values.d.ts +1 -0
  65. package/dist/types/src/app/design-system/tokens.d.ts +22 -3
  66. package/dist/types/src/icons.d.ts +1 -1
  67. package/dist/types/src/index.d.ts +33 -124
  68. package/dist/types/src/patterns.d.ts +20 -25
  69. package/dist/variables.css +6 -0
  70. package/docs/CONSUMING.md +21 -13
  71. package/hirobius.tokens.json +48 -15
  72. package/llms.txt +19 -20
  73. package/package.json +17 -22
  74. package/public/hds-manifest.json +2405 -6537
  75. package/public/llms/components.txt +41 -423
  76. package/public/llms/layout.txt +4 -4
  77. package/public/llms-full.txt +67 -448
  78. package/public/llms.txt +19 -20
  79. package/src/app/data/component-api.json +1379 -3271
  80. package/dist/chunks/LanguageContext-BxdCwiFg.js +0 -95
  81. package/dist/chunks/TokenDisplayContext-DKYJMVWk.js +0 -26
  82. package/dist/chunks/activity-feed-BGQ6v3wc.js +0 -22040
  83. package/dist/types/src/app/components/activity-feed.d.ts +0 -73
  84. package/dist/types/src/app/components/app-shell.d.ts +0 -40
  85. package/dist/types/src/app/components/aspect-ratio.d.ts +0 -25
  86. package/dist/types/src/app/components/bleed.d.ts +0 -39
  87. package/dist/types/src/app/components/button-group.d.ts +0 -22
  88. package/dist/types/src/app/components/calendar.d.ts +0 -22
  89. package/dist/types/src/app/components/carousel.d.ts +0 -26
  90. package/dist/types/src/app/components/center.d.ts +0 -36
  91. package/dist/types/src/app/components/cinematic-link.d.ts +0 -18
  92. package/dist/types/src/app/components/circular-progress.d.ts +0 -28
  93. package/dist/types/src/app/components/cluster.d.ts +0 -39
  94. package/dist/types/src/app/components/command-palette.d.ts +0 -46
  95. package/dist/types/src/app/components/component-instance-matrix.d.ts +0 -27
  96. package/dist/types/src/app/components/context-menu.d.ts +0 -78
  97. package/dist/types/src/app/components/cover.d.ts +0 -43
  98. package/dist/types/src/app/components/date-input.d.ts +0 -31
  99. package/dist/types/src/app/components/date-range-input.d.ts +0 -34
  100. package/dist/types/src/app/components/date-time-input.d.ts +0 -30
  101. package/dist/types/src/app/components/doc-link-card.d.ts +0 -32
  102. package/dist/types/src/app/components/error-boundary.d.ts +0 -25
  103. package/dist/types/src/app/components/file-input.d.ts +0 -30
  104. package/dist/types/src/app/components/foundation-swatch.d.ts +0 -45
  105. package/dist/types/src/app/components/frame.d.ts +0 -38
  106. package/dist/types/src/app/components/heading-stack.d.ts +0 -52
  107. package/dist/types/src/app/components/history-card.d.ts +0 -12
  108. package/dist/types/src/app/components/hover-card.d.ts +0 -46
  109. package/dist/types/src/app/components/icon-button.d.ts +0 -22
  110. package/dist/types/src/app/components/image-lightbox.d.ts +0 -14
  111. package/dist/types/src/app/components/input-group.d.ts +0 -23
  112. package/dist/types/src/app/components/multi-selector.d.ts +0 -40
  113. package/dist/types/src/app/components/nav-group.d.ts +0 -29
  114. package/dist/types/src/app/components/nav-item.d.ts +0 -33
  115. package/dist/types/src/app/components/not-found-pattern.d.ts +0 -1
  116. package/dist/types/src/app/components/overflow-list.d.ts +0 -21
  117. package/dist/types/src/app/components/selectable-card.d.ts +0 -29
  118. package/dist/types/src/app/components/side-nav.d.ts +0 -23
  119. package/dist/types/src/app/components/sketch.d.ts +0 -19
  120. package/dist/types/src/app/components/stacked-card-rail.d.ts +0 -32
  121. package/dist/types/src/app/components/stepper-field.d.ts +0 -12
  122. package/dist/types/src/app/components/stepper.d.ts +0 -33
  123. package/dist/types/src/app/components/text-lockup.d.ts +0 -38
  124. package/dist/types/src/app/components/tile-grid.d.ts +0 -17
  125. package/dist/types/src/app/components/time-input.d.ts +0 -24
  126. package/dist/types/src/app/components/toggle-button.d.ts +0 -32
  127. package/dist/types/src/app/components/token.d.ts +0 -90
  128. package/dist/types/src/app/components/tokenUtils.d.ts +0 -38
  129. package/dist/types/src/app/components/tokenizer.d.ts +0 -24
  130. package/dist/types/src/app/components/toolbar.d.ts +0 -36
  131. package/dist/types/src/app/components/top-nav.d.ts +0 -23
  132. package/dist/types/src/app/components/tree-list.d.ts +0 -30
  133. package/dist/types/src/app/data/nav-model.d.ts +0 -39
  134. package/dist/types/src/app/hooks/useFocusVisible.d.ts +0 -9
  135. package/dist/types/src/app/layouts/CaseStudyLayout.d.ts +0 -20
  136. package/dist/types/src/app/layouts/DocLayout.d.ts +0 -14
  137. package/dist/types/src/app/layouts/EmbeddedDocLayoutContext.d.ts +0 -6
  138. package/dist/types/src/app/layouts/HdsDocsShell.d.ts +0 -72
  139. package/dist/types/src/app/layouts/HdsSystemDocLayout.d.ts +0 -14
  140. package/dist/types/src/app/lib/hds-search.d.ts +0 -45
  141. package/dist/types/src/app/lib/nav-active.d.ts +0 -16
  142. package/dist/types/src/app/lib/navLevels.d.ts +0 -4
package/dist/tokens.js CHANGED
@@ -190,6 +190,7 @@ const a = {
190
190
  64: "64px",
191
191
  80: "80px",
192
192
  96: "96px",
193
+ 120: "120px",
193
194
  interactive: {
194
195
  min: "44px",
195
196
  minCompact: "24px"
@@ -502,16 +503,25 @@ const o = "var(--primitive-typography-family-primary)", n = "var(--primitive-typ
502
503
  xs: "var(--semantic-space-subgrid-xs)"
503
504
  },
504
505
  component: {
505
- /** @deprecated hds#206 — use `semantic.space.surface.padding`. */
506
+ /**
507
+ * @deprecated hds#206 — use `semantic.space.surface.padding`.
508
+ * @removeIn 1.0.0
509
+ */
506
510
  padding: "var(--semantic-space-surface-padding)",
507
- /** @deprecated hds#206 — use `semantic.space.scale.xs`. */
511
+ /**
512
+ * @deprecated hds#206 — use `semantic.space.scale.xs`.
513
+ * @removeIn 1.0.0
514
+ */
508
515
  gap: "var(--semantic-space-scale-xs)"
509
516
  },
510
517
  stack: {
511
518
  gap: "var(--semantic-space-section-stack)"
512
519
  },
513
520
  layout: {
514
- /** @deprecated hds#206 — use `semantic.space.region.gutter`. */
521
+ /**
522
+ * @deprecated hds#206 — use `semantic.space.region.gutter`.
523
+ * @removeIn 1.0.0
524
+ */
515
525
  gutter: "var(--semantic-space-region-gutter)",
516
526
  gap: "var(--semantic-space-layout-gap)",
517
527
  section: "var(--semantic-layout-section-paddingY)"
@@ -594,10 +604,21 @@ const o = "var(--primitive-typography-family-primary)", n = "var(--primitive-typ
594
604
  large: "var(--primitive-size-24)"
595
605
  // 24px — hero / large empty states
596
606
  },
597
- // ── Density-aware spacing ────────────────────────────────────────────────────
598
- // These vars respond to [data-density="compact"] on <html>.
599
- // Use for component padding/gap that should tighten in compact mode.
600
- // hds.space.px* for fixed measurements that never participate in density.
607
+ // ── Density-aware spacing (deprecated) ───────────────────────────────────────
608
+ // These vars respond to [data-density="compact"] on <html>, and so does
609
+ // semantic.space.scale.*, the one spacing vocabulary (hds#206). The same
610
+ // names mean different pixels here (density.sm is 8px, scale.sm is 16px),
611
+ // so this group is deprecated. Nothing in HDS reads it.
612
+ /**
613
+ * @deprecated hds#206 — use `hds.semantic.space.scale.*`, which compact density
614
+ * remaps too. Same pixels at both densities, one step down the name ladder:
615
+ * `density.sm` → `scale.xs`, `density.md` → `scale.sm`, `density.lg` → `scale.md`,
616
+ * `density.xl` → `scale.lg`, `density.xl2` → `scale.xl`. `density.xs` (4px),
617
+ * `density.xl3` (64px) and `density.xl4` (80px) have no scale step:
618
+ * `hds.space.px4` / `px64` / `px80` keep their comfortable pixels, without the
619
+ * compact remap.
620
+ * @removeIn 1.0.0
621
+ */
601
622
  density: {
602
623
  xs: "var(--hds-space-xs)",
603
624
  // 4px comfortable / 2px compact
@@ -620,7 +641,7 @@ const o = "var(--primitive-typography-family-primary)", n = "var(--primitive-typ
620
641
  // CSS var strings — valid in any inline style property that accepts a length.
621
642
  // Note: avoid interpolating these into template literal shorthand strings,
622
643
  // e.g. `margin: \`0 0 ${hds.space.px20}\`` — use individual properties instead.
623
- // For component spacing that adapts to density, use hds.density.* instead.
644
+ // For component spacing that adapts to density, use hds.semantic.space.scale.* instead.
624
645
  space: {
625
646
  px1: "var(--primitive-space-px1)",
626
647
  px2: "var(--primitive-space-px2)",
@@ -18,5 +18,4 @@ export interface AvatarGroupProps extends Omit<React.HTMLAttributes<HTMLDivEleme
18
18
  }
19
19
  /** Renders up to `max` overlapping avatars followed by a `+N` overflow chip. */
20
20
  export declare const AvatarGroup: React.ForwardRefExoticComponent<AvatarGroupProps & React.RefAttributes<HTMLDivElement>>;
21
- /** @internal — CVA variant helper; compose via AvatarGroup props instead. */
22
- export { overflowBubbleVariants };
21
+ export {};
@@ -2,7 +2,7 @@
2
2
  * Badge - compact feedback badge for neutral and semantic states.
3
3
  * @category Feedback
4
4
  * @tier primitive
5
- * @usage Label a status, state or count with a compact neutral or semantic chip.
5
+ * @usage Label a status, state or count with a compact neutral or semantic chip, or a dot.
6
6
  * @whenNot A chip people can toggle, or a message that needs a sentence.
7
7
  * @useInstead Tag an interactive filter or category chip
8
8
  * @useInstead Alert a message that needs a sentence
@@ -18,8 +18,13 @@ type BadgeVariantProps = VariantProps<typeof badgeVariants>;
18
18
  export interface BadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'style'>, BadgeVariantProps {
19
19
  /** Element rendered as the badge wrapper. Defaults to 'span'. */
20
20
  as?: React.ElementType;
21
+ /** Render a solid status dot with no text (children are ignored). */
22
+ dot?: boolean;
23
+ /** Dot diameter; used only with `dot`. */
24
+ size?: 'sm' | 'md' | 'lg';
25
+ /** Names the dot: role="status" with this aria-label. Without it the dot is aria-hidden. */
26
+ label?: string;
21
27
  }
22
28
  /** Compact metadata/status chip. Tone is the only styling input. */
23
29
  export declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
24
- /** @internal — CVA variant helper; compose via Badge props instead. */
25
- export { badgeVariants };
30
+ export {};
@@ -16,5 +16,4 @@ export interface BlockquoteProps extends React.BlockquoteHTMLAttributes<HTMLQuot
16
16
  }
17
17
  /** A quoted passage; pass `cite` for the source URL and `attribution` for a byline. */
18
18
  export declare const Blockquote: React.ForwardRefExoticComponent<BlockquoteProps & React.RefAttributes<HTMLQuoteElement>>;
19
- /** @internal — CVA variant helper; compose via Blockquote props instead. */
20
- export { blockquoteVariants };
19
+ export {};
@@ -1,13 +1,19 @@
1
1
  /**
2
2
  * box-sx.ts — pure resolver + CSS injector for Box's `sx` prop.
3
3
  *
4
- * Deliberately dependency-free (no React import) so the resolver is unit
5
- * testable in isolation from the component tree. `box.tsx` is the only
6
- * consumer; it re-exports the types below as part of the public `Box` API.
4
+ * Deliberately React-free (its one import is the dev-only `warnOnce`) so the
5
+ * resolver is unit testable in isolation from the component tree. Its
6
+ * consumers: `box.tsx` re-exports the types below as part of the public `Box`
7
+ * API; `stack.tsx` resolves its `gap` through `resolveSpacingValue`, the one
8
+ * spacing resolver (hds#206); and the layout components (Grid, Sidebar,
9
+ * Switcher, Card) resolve theirs through it against `LAYOUT_GAP`, the one copy
10
+ * of the layout-gap names (hds#404).
7
11
  *
8
12
  * @internal — the resolver internals (`resolveSx`, `sxClassName`, `injectSx`)
9
- * are exported for testing but the supported public surface is `Box` + the
10
- * `Sx*` types, both re-exported from `box.tsx`.
13
+ * are exported for testing, and `resolveSpacingValue`, `SpacingVocabulary`,
14
+ * `SPACE_SCALE`, `LAYOUT_GAP_NAMES` and `LAYOUT_GAP` for the components. The
15
+ * supported public surface is `Box` + the `Sx*` types, both re-exported from
16
+ * `box.tsx`.
11
17
  */
12
18
  export declare const BOX_BREAKPOINTS: {
13
19
  readonly xs: 375;
@@ -29,18 +35,108 @@ export type ResponsiveValue<T> = T | Partial<Record<Breakpoint, T>>;
29
35
  export interface SxObject {
30
36
  [key: string]: ResponsiveValue<SxValue> | SxObject | undefined;
31
37
  }
38
+ /** The canonical t-shirt scale, `semantic.space.scale.{xs,sm,md,lg,xl}` (hds#206). */
39
+ export declare const SPACE_SCALE: {
40
+ readonly xs: "var(--semantic-space-scale-xs)";
41
+ readonly sm: "var(--semantic-space-scale-sm)";
42
+ readonly md: "var(--semantic-space-scale-md)";
43
+ readonly lg: "var(--semantic-space-scale-lg)";
44
+ readonly xl: "var(--semantic-space-scale-xl)";
45
+ };
46
+ /**
47
+ * The names a spacing prop accepts, and what any other value means there.
48
+ *
49
+ * An open vocabulary passes any other string through ('auto', '1rem', a
50
+ * `var()`) and reads a number by `numbers`: `'units'` is a count of 4px
51
+ * units (Box `sx`), `'raw'` returns the number as-is for React's inline
52
+ * style to read as px (Stack and Card `gap`).
53
+ *
54
+ * A closed vocabulary resolves its own names and nothing else: any other
55
+ * value, a number included, resolves to `undefined`, so the prop sets no
56
+ * style. That is what the layout components rendered before hds#404, when
57
+ * each looked a value up in a private map.
58
+ */
59
+ export type SpacingVocabulary = {
60
+ readonly names: Readonly<Record<string, string>>;
61
+ readonly numbers: 'units' | 'raw';
62
+ } | {
63
+ readonly names: Readonly<Record<string, string>>;
64
+ readonly closed: true;
65
+ };
66
+ type OpenSpacingVocabulary = Extract<SpacingVocabulary, {
67
+ readonly numbers: unknown;
68
+ }>;
69
+ type ClosedSpacingVocabulary = Extract<SpacingVocabulary, {
70
+ readonly closed: true;
71
+ }>;
72
+ /**
73
+ * The layout-gap names (hds#404): the only copy of the four names the layout
74
+ * components take for a gap, a gutter or a bleed, with the same values as
75
+ * Stack's `gap`:
76
+ *
77
+ * tight → var(--semantic-space-scale-sm)
78
+ * normal → var(--semantic-space-scale-md)
79
+ * inset → var(--semantic-space-scale-lg)
80
+ * spacious → var(--semantic-space-scale-xl)
81
+ *
82
+ * They read the scale steps, so compact density tightens them. Box `sx`'s
83
+ * deprecated names of the same spelling read the fixed layout vars instead
84
+ * (BOX_SX_SPACING below). scripts/check-layout-gap-vocabulary.mjs fails a
85
+ * second copy anywhere else in src/.
86
+ */
87
+ export declare const LAYOUT_GAP_NAMES: {
88
+ readonly tight: "var(--semantic-space-scale-sm)";
89
+ readonly normal: "var(--semantic-space-scale-md)";
90
+ readonly inset: "var(--semantic-space-scale-lg)";
91
+ readonly spacious: "var(--semantic-space-scale-xl)";
92
+ };
93
+ /**
94
+ * Grid, Sidebar and Switcher `gap` (Cluster, Cover, Bleed and Center, which
95
+ * read it too, went in 0.20.0, hds#394): the four layout-gap names, plus
96
+ * `medium` (hds#393), and nothing else. Closed, so an untyped value sets no style, as it did before
97
+ * hds#404 (scripts/__tests__/spacing-computed-lock.test.mjs).
98
+ *
99
+ * `medium` is the 12px default gap of TileGrid (removed in 0.20.0, hds#395),
100
+ * `semantic.space.component.medium`, the step Stack's `medium` reads. Unlike
101
+ * the four names it is fixed: compact density does not remap it, as it did not
102
+ * remap TileGrid's 12px. Only
103
+ * Grid's `gap` type takes it so far. It stays out of LAYOUT_GAP_NAMES, so
104
+ * Card and Stack, which spread those names, do not change.
105
+ */
106
+ export declare const LAYOUT_GAP: {
107
+ names: {
108
+ medium: string;
109
+ tight: "var(--semantic-space-scale-sm)";
110
+ normal: "var(--semantic-space-scale-md)";
111
+ inset: "var(--semantic-space-scale-lg)";
112
+ spacious: "var(--semantic-space-scale-xl)";
113
+ };
114
+ closed: true;
115
+ };
116
+ /**
117
+ * The one spacing resolver for Box `sx`, Stack `gap` and the layout
118
+ * components. A name is looked up in the caller's vocabulary (own keys only,
119
+ * so 'constructor' is not a name). Anything else ('auto', '1rem', a `var()`)
120
+ * passes through an open vocabulary and resolves to `undefined` in a closed
121
+ * one. The return type says which: an open vocabulary never yields
122
+ * `undefined`, so Box cannot emit `margin:undefined`, and a closed one never
123
+ * yields a number.
124
+ */
125
+ export declare function resolveSpacingValue(value: SxValue, vocabulary: OpenSpacingVocabulary): string | number;
126
+ export declare function resolveSpacingValue(value: SxValue, vocabulary: ClosedSpacingVocabulary): string | undefined;
127
+ export declare function resolveSpacingValue(value: SxValue, vocabulary: SpacingVocabulary): string | number | undefined;
32
128
  /**
33
129
  * Resolves an `SxObject` into an ordered array of standalone, top-level CSS
34
130
  * rule strings ready for individual `CSSStyleSheet.insertRule()` calls.
35
131
  *
36
- * Pure — no DOM access. Order: base (non-responsive) rules for every selector
37
- * encountered (outer class first, then each `&`-selector in declaration
38
- * order), followed by `@media (min-width: …)` blocks in ascending breakpoint
39
- * order. Each media block is ONE rule string containing its inner selector
40
- * rules concatenated as plain text — that concatenation is safe (and
41
- * required) because a single `insertRule()` call for an `@media {...}` block
42
- * is one rule; only top-level rule concatenation breaks `insertRule()` (see
43
- * `injectSx` below).
132
+ * Pure apart from a dev-only deprecation warning; no DOM access. Order: base
133
+ * (non-responsive) rules for every selector encountered (outer class first,
134
+ * then each `&`-selector in declaration order), followed by
135
+ * `@media (min-width: …)` blocks in ascending breakpoint order. Each media
136
+ * block is ONE rule string containing its inner selector rules concatenated
137
+ * as plain text — that concatenation is safe (and required) because a single
138
+ * `insertRule()` call for an `@media {...}` block is one rule; only top-level
139
+ * rule concatenation breaks `insertRule()` (see `injectSx` below).
44
140
  */
45
141
  export declare function resolveSx(sx: SxObject, className: string): string[];
46
142
  /** Deterministic class name for an sx object — identical objects (by value) share one class/hash. */
@@ -67,3 +163,4 @@ export declare function sxClassName(sx: SxObject): string;
67
163
  export declare function injectSx(sx: SxObject): string;
68
164
  /** @internal test-only — clears the injection cache and managed stylesheet between test runs. */
69
165
  export declare function __resetBoxSxForTests(): void;
166
+ export {};
@@ -16,9 +16,12 @@
16
16
  * keys, not raw hex/px. Prefer named layout primitives over ad-hoc flex.
17
17
  *
18
18
  * `sx` is a deliberate SUBSET of MUI's sx — not all of CSS-in-JS is a feature:
19
- * - Spacing shorthands (m/p/gap family) resolve numbers off the 4px HDS scale
20
- * (`--primitive-space-<n>`) and named steps ('tight'|'normal'|'inset'|'spacious')
21
- * off `--semantic-space-layout-*`.
19
+ * - Spacing shorthands (m/p/gap family) take the t-shirt scale
20
+ * ('xs'|'sm'|'md'|'lg'|'xl' → `--semantic-space-scale-*`, hds#206) through the
21
+ * resolver Stack's `gap` shares. Numbers still resolve as a count of 4px units
22
+ * (`p: 4` is 16px), and the deprecated 'tight'|'normal'|'inset'|'spacious' still
23
+ * read `--semantic-space-layout-*`, fixed px that compact density does not
24
+ * remap. HDS source may not use raw integers (check-spacing-vocabulary).
22
25
  * - `color`/`bgcolor`/`borderColor`/`fill`/`stroke` resolve dotted token keys
23
26
  * ('content.primary', 'surface.raised', 'border.subtle', 'accent',
24
27
  * 'accent.hover', 'feedback.success', …) to the matching semantic CSS var.
@@ -9,9 +9,6 @@
9
9
  * @figma https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-159
10
10
  */
11
11
  import * as React from 'react';
12
- declare const crumbLabelVariants: (props?: ({
13
- current?: boolean | null | undefined;
14
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
15
12
  /** @public */
16
13
  export interface BreadcrumbItem {
17
14
  /** Visible label for the crumb. */
@@ -32,5 +29,3 @@ export interface BreadcrumbProps extends Omit<React.HTMLAttributes<HTMLElement>,
32
29
  * is marked aria-current="page".
33
30
  */
34
31
  export declare const Breadcrumb: React.ForwardRefExoticComponent<BreadcrumbProps & React.RefAttributes<HTMLElement>>;
35
- /** @internal — CVA variant helper; compose via Breadcrumb instead. */
36
- export { crumbLabelVariants };
@@ -7,6 +7,30 @@
7
7
  */
8
8
  import * as React from 'react';
9
9
  import { type VariantProps } from 'class-variance-authority';
10
+ /**
11
+ * Pressed state (hds#322): an inset box-shadow wash bound to
12
+ * `role.pressed-overlay` (`semantic.color.state.pressed.overlay`: black in
13
+ * light, white in dark; the 5% alpha lives in the class, like `bg-scrim/60`),
14
+ * not the brightness filter it replaces (95% in light, 110% in dark), which
15
+ * had no token behind it and no Figma equivalent. Why an inset shadow and not
16
+ * a pseudo-element: Tailwind v4 composes `--tw-inset-shadow` with the
17
+ * `focus-visible:ring-*` and any consumer `shadow-*` into one `box-shadow`
18
+ * list, so the focus ring, an outer shadow and the press wash all render at
19
+ * once with no `relative`/`after:` classes and no extra DOM; the
20
+ * `inset-shadow-[0_0_0_9999px]` spread fills the padding box, so it works on
21
+ * a transparent tertiary fill and respects the radius. `disabled:pointer-events-none`
22
+ * keeps a disabled control from ever matching `:active`. The wash snaps on
23
+ * and off (`transition-[colors,filter]` is unchanged: the tone variants still
24
+ * hover through the brightness filter), which is also how the Figma Pressed
25
+ * variant behaves. Without `color-mix()` support the fallback is the opaque
26
+ * token, the same fallback Tailwind emits for `bg-scrim/60`.
27
+ *
28
+ * Toggled on (`pressed`, hds#393) is a different state from that momentary
29
+ * wash: `data-pressed="true"` fills with `role.accent` and its foreground,
30
+ * the on-state a toggle needs, so it reads as on at rest, not only mid-click.
31
+ * Only toggle buttons get these classes, so every other Button renders the
32
+ * same markup as before.
33
+ */
10
34
  declare const buttonVariants: (props?: ({
11
35
  variant?: "primary" | "secondary" | "tertiary" | null | undefined;
12
36
  tone?: "success" | "danger" | "warning" | "info" | "neutral" | null | undefined;
@@ -26,17 +50,22 @@ export interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonE
26
50
  iconLeft?: React.ReactNode;
27
51
  /** Trailing icon rendered after the label. */
28
52
  iconRight?: React.ReactNode;
29
- /** Render the button as a square icon-only control. Requires aria-label. */
53
+ /** Render a square icon-only control; `label` becomes its aria-label. */
30
54
  iconOnly?: boolean;
31
55
  /** Disable interaction. Mirrors the native HTML attribute. */
32
56
  disabled?: boolean;
57
+ /** Make it a toggle button (aria-pressed), controlled. */
58
+ pressed?: boolean;
59
+ /** Initial toggle state when `pressed` is not set. */
60
+ defaultPressed?: boolean;
61
+ /** Called with the next pressed state on click. */
62
+ onPressedChange?: (pressed: boolean) => void;
33
63
  }
34
64
  /**
35
65
  * Triggers an action when activated.
36
- * @usage Trigger an action (submit, save, open a dialog) with a text label and optional icons; for an icon-only control pass iconOnly with iconLeft.
66
+ * @usage Trigger an action (submit, save, open a dialog) with a text label and optional icons; for an icon-only control pass iconOnly with iconLeft and label; for an on/off toggle pass pressed.
37
67
  * @whenNot Navigating to another page, where a link is the correct element.
38
68
  * @useInstead InlineLink navigation to another page
39
69
  */
40
70
  export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
41
- /** @internal — CVA variant helper; compose via Button props instead. */
42
- export { buttonVariants };
71
+ export {};
@@ -51,11 +51,6 @@ type GapOption = 'tight' | 'normal' | 'inset' | 'spacious' | keyof typeof hds.sp
51
51
  export type CardVariant = 'default' | 'accent';
52
52
  /** @public */
53
53
  export type CardTone = 'neutral' | 'danger' | 'success' | 'warning' | 'info';
54
- declare const cardVariants: (props?: ({
55
- variant?: "default" | "accent" | null | undefined;
56
- tone?: "success" | "danger" | "warning" | "info" | "neutral" | null | undefined;
57
- bordered?: boolean | null | undefined;
58
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
59
54
  /** @public */
60
55
  export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
61
56
  /** Render-as element for the root wrapper. */
@@ -79,6 +74,12 @@ export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
79
74
  * legibility. Default false — repeated cards in grids should stay
80
75
  * borderless and rely on whitespace, rails, or section dividers. */
81
76
  bordered?: boolean;
77
+ /** Make the card one checkbox-like option (role="checkbox"): click or Space toggles it, Enter does not. A click on a control inside it is left to that control. */
78
+ selectable?: boolean;
79
+ /** Whether a selectable card is selected. Controlled: pair with onSelectedChange. */
80
+ selected?: boolean;
81
+ /** Called with the next selected state when a selectable card is toggled. */
82
+ onSelectedChange?: (selected: boolean) => void;
82
83
  }
83
84
  interface CardComponent extends React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>> {
84
85
  Header: typeof CardHeader;
@@ -138,12 +139,10 @@ declare const CardMetric: React.ForwardRefExoticComponent<CardMetricProps & Reac
138
139
  * Tagged per-export, not on the file block: this module exports eight
139
140
  * components and a file-level @figma would hand all eight this one node.
140
141
  * @figma https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=39-11
141
- * @usage Group related content on a raised surface with header, body, footer and metric slots.
142
+ * @usage Group related content on a raised surface with header, body, footer and metric slots, or as one selectable option.
142
143
  * @whenNot A bare padded background with no slot anatomy, or a single headline figure.
143
144
  * @useInstead Surface a padded background without slot anatomy
144
145
  * @useInstead Card.Metric a single headline figure
145
146
  */
146
147
  export declare const Card: CardComponent;
147
148
  export { CardHeader, CardTitle, CardDescription, CardBody, CardFooter, CardProgress, CardMetric };
148
- /** @internal — CVA variant helper; compose via Card props instead. */
149
- export { cardVariants };
@@ -1,22 +1,23 @@
1
1
  /**
2
- * Combobox — searchable single-select (Popover + filtered listbox).
2
+ * Combobox — searchable single- or multi-select (Popover + filtered listbox).
3
3
  * @category Inputs
4
4
  * @tier pattern
5
- * @usage Pick one value from a long list of options, with a search field that filters as you type.
5
+ * @usage Pick one value, or several with `multiple`, from a long list of options, with a search field that filters as you type.
6
6
  * @whenNot A short list that needs no search, or an action list.
7
7
  * @useInstead Select a short list without search
8
8
  * @useInstead Menu firing actions from a trigger
9
9
  * @keyboard Enter/Space Opens the list from the trigger and moves focus to the search field.
10
10
  * @keyboard ArrowDown/ArrowUp Moves the active option and wraps at the ends.
11
11
  * @keyboard Character Filters the options to those matching the typed text.
12
- * @keyboard Enter Commits the active option and closes the list.
12
+ * @keyboard Enter Commits the active option and closes the list; with `multiple`, toggles it and keeps the list open.
13
13
  * @keyboard Escape Closes the list.
14
14
  * @keyboard Tab Stays inside the open list.
15
15
  * @figma https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-237
16
16
  * @doc-exempt: no Inputs-overlay doc page yet — add demo when created
17
17
  *
18
18
  * A select-with-search built on the HDS Popover. The trigger shows the current
19
- * selection; opening reveals a search field that filters the option list.
19
+ * selection (with `multiple`, a count and a removable chip per value); opening
20
+ * reveals a search field that filters the option list.
20
21
  * Full keyboard support (↑/↓ to move, Enter to choose, Esc/outside-click to
21
22
  * close) and listbox/option ARIA. Controlled via `value` + `onChange`.
22
23
  *
@@ -34,14 +35,10 @@ export interface ComboboxOption {
34
35
  label: string;
35
36
  disabled?: boolean;
36
37
  }
37
- /** @public */
38
- export interface ComboboxProps {
38
+ /** Props both arms share; consumers name an arm or `ComboboxAnyProps`. */
39
+ interface ComboboxBaseProps {
39
40
  /** Selectable options. */
40
41
  options: ComboboxOption[];
41
- /** Currently selected value, or null when nothing is chosen. */
42
- value: string | null;
43
- /** Fired with the chosen option's value. */
44
- onChange: (value: string) => void;
45
42
  /** Trigger text when nothing is selected. */
46
43
  placeholder?: string;
47
44
  /** Placeholder for the search field. */
@@ -50,8 +47,47 @@ export interface ComboboxProps {
50
47
  emptyMessage?: string;
51
48
  /** Accessible label for the trigger (when not labelled by a <Field>). */
52
49
  'aria-label'?: string;
50
+ /**
51
+ * Id of the trigger, so a `<label for>` names it. `FormField` sets it, with
52
+ * `aria-describedby` and `aria-invalid`.
53
+ */
54
+ id?: string;
55
+ /** Ids of the elements that describe the trigger (helper text, error). */
56
+ 'aria-describedby'?: string;
57
+ /** Marks the trigger invalid, for example while the field shows an error. */
58
+ 'aria-invalid'?: boolean;
53
59
  className?: string;
54
60
  disabled?: boolean;
55
61
  }
62
+ /**
63
+ * Single-select: one value, or none.
64
+ * @public
65
+ */
66
+ export interface ComboboxProps extends ComboboxBaseProps {
67
+ /** Leave unset (or false) to pick one value. */
68
+ multiple?: false;
69
+ /** Currently selected value, or null when nothing is chosen. */
70
+ value: string | null;
71
+ /** Fired with the chosen option's value. */
72
+ onChange: (value: string) => void;
73
+ }
74
+ /**
75
+ * Multi-select (`multiple`): any number of values.
76
+ * @public
77
+ */
78
+ export interface ComboboxMultipleProps extends ComboboxBaseProps {
79
+ /** Pick any number of values. */
80
+ multiple: true;
81
+ /** Currently selected values, in the order they were picked. */
82
+ value: readonly string[];
83
+ /** Fired with the next selected values whenever one is added or removed. */
84
+ onChange: (value: string[]) => void;
85
+ }
86
+ /**
87
+ * Either arm: single-select `ComboboxProps` or `ComboboxMultipleProps`.
88
+ * @public
89
+ */
90
+ export type ComboboxAnyProps = ComboboxProps | ComboboxMultipleProps;
56
91
  /** @public */
57
- export declare const Combobox: React.ForwardRefExoticComponent<ComboboxProps & React.RefAttributes<HTMLButtonElement>>;
92
+ export declare const Combobox: React.ForwardRefExoticComponent<ComboboxAnyProps & React.RefAttributes<HTMLButtonElement>>;
93
+ export {};
@@ -15,8 +15,8 @@
15
15
  * NOT use the deprecated `padding` prop — it is a no-op; apply padding via
16
16
  * Surface or a Stack instead. Do NOT import Container directly inside a page
17
17
  * under src/app/pages — use Page, which wraps Container and owns vertical
18
- * rhythm. Use Center instead when you also need a horizontal gutter, which
19
- * Container does not support.
18
+ * rhythm. For a horizontal gutter, which Container does not support, put a
19
+ * Box with `style={{ paddingInline }}` inside it.
20
20
  *
21
21
  * Centers content horizontally and applies semantic max-width constraints.
22
22
  * - maxWidth options: 'content' (760px prose) | 'max' (1200px full layout)
@@ -12,7 +12,7 @@ export interface DataTableSectionRow {
12
12
  /** One node per column, in column order. */
13
13
  cells: React.ReactNode[];
14
14
  /**
15
- * Row actions (a `Button` group, a `Menu` trigger, `IconButton`s). Rendered in a
15
+ * Row actions (a `Button` group, a `Menu` trigger, icon-only `Button`s). Rendered in a
16
16
  * trailing column; the pattern bakes in no icon.
17
17
  */
18
18
  actions?: React.ReactNode;
@@ -81,11 +81,17 @@ interface DialogComponent extends React.FC<DialogProps> {
81
81
  * and a file-level @figma would hand all ten this one node.
82
82
  * @usage Interrupt the page with a modal that needs a decision or focused input before people continue.
83
83
  * @whenNot A preview on hover, a message that needs no reply, or content that can stay inline.
84
- * @useInstead HoverCard a preview on hover or focus
84
+ * @useInstead Tooltip a short hint on hover or focus
85
85
  * @useInstead Alert a message that needs no reply
86
86
  * @useInstead ToastProvider a brief confirmation
87
87
  * @slot trigger The element that opens the dialog (Dialog.Trigger).
88
+ * @slot overlay The scrim that dims the page behind the dialog (Dialog.Overlay).
88
89
  * @slot surface The modal surface (Dialog.Content).
90
+ * @slot header Groups the title and description (Dialog.Header).
91
+ * @slot title The heading that names the dialog (Dialog.Title).
92
+ * @slot description Supporting text announced with the title (Dialog.Description).
93
+ * @slot footer The row of actions (Dialog.Footer).
94
+ * @slot close The button that closes the dialog (Dialog.Close, or the X built into Dialog.Content).
89
95
  * @keyboard Enter/Space Opens the dialog from the trigger and moves focus inside it.
90
96
  * @keyboard Escape Closes the dialog and returns focus to the trigger.
91
97
  * @keyboard Tab Cycles focus inside the open dialog.
@@ -9,9 +9,6 @@
9
9
  */
10
10
  import React, { type CSSProperties, type ReactNode } from 'react';
11
11
  type DisclosureVariant = 'panel' | 'nav' | 'card';
12
- declare const disclosureTriggerVariants: (props?: ({
13
- variant?: "nav" | "panel" | "card" | null | undefined;
14
- } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
15
12
  export type DisclosureProps = {
16
13
  /** Summary label rendered in the disclosure trigger. Accepts a string or ReactNode for icon+label combos. */
17
14
  label: ReactNode;
@@ -36,5 +33,4 @@ export type DisclosureProps = {
36
33
  };
37
34
  /** @public */
38
35
  export declare const Disclosure: React.ForwardRefExoticComponent<DisclosureProps & React.RefAttributes<HTMLDivElement>>;
39
- /** @internal — CVA variant helper; compose via Disclosure props instead. */
40
- export { disclosureTriggerVariants };
36
+ export {};
@@ -24,5 +24,4 @@ export interface FieldProps extends Omit<React.HTMLAttributes<HTMLDivElement>, '
24
24
  * Caption label paired with a value — used in metadata grids and read-only forms.
25
25
  */
26
26
  export declare const Field: React.ForwardRefExoticComponent<FieldProps & React.RefAttributes<HTMLDivElement>>;
27
- /** @internal — CVA variant helper; compose via Field props instead. */
28
- export { fieldValueVariants };
27
+ export {};
@@ -7,13 +7,14 @@
7
7
  * @useInstead Stack a single row or column
8
8
  * @useInstead Box one-off layout that no named primitive covers
9
9
  * @ai-intent Solves multi-column layout and repeatable alignment with token-governed gaps, responsive column collapse, and a first-class subgrid escape hatch for nested structure.
10
- * @ai-rules 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.
10
+ * @ai-rules 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, auto-fill, or subgrid modes already express the layout. Do NOT use Grid for simple one-dimensional stacks where Stack is sufficient.
11
11
  *
12
12
  * Enforces semantic gap and column values. No arbitrary CSS grid.
13
13
  * - layout='fixed': responsive base (collapses via CSS at tablet/mobile).
14
14
  * `columns` sets desktop count (default 12). Tablet/mobile
15
15
  * clamp to min(8, cols) and min(4, cols) respectively.
16
16
  * - layout='auto-fit': responsive card wrapping via auto-fit.
17
+ * - layout='auto-fill': tile wrapping at `minItemWidth` (TileGrid's recipe; 0.20.0 removed TileGrid).
17
18
  * - subgrid=true: sets gridTemplateColumns:'subgrid' for nested alignment.
18
19
  *
19
20
  * Usage (default responsive 12-col):
@@ -29,16 +30,19 @@
29
30
  * </Grid>
30
31
  */
31
32
  import React, { type ReactNode, type CSSProperties } from 'react';
32
- type SemanticGap = 'tight' | 'normal' | 'inset' | 'spacious';
33
- type GridLayout = 'fixed' | 'auto-fit';
34
- export interface GridProps {
33
+ type SemanticGap = 'medium' | 'tight' | 'normal' | 'inset' | 'spacious';
34
+ type GridLayout = 'fixed' | 'auto-fit' | 'auto-fill';
35
+ /** Grid's own props, plus any HTML attribute (role, aria-*, id) for its root element. */
36
+ export interface GridProps extends React.HTMLAttributes<HTMLDivElement> {
35
37
  /** Grid content. */
36
38
  children: ReactNode;
37
- /** Grid layout mode: 'fixed' (responsive) or 'auto-fit' (card wrapping). Defaults to 'fixed'. */
39
+ /** Grid layout mode: 'fixed' (responsive), 'auto-fit' (card wrapping) or 'auto-fill' (tile wrapping that keeps empty tracks). Defaults to 'fixed'. */
38
40
  layout?: GridLayout;
41
+ /** Minimum item width before 'auto-fit' or 'auto-fill' wraps, capped at the container width. Defaults to 280px. */
42
+ minItemWidth?: string;
39
43
  /** Desktop column count for layout='fixed'. Tablet clamps to min(8,n), mobile to min(4,n). Defaults to 12. */
40
44
  columns?: number;
41
- /** Gap between grid items: semantic only. Defaults to 'inset' (32px). */
45
+ /** Gap between grid items: semantic only. 'medium' is a fixed 12px. Defaults to 'inset' (32px). */
42
46
  gap?: SemanticGap;
43
47
  /** If true, sets gridTemplateColumns:'subgrid' for nested grid alignment. */
44
48
  subgrid?: boolean;
@@ -2,6 +2,7 @@
2
2
  * Tooltip — accessible hover/focus tooltip on Radix (Overlays).
3
3
  * @category Overlays
4
4
  * @tier primitive
5
+ * @figma https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=93-15
5
6
  * @doc-exempt: no Overlays doc page yet — add demo when the overlays page is created
6
7
  *
7
8
  * Radix Tooltip (@radix-ui/react-tooltip) themed with role tokens. Provides
@@ -12,7 +13,7 @@
12
13
  *
13
14
  * <Tooltip>
14
15
  * <Tooltip.Trigger asChild>
15
- * <IconButton icon={Link} aria-label="Copy link" />
16
+ * <Button iconOnly label="Copy link" iconLeft={<Icon icon={Link} />} />
16
17
  * </Tooltip.Trigger>
17
18
  * <Tooltip.Content>Copy link</Tooltip.Content>
18
19
  * </Tooltip>
@@ -21,7 +22,9 @@
21
22
  * content text (semantic.color.content.inverse) — these are a designed pair, so
22
23
  * the bubble reads correctly in BOTH themes (dark bubble/light text in light
23
24
  * mode, light bubble/dark text in dark mode). Radius 4 (primitive.radius.4),
24
- * shadow-overlay, and a matching arrow. Text reuses the caption type composite.
25
+ * shadow-floating (semantic.elevation.floating, the popover and dropdown
26
+ * shadow; shadow-overlay is for dialogs), and a matching arrow. Text reuses the
27
+ * caption type composite.
25
28
  */
26
29
  import * as React from 'react';
27
30
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
@@ -51,6 +54,13 @@ interface HdsTooltipComponent extends React.FC<React.ComponentProps<typeof Toolt
51
54
  * Tooltip root. Bakes in the Radix Provider so a single `<Tooltip>` is
52
55
  * self-contained — no app-level provider required. Controlled via
53
56
  * `open`/`onOpenChange`, or uncontrolled with `defaultOpen`.
57
+ * @usage Name an icon-only control, or add a short hint that appears on hover and keyboard focus.
58
+ * @whenNot Anything interactive, text people need to finish a task, or a hint touch users must see (touch has no hover).
59
+ * @useInstead Popover interactive or longer content that opens on click
60
+ * @useInstead Text a hint that must stay visible
61
+ * @keyboard Focus Opens the tooltip when the trigger receives keyboard focus.
62
+ * @keyboard Escape Closes the tooltip and keeps focus on the trigger.
63
+ * @keyboard Tab Moves on to the next control and closes the tooltip.
54
64
  * @public
55
65
  */
56
66
  declare const Tooltip: HdsTooltipComponent;