banhaten 0.1.3 → 0.2.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 (258) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/CONTRIBUTING.md +44 -0
  3. package/README.md +65 -13
  4. package/SECURITY.md +15 -0
  5. package/banhaten.config.example.json +0 -2
  6. package/docs/design-system/README.md +9 -0
  7. package/docs/design-system/adoption-quality-remediation.md +87 -0
  8. package/docs/design-system/agent-usage.md +13 -0
  9. package/docs/design-system/appearance-presets.md +6 -1
  10. package/docs/design-system/component-docs-pattern.md +81 -0
  11. package/docs/design-system/component-token-consistency-audit.md +13 -3
  12. package/docs/design-system/components/README.md +3 -2
  13. package/docs/design-system/components/accordion.md +16 -0
  14. package/docs/design-system/components/activity-feed.md +15 -1
  15. package/docs/design-system/components/alert-dialog.md +17 -0
  16. package/docs/design-system/components/alert.md +46 -14
  17. package/docs/design-system/components/aspect-ratio.md +15 -0
  18. package/docs/design-system/components/attribute.md +16 -0
  19. package/docs/design-system/components/autocomplete.md +19 -0
  20. package/docs/design-system/components/avatar.md +18 -0
  21. package/docs/design-system/components/badge.md +19 -0
  22. package/docs/design-system/components/banner.md +15 -1
  23. package/docs/design-system/components/breadcrumbs.md +14 -0
  24. package/docs/design-system/components/button-group.md +34 -0
  25. package/docs/design-system/components/button.md +18 -0
  26. package/docs/design-system/components/card.md +18 -1
  27. package/docs/design-system/components/carousel.md +20 -3
  28. package/docs/design-system/components/catalog-components.md +15 -1
  29. package/docs/design-system/components/chart.md +15 -0
  30. package/docs/design-system/components/checkbox.md +16 -0
  31. package/docs/design-system/components/collapsible.md +15 -0
  32. package/docs/design-system/components/command.md +15 -0
  33. package/docs/design-system/components/context-menu.md +15 -0
  34. package/docs/design-system/components/date-picker.md +21 -1
  35. package/docs/design-system/components/divider.md +16 -0
  36. package/docs/design-system/components/empty-state.md +17 -0
  37. package/docs/design-system/components/field.md +17 -0
  38. package/docs/design-system/components/file-upload.md +14 -0
  39. package/docs/design-system/components/hover-card.md +15 -0
  40. package/docs/design-system/components/input-group.md +17 -0
  41. package/docs/design-system/components/input-otp.md +18 -0
  42. package/docs/design-system/components/input.md +43 -7
  43. package/docs/design-system/components/item.md +72 -0
  44. package/docs/design-system/components/kbd.md +18 -0
  45. package/docs/design-system/components/label.md +16 -0
  46. package/docs/design-system/components/menu.md +17 -0
  47. package/docs/design-system/components/menubar.md +15 -0
  48. package/docs/design-system/components/modal.md +25 -4
  49. package/docs/design-system/components/native-select.md +18 -0
  50. package/docs/design-system/components/navigation-menu.md +15 -0
  51. package/docs/design-system/components/onboarding-step-list-item.md +15 -1
  52. package/docs/design-system/components/page-header.md +15 -1
  53. package/docs/design-system/components/pagination.md +30 -8
  54. package/docs/design-system/components/popover.md +19 -0
  55. package/docs/design-system/components/progress-slider.md +18 -0
  56. package/docs/design-system/components/progress.md +17 -0
  57. package/docs/design-system/components/radio-card.md +16 -0
  58. package/docs/design-system/components/radio-group.md +17 -0
  59. package/docs/design-system/components/resizable.md +15 -0
  60. package/docs/design-system/components/scroll-area.md +15 -0
  61. package/docs/design-system/components/segmented-control.md +71 -0
  62. package/docs/design-system/components/select.md +44 -7
  63. package/docs/design-system/components/sheet.md +17 -0
  64. package/docs/design-system/components/sidebar.md +15 -0
  65. package/docs/design-system/components/skeleton.md +18 -0
  66. package/docs/design-system/components/slideout.md +14 -0
  67. package/docs/design-system/components/slider.md +20 -0
  68. package/docs/design-system/components/social-button.md +21 -3
  69. package/docs/design-system/components/spinner.md +16 -0
  70. package/docs/design-system/components/steps.md +14 -0
  71. package/docs/design-system/components/table.md +15 -1
  72. package/docs/design-system/components/tabs.md +17 -0
  73. package/docs/design-system/components/tag.md +17 -0
  74. package/docs/design-system/components/textarea.md +16 -0
  75. package/docs/design-system/components/timeline.md +14 -0
  76. package/docs/design-system/components/toast.md +17 -0
  77. package/docs/design-system/components/toggle.md +17 -0
  78. package/docs/design-system/components/toolbar.md +21 -1
  79. package/docs/design-system/components/tooltip.md +18 -1
  80. package/docs/design-system/density-and-elevation.md +44 -0
  81. package/docs/design-system/direction-and-localization.md +23 -0
  82. package/docs/design-system/form-recipes.md +73 -0
  83. package/docs/design-system/gap-promotion-policy.md +21 -0
  84. package/docs/design-system/gap-promotion-report.md +166 -0
  85. package/docs/design-system/installation.md +68 -0
  86. package/docs/design-system/launch-comparison-shadcn.md +98 -0
  87. package/docs/design-system/registry-and-cli.md +30 -7
  88. package/docs/design-system/release-policy.md +30 -0
  89. package/docs/design-system/roadmap.md +14 -0
  90. package/docs/design-system/support-matrix.md +23 -0
  91. package/docs/design-system/tabs.md +1 -1
  92. package/docs/design-system/token-governance.md +23 -1
  93. package/package.json +29 -15
  94. package/registry/component-contract.json +40 -0
  95. package/registry/components/alert-dialog.tsx +1 -1
  96. package/registry/components/alert.tsx +86 -65
  97. package/registry/components/autocomplete.tsx +23 -9
  98. package/registry/components/avatar.tsx +7 -7
  99. package/registry/components/badge.tsx +1 -1
  100. package/registry/components/button-group.tsx +321 -4
  101. package/registry/components/button.tsx +38 -17
  102. package/registry/components/card.tsx +68 -59
  103. package/registry/components/carousel.tsx +53 -5
  104. package/registry/components/chart.tsx +36 -3
  105. package/registry/components/checkbox.tsx +3 -3
  106. package/registry/components/collapsible.tsx +1 -1
  107. package/registry/components/command.tsx +1 -1
  108. package/registry/components/context-menu.tsx +1 -1
  109. package/registry/components/date-picker.tsx +245 -104
  110. package/registry/components/expanded/ActivityFeed.tsx +6 -15
  111. package/registry/components/expanded/Banner.tsx +3 -3
  112. package/registry/components/expanded/Breadcrumbs.tsx +5 -5
  113. package/registry/components/expanded/CatalogComponentsShowcase.tsx +13 -13
  114. package/registry/components/expanded/CatalogDivider.tsx +1 -1
  115. package/registry/components/expanded/EmptyState.tsx +1 -1
  116. package/registry/components/expanded/FileUpload.tsx +9 -2
  117. package/registry/components/expanded/OnboardingStepListItem.tsx +2 -4
  118. package/registry/components/expanded/PageHeader.tsx +13 -13
  119. package/registry/components/expanded/Slideout.tsx +15 -415
  120. package/registry/components/expanded/Steps.tsx +4 -4
  121. package/registry/components/expanded/Table.tsx +116 -69
  122. package/registry/components/expanded/Timeline.tsx +3 -3
  123. package/registry/components/expanded/activityFeed.css +1 -1
  124. package/registry/components/expanded/breadcrumbs.css +1 -1
  125. package/registry/components/expanded/divider.css +1 -1
  126. package/registry/components/expanded/emptyState.css +1 -1
  127. package/registry/components/expanded/fileUpload.css +6 -6
  128. package/registry/components/expanded/slideout.css +9 -685
  129. package/registry/components/expanded/steps.css +3 -3
  130. package/registry/components/expanded/table.css +2 -2
  131. package/registry/components/expanded/timeline.css +2 -2
  132. package/registry/components/input-content.ts +1 -0
  133. package/registry/components/input-otp.tsx +13 -3
  134. package/registry/components/input.tsx +68 -43
  135. package/registry/components/item.tsx +189 -0
  136. package/registry/components/kbd.tsx +111 -4
  137. package/registry/components/menu.tsx +31 -245
  138. package/registry/components/menubar.tsx +1 -1
  139. package/registry/components/modal.tsx +142 -102
  140. package/registry/components/native-select.tsx +2 -2
  141. package/registry/components/pagination.tsx +80 -58
  142. package/registry/components/popover.tsx +162 -664
  143. package/registry/components/radio-card.tsx +116 -87
  144. package/registry/components/segmented-control.tsx +87 -0
  145. package/registry/components/select-content.tsx +2 -2
  146. package/registry/components/select.tsx +52 -16
  147. package/registry/components/sheet.tsx +1 -1
  148. package/registry/components/sidebar.tsx +1 -1
  149. package/registry/components/skeleton.css +0 -3
  150. package/registry/components/social-button.tsx +47 -25
  151. package/registry/components/spinner.tsx +18 -55
  152. package/registry/components/tabs.css +1 -1
  153. package/registry/components/tabs.tsx +8 -4
  154. package/registry/components/tag.tsx +2 -2
  155. package/registry/components/textarea.tsx +3 -3
  156. package/registry/components/toast.tsx +16 -11
  157. package/registry/components/toggle.tsx +2 -2
  158. package/registry/components/toolbar.tsx +89 -17
  159. package/registry/components/tooltip.tsx +1 -1
  160. package/registry/examples/alert-demo.tsx +25 -5
  161. package/registry/examples/attribute-demo.tsx +1 -1
  162. package/registry/examples/autocomplete-demo.tsx +3 -3
  163. package/registry/examples/avatar-demo.tsx +7 -7
  164. package/registry/examples/badge-demo.tsx +1 -1
  165. package/registry/examples/button-demo.tsx +6 -6
  166. package/registry/examples/button-group-demo.tsx +23 -2
  167. package/registry/examples/card-demo.tsx +46 -8
  168. package/registry/examples/carousel-demo.tsx +20 -2
  169. package/registry/examples/chart-demo.tsx +1 -1
  170. package/registry/examples/checkbox-demo.tsx +5 -5
  171. package/registry/examples/collection-filter-bar-demo.tsx +135 -0
  172. package/registry/examples/command-demo.tsx +3 -3
  173. package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
  174. package/registry/examples/context-menu-demo.tsx +1 -1
  175. package/registry/examples/control-density-contract-demo.tsx +61 -0
  176. package/registry/examples/date-picker-demo.tsx +12 -12
  177. package/registry/examples/divider-demo.tsx +3 -3
  178. package/registry/examples/expanded/banner-demo.tsx +1 -1
  179. package/registry/examples/expanded/breadcrumbs-demo.tsx +1 -1
  180. package/registry/examples/expanded/empty-state-demo.tsx +1 -1
  181. package/registry/examples/expanded/file-upload-demo.tsx +1 -1
  182. package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
  183. package/registry/examples/expanded/slideout-demo.tsx +2 -2
  184. package/registry/examples/expanded/steps-demo.tsx +1 -1
  185. package/registry/examples/expanded/tabs-demo.tsx +1 -1
  186. package/registry/examples/expanded/timeline-demo.tsx +1 -1
  187. package/registry/examples/hover-card-demo.tsx +2 -2
  188. package/registry/examples/input-demo.tsx +6 -6
  189. package/registry/examples/input-otp-demo.tsx +4 -4
  190. package/registry/examples/item-demo.tsx +46 -0
  191. package/registry/examples/kbd-demo.tsx +1 -1
  192. package/registry/examples/label-demo.tsx +1 -1
  193. package/registry/examples/menu-demo.tsx +1 -1
  194. package/registry/examples/modal-demo.tsx +67 -9
  195. package/registry/examples/navigation-menu-demo.tsx +1 -1
  196. package/registry/examples/pagination-demo.tsx +6 -3
  197. package/registry/examples/popover-demo.tsx +19 -19
  198. package/registry/examples/progress-demo.tsx +1 -1
  199. package/registry/examples/progress-slider-demo.tsx +1 -1
  200. package/registry/examples/radio-card-demo.tsx +4 -4
  201. package/registry/examples/radio-group-demo.tsx +2 -2
  202. package/registry/examples/resizable-demo.tsx +1 -1
  203. package/registry/examples/results-toolbar-demo.tsx +44 -0
  204. package/registry/examples/scroll-area-demo.tsx +3 -3
  205. package/registry/examples/segmented-control-demo.tsx +39 -0
  206. package/registry/examples/select-demo.tsx +1 -1
  207. package/registry/examples/sidebar-demo.tsx +1 -1
  208. package/registry/examples/slider-demo.tsx +3 -3
  209. package/registry/examples/social-button-demo.tsx +18 -8
  210. package/registry/examples/spinner-demo.tsx +13 -13
  211. package/registry/examples/tabs-demo.tsx +1 -1
  212. package/registry/examples/tag-demo.tsx +1 -1
  213. package/registry/examples/textarea-demo.tsx +4 -4
  214. package/registry/examples/toast-demo.tsx +1 -1
  215. package/registry/examples/toggle-demo.tsx +6 -6
  216. package/registry/examples/tooltip-demo.tsx +4 -4
  217. package/registry/guidance/USAGE.md +27 -0
  218. package/registry/hooks/use-direction.ts +193 -13
  219. package/registry/index.json +5311 -377
  220. package/registry/styles/globals.css +2440 -4061
  221. package/registry.json +119 -149
  222. package/schema/config.schema.json +11 -8
  223. package/schema/registry.schema.json +150 -45
  224. package/schema/tokens.schema.json +134 -34
  225. package/src/cli/command-line.js +194 -0
  226. package/src/cli/config-editors.js +9 -0
  227. package/src/cli/doctor.js +399 -0
  228. package/src/cli/file-transaction.js +295 -0
  229. package/src/cli/global-css.js +153 -0
  230. package/src/cli/index.js +567 -1613
  231. package/src/cli/install-plan.js +592 -0
  232. package/src/cli/install-receipt.js +171 -0
  233. package/src/cli/jsonc.js +203 -0
  234. package/src/cli/package-install-state.js +254 -0
  235. package/src/cli/package-manager.js +238 -0
  236. package/src/cli/package-plan.js +185 -0
  237. package/src/cli/package-version.js +97 -0
  238. package/src/cli/registry-query.js +207 -0
  239. package/src/cli/reporting.js +55 -0
  240. package/src/cli/schema-validation.js +19 -0
  241. package/src/cli/source-scanner.js +686 -0
  242. package/src/cli/vite-config.js +478 -0
  243. package/tokens/banhaten.tokens.json +4312 -309
  244. package/docs/design-system/components/command-bar.md +0 -57
  245. package/registry/components/expanded/BannerBoard.tsx +0 -225
  246. package/registry/components/expanded/CatalogTag.tsx +0 -85
  247. package/registry/components/expanded/CommandBar.tsx +0 -386
  248. package/registry/components/expanded/IconExplorer.tsx +0 -612
  249. package/registry/components/expanded/TimelineShowcase.tsx +0 -158
  250. package/registry/components/expanded/commandBar.css +0 -470
  251. package/registry/components/expanded/iconExplorer.css +0 -764
  252. package/registry/components/expanded/iconPacks.ts +0 -866
  253. package/registry/components/expanded/tag.css +0 -148
  254. package/registry/examples/expanded/icons-demo.tsx +0 -5
  255. package/tokens/Color mode.zip +0 -0
  256. package/tokens/Numbers.zip +0 -0
  257. package/tokens/Radius.zip +0 -0
  258. package/tokens/Theme.zip +0 -0
@@ -8,8 +8,8 @@ export function CheckboxDemo() {
8
8
  const [checked, setChecked] = React.useState(true)
9
9
 
10
10
  return (
11
- <div className="grid gap-6">
12
- <div className="flex flex-wrap items-center gap-4">
11
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
12
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-3xl-16)]">
13
13
  <Checkbox
14
14
  checked={checked}
15
15
  onCheckedChange={(value) => setChecked(value === true)}
@@ -20,7 +20,7 @@ export function CheckboxDemo() {
20
20
  <Checkbox disabled aria-label="Disabled option" />
21
21
  </div>
22
22
 
23
- <div className="grid gap-3">
23
+ <div className="grid gap-[var(--bh-space-xl-12)]">
24
24
  <CheckboxCard
25
25
  checked
26
26
  label="Label"
@@ -40,7 +40,7 @@ export function CheckboxDemo() {
40
40
  />
41
41
  </div>
42
42
 
43
- <div dir="rtl" className="grid gap-3">
43
+ <div dir="rtl" className="grid gap-[var(--bh-space-xl-12)]">
44
44
  <CheckboxCard
45
45
  checked
46
46
  label={"\u0627\u0644\u062a\u0633\u0645\u064a\u0629"}
@@ -58,5 +58,5 @@ export function CheckboxDemo() {
58
58
  }
59
59
 
60
60
  function UserLineIcon() {
61
- return <UserIcon aria-hidden="true" focusable="false" strokeWidth={2.1} />
61
+ return <UserIcon aria-hidden="true" focusable="false" strokeWidth="var(--bh-icon-stroke-210)" />
62
62
  }
@@ -0,0 +1,135 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+
5
+ import { DatePicker } from "@/components/ui/date-picker"
6
+ import { Field, FieldLabel } from "@/components/ui/field"
7
+ import {
8
+ Select,
9
+ SelectMenuItem,
10
+ } from "@/components/ui/select"
11
+ import {
12
+ ToolbarButton,
13
+ ToolbarSearch,
14
+ } from "@/components/ui/toolbar"
15
+
16
+ const typeLabels = {
17
+ everything: "Everything",
18
+ articles: "Articles",
19
+ videos: "Videos",
20
+ }
21
+
22
+ const orderLabels = {
23
+ recent: "Recently bookmarked",
24
+ oldest: "Oldest bookmarked",
25
+ title: "Title",
26
+ }
27
+
28
+ export function CollectionFilterBarDemo() {
29
+ const [typeFilter, setTypeFilter] = React.useState<keyof typeof typeLabels>(
30
+ "everything"
31
+ )
32
+ const [order, setOrder] = React.useState<keyof typeof orderLabels>("recent")
33
+ const [dateRevision, setDateRevision] = React.useState(0)
34
+
35
+ return (
36
+ <form
37
+ aria-label="Collection filters"
38
+ data-recipe="collection-filter-bar"
39
+ className="grid w-full min-w-0 gap-[var(--bh-space-xl-12)] rounded-[var(--bh-radius-2xl-12)] bg-[var(--bh-bg-raised)] p-[var(--bh-space-3xl-16)] shadow-[var(--shadow-component-default)]"
40
+ onReset={() => {
41
+ setTypeFilter("everything")
42
+ setOrder("recent")
43
+ setDateRevision((revision) => revision + 1)
44
+ }}
45
+ >
46
+ <ToolbarSearch
47
+ aria-label="Search bookmarks"
48
+ density="default"
49
+ placeholder="Search words, people, or folders"
50
+ shortcutKeys={["Mod", "F"]}
51
+ width="full"
52
+ />
53
+
54
+ <div className="flex min-w-0 flex-wrap items-end gap-[var(--bh-space-xl-12)]">
55
+ <Field
56
+ className="flex-[1_1_var(--bh-date-trigger-width)]"
57
+ controlId="collection-filter-from"
58
+ >
59
+ <FieldLabel tone="subtle">From</FieldLabel>
60
+ <DatePicker
61
+ key={`from-${dateRevision}`}
62
+ className="w-full"
63
+ density="default"
64
+ placeholder="dd/mm/yyyy"
65
+ triggerClassName="w-full"
66
+ triggerProps={{ id: "collection-filter-from" }}
67
+ />
68
+ </Field>
69
+
70
+ <Field
71
+ className="flex-[1_1_var(--bh-date-trigger-width)]"
72
+ controlId="collection-filter-to"
73
+ >
74
+ <FieldLabel tone="subtle">To</FieldLabel>
75
+ <DatePicker
76
+ key={`to-${dateRevision}`}
77
+ className="w-full"
78
+ density="default"
79
+ placeholder="dd/mm/yyyy"
80
+ triggerClassName="w-full"
81
+ triggerProps={{ id: "collection-filter-to" }}
82
+ />
83
+ </Field>
84
+
85
+ <Field
86
+ className="flex-[1_1_var(--bh-date-trigger-width)]"
87
+ controlId="collection-filter-type"
88
+ >
89
+ <FieldLabel tone="subtle">Type</FieldLabel>
90
+ <Select
91
+ className="w-full"
92
+ density="default"
93
+ onValueChange={(value) =>
94
+ setTypeFilter(value as keyof typeof typeLabels)
95
+ }
96
+ selectValue={typeFilter}
97
+ triggerId="collection-filter-type"
98
+ value={typeLabels[typeFilter]}
99
+ >
100
+ <SelectMenuItem label="Everything" value="everything" />
101
+ <SelectMenuItem label="Articles" value="articles" />
102
+ <SelectMenuItem label="Videos" value="videos" />
103
+ </Select>
104
+ </Field>
105
+
106
+ <Field
107
+ className="flex-[1_1_var(--bh-date-trigger-width)]"
108
+ controlId="collection-filter-order"
109
+ >
110
+ <FieldLabel tone="subtle">Order</FieldLabel>
111
+ <Select
112
+ className="w-full"
113
+ density="default"
114
+ onValueChange={(value) =>
115
+ setOrder(value as keyof typeof orderLabels)
116
+ }
117
+ selectValue={order}
118
+ triggerId="collection-filter-order"
119
+ value={orderLabels[order]}
120
+ >
121
+ <SelectMenuItem label="Recently bookmarked" value="recent" />
122
+ <SelectMenuItem label="Oldest bookmarked" value="oldest" />
123
+ <SelectMenuItem label="Title" value="title" />
124
+ </Select>
125
+ </Field>
126
+
127
+ <div className="flex items-end">
128
+ <ToolbarButton density="default" type="reset" variant="link">
129
+ Reset
130
+ </ToolbarButton>
131
+ </div>
132
+ </div>
133
+ </form>
134
+ )
135
+ }
@@ -19,12 +19,12 @@ export function CommandDemo() {
19
19
  <CommandEmpty>No results found.</CommandEmpty>
20
20
  <CommandGroup heading="Pages">
21
21
  <CommandItem value="profile">
22
- <UserIcon className="size-4" />
22
+ <UserIcon className="size-[var(--bh-space-3xl-16)]" />
23
23
  Profile
24
24
  <CommandShortcut>⌘P</CommandShortcut>
25
25
  </CommandItem>
26
26
  <CommandItem value="docs">
27
- <FileTextIcon className="size-4" />
27
+ <FileTextIcon className="size-[var(--bh-space-3xl-16)]" />
28
28
  Docs
29
29
  <CommandShortcut>⌘D</CommandShortcut>
30
30
  </CommandItem>
@@ -32,7 +32,7 @@ export function CommandDemo() {
32
32
  <CommandSeparator />
33
33
  <CommandGroup heading="Actions">
34
34
  <CommandItem value="settings">
35
- <SettingsIcon className="size-4" />
35
+ <SettingsIcon className="size-[var(--bh-space-3xl-16)]" />
36
36
  Settings
37
37
  </CommandItem>
38
38
  </CommandGroup>
@@ -21,7 +21,7 @@ import { Avatar, AvatarIcon, AvatarStatus } from "@/components/ui/avatar"
21
21
  import { Badge } from "@/components/ui/badge"
22
22
  import { Button } from "@/components/ui/button"
23
23
  import {
24
- Menu,
24
+ MenuPreview,
25
25
  MenuItem,
26
26
  MenuItemDescription,
27
27
  MenuItemText,
@@ -34,7 +34,6 @@ import {
34
34
  ToolbarSearch,
35
35
  ToolbarSection,
36
36
  } from "@/components/ui/toolbar"
37
- import { CommandBar } from "@/components/ui/expanded/CommandBar"
38
37
 
39
38
  type ToolTone = "neutral" | "blue" | "green" | "amber" | "purple" | "sky"
40
39
  type ToolIcon = React.ComponentType<React.SVGProps<SVGSVGElement>>
@@ -96,16 +95,7 @@ const toolToneClassNames: Record<ToolTone, string> = {
96
95
  sky: "text-[var(--bh-content-accent-sky-default)]",
97
96
  }
98
97
 
99
- export function CommandBarDemo() {
100
- return (
101
- <div className="grid gap-6">
102
- <CommandBar />
103
- <CommandBar type="results" />
104
- </div>
105
- )
106
- }
107
-
108
- export function AddToolPickerExample() {
98
+ export function CommandPaletteDemo() {
109
99
  return (
110
100
  <ModalSurface
111
101
  aria-label="Add tool command example"
@@ -197,7 +187,7 @@ function ToolRow({ item }: { item: ToolItem }) {
197
187
  const tone = item.tone ?? "neutral"
198
188
 
199
189
  return (
200
- <Menu
190
+ <MenuPreview
201
191
  aria-label={`${item.title} tool action`}
202
192
  className="w-full bg-transparent p-0 shadow-none"
203
193
  width="auto"
@@ -217,7 +207,7 @@ function ToolRow({ item }: { item: ToolItem }) {
217
207
  ].join(" ")}
218
208
  size="lg"
219
209
  >
220
- <Icon aria-hidden="true" strokeWidth={2} />
210
+ <Icon aria-hidden="true" strokeWidth="var(--bh-icon-stroke-200)" />
221
211
  </AvatarIcon>
222
212
  {item.added ? <AvatarStatus size="small" status="available" /> : null}
223
213
  </Avatar>
@@ -241,6 +231,6 @@ function ToolRow({ item }: { item: ToolItem }) {
241
231
  ) : null}
242
232
  </MenuItemText>
243
233
  </MenuItem>
244
- </Menu>
234
+ </MenuPreview>
245
235
  )
246
236
  }
@@ -11,7 +11,7 @@ import {
11
11
  export function ContextMenuDemo() {
12
12
  return (
13
13
  <ContextMenu>
14
- <ContextMenuTrigger className="flex h-32 w-64 items-center justify-center rounded-xl border border-dashed border-[var(--bh-border-default)] text-sm">
14
+ <ContextMenuTrigger className="flex h-[var(--bh-space-12xl-128)] w-[var(--bh-space-16xl-256)] items-center justify-center rounded-xl border border-dashed border-[var(--bh-border-default)] text-sm">
15
15
  Right click
16
16
  </ContextMenuTrigger>
17
17
  <ContextMenuContent>
@@ -0,0 +1,61 @@
1
+ import { Button } from "@/components/ui/button"
2
+ import { DatePicker } from "@/components/ui/date-picker"
3
+ import { Input } from "@/components/ui/input"
4
+ import {
5
+ SegmentedControl,
6
+ SegmentedControlItem,
7
+ } from "@/components/ui/segmented-control"
8
+ import { Select } from "@/components/ui/select"
9
+ import { ToolbarSearch } from "@/components/ui/toolbar"
10
+
11
+ const densities = ["compact", "default", "comfortable"] as const
12
+
13
+ export function ControlDensityContractDemo() {
14
+ return (
15
+ <div
16
+ id="control-density-contract"
17
+ className="grid w-full min-w-0 gap-[var(--bh-space-3xl-16)]"
18
+ >
19
+ {densities.map((density) => (
20
+ <section
21
+ key={density}
22
+ data-control-density-row={density}
23
+ className="grid min-w-0 gap-[var(--bh-space-md-8)] rounded-[var(--bh-radius-xl-10)] bg-[var(--bh-bg-default)] p-[var(--bh-space-xl-12)]"
24
+ >
25
+ <p className="font-mono text-[length:var(--bh-text-body-xs-medium-font-size)] font-[var(--bh-text-body-xs-medium-font-weight)] uppercase text-[var(--bh-content-subtle)]">
26
+ {density}
27
+ </p>
28
+ <div className="flex min-w-0 flex-wrap items-center gap-[var(--bh-space-xl-12)]">
29
+ <Input
30
+ density={density}
31
+ hasHelperText={false}
32
+ hasLabel={false}
33
+ placeholder="Input"
34
+ />
35
+ <Select density={density} value="Select" />
36
+ <DatePicker
37
+ density={density}
38
+ placeholder="Date"
39
+ triggerProps={{ "aria-label": `${density} date` }}
40
+ />
41
+ <Button density={density}>Button</Button>
42
+ <SegmentedControl
43
+ aria-label={`${density} view`}
44
+ defaultValue="grid"
45
+ density={density}
46
+ >
47
+ <SegmentedControlItem value="grid">Grid</SegmentedControlItem>
48
+ <SegmentedControlItem value="list">List</SegmentedControlItem>
49
+ </SegmentedControl>
50
+ <ToolbarSearch
51
+ aria-label={`${density} search`}
52
+ density={density}
53
+ placeholder="Search"
54
+ width="compact"
55
+ />
56
+ </div>
57
+ </section>
58
+ ))}
59
+ </div>
60
+ )
61
+ }
@@ -13,15 +13,15 @@ const selectedRange: CalendarRange = {
13
13
  }
14
14
 
15
15
  const staticPopoverClassName =
16
- "static left-auto top-auto mt-2 translate-x-0"
16
+ "static left-auto top-auto mt-[var(--bh-space-md-8)] translate-x-0"
17
17
  const datePickerClassName =
18
18
  "w-[var(--bh-date-surface-width-picker)] max-w-full"
19
19
  const dateRangePickerClassName = "w-max max-w-none"
20
20
 
21
21
  export function DatePickerDemo() {
22
22
  return (
23
- <div className="grid gap-8">
24
- <div className="grid gap-6 lg:grid-cols-[repeat(auto-fit,minmax(260px,max-content))]">
23
+ <div className="grid gap-[var(--bh-space-6xl-32)]">
24
+ <div className="grid gap-[var(--bh-space-5xl-24)] lg:grid-cols-[repeat(auto-fit,minmax(calc(var(--bh-space-16xl-256)_+_var(--bh-space-xs-4)),max-content))]">
25
25
  <div data-date-demo-item>
26
26
  <Calendar value={selectedDate} />
27
27
  </div>
@@ -30,7 +30,7 @@ export function DatePickerDemo() {
30
30
  </div>
31
31
  </div>
32
32
 
33
- <div className="grid gap-6 xl:grid-cols-2">
33
+ <div className="grid gap-[var(--bh-space-5xl-24)] xl:grid-cols-2">
34
34
  <div data-date-demo-item>
35
35
  <DatePicker
36
36
  calendarProps={{ className: staticPopoverClassName }}
@@ -48,7 +48,7 @@ export function DatePickerDemo() {
48
48
  </div>
49
49
  </div>
50
50
 
51
- <div className="grid gap-6 xl:grid-cols-2">
51
+ <div className="grid gap-[var(--bh-space-5xl-24)] xl:grid-cols-2">
52
52
  <div data-date-demo-item>
53
53
  <DatePicker
54
54
  calendarProps={{ className: staticPopoverClassName }}
@@ -69,7 +69,7 @@ export function DatePickerDemo() {
69
69
  </div>
70
70
  </div>
71
71
 
72
- <div className="grid gap-6 overflow-x-auto">
72
+ <div className="grid gap-[var(--bh-space-5xl-24)] overflow-x-auto">
73
73
  <div data-date-demo-item>
74
74
  <RangeCalendar value={selectedRange} />
75
75
  </div>
@@ -81,15 +81,15 @@ export function DatePickerDemo() {
81
81
  </div>
82
82
  </div>
83
83
 
84
- <div className="grid gap-6 xl:grid-cols-2">
85
- <div data-date-demo-item className="overflow-x-auto pb-2">
84
+ <div className="grid gap-[var(--bh-space-5xl-24)] xl:grid-cols-2">
85
+ <div data-date-demo-item className="overflow-x-auto pb-[var(--bh-space-md-8)]">
86
86
  <DateRangePicker
87
87
  calendarProps={{ className: staticPopoverClassName }}
88
88
  className={dateRangePickerClassName}
89
89
  value={selectedRange}
90
90
  />
91
91
  </div>
92
- <div data-date-demo-item className="overflow-x-auto pb-2" dir="rtl">
92
+ <div data-date-demo-item className="overflow-x-auto pb-[var(--bh-space-md-8)]" dir="rtl">
93
93
  <DateRangePicker
94
94
  calendarProps={{ className: staticPopoverClassName }}
95
95
  className={dateRangePickerClassName}
@@ -100,8 +100,8 @@ export function DatePickerDemo() {
100
100
  </div>
101
101
  </div>
102
102
 
103
- <div className="grid gap-6">
104
- <div data-date-demo-item className="overflow-x-auto pb-2">
103
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
104
+ <div data-date-demo-item className="overflow-x-auto pb-[var(--bh-space-md-8)]">
105
105
  <DateRangePicker
106
106
  calendarProps={{ className: staticPopoverClassName }}
107
107
  className={dateRangePickerClassName}
@@ -110,7 +110,7 @@ export function DatePickerDemo() {
110
110
  value={selectedRange}
111
111
  />
112
112
  </div>
113
- <div data-date-demo-item className="overflow-x-auto pb-2" dir="rtl">
113
+ <div data-date-demo-item className="overflow-x-auto pb-[var(--bh-space-md-8)]" dir="rtl">
114
114
  <DateRangePicker
115
115
  calendarProps={{ className: staticPopoverClassName }}
116
116
  className={dateRangePickerClassName}
@@ -2,13 +2,13 @@ import { Divider } from "@/components/ui/divider"
2
2
 
3
3
  export function DividerDemo() {
4
4
  return (
5
- <div className="grid gap-6">
6
- <div className="grid gap-4">
5
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
6
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
7
7
  <Divider />
8
8
  <Divider type="dotted" />
9
9
  </div>
10
10
 
11
- <div className="flex h-[var(--bh-space-15xl-224)] items-start gap-6">
11
+ <div className="flex h-[var(--bh-space-15xl-224)] items-start gap-[var(--bh-space-5xl-24)]">
12
12
  <Divider direction="vertical" type="dotted" />
13
13
  <Divider direction="vertical" />
14
14
  </div>
@@ -20,7 +20,7 @@ const rtlBannerDemoCopy = {
20
20
 
21
21
  export function BannerDemo() {
22
22
  return (
23
- <div className="grid gap-4">
23
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
24
24
  <Banner {...bannerDemoCopy} />
25
25
  <Banner {...bannerDemoCopy} type="single-action-inline" />
26
26
  <Banner {...bannerDemoCopy} size="full-width" type="single-action" />
@@ -29,7 +29,7 @@ const rtlBreadcrumbItems: BreadcrumbItem[] = [
29
29
 
30
30
  export function BreadcrumbsDemo() {
31
31
  return (
32
- <div className="grid gap-4">
32
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
33
33
  <Breadcrumbs aria-label="Breadcrumb" items={breadcrumbItems} overflowLabel="More" />
34
34
  <Breadcrumbs
35
35
  aria-label="Breadcrumb"
@@ -19,7 +19,7 @@ const inboxActions: EmptyStateAction[] = [
19
19
 
20
20
  export function EmptyStateDemo() {
21
21
  return (
22
- <div className="grid gap-6">
22
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
23
23
  <EmptyState
24
24
  actions={searchActions}
25
25
  description="Try adjusting your search or filters"
@@ -37,7 +37,7 @@ const uploadFiles: FileUploadFile[] = [
37
37
 
38
38
  export function FileUploadDemo() {
39
39
  return (
40
- <div className="grid items-start gap-5 xl:grid-cols-2">
40
+ <div className="grid items-start gap-[var(--bh-space-4xl-20)] xl:grid-cols-2">
41
41
  <FileUpload
42
42
  files={uploadFiles}
43
43
  multiple
@@ -2,7 +2,7 @@ import { OnboardingStepListItem } from "@/components/ui/expanded/OnboardingStepL
2
2
 
3
3
  export function OnboardingStepDemo() {
4
4
  return (
5
- <div className="flex gap-2">
5
+ <div className="flex gap-[var(--bh-space-md-8)]">
6
6
  <OnboardingStepListItem label="Finished" state="finished" />
7
7
  <OnboardingStepListItem label="Active" state="active" />
8
8
  <OnboardingStepListItem label="Inactive" state="inactive" />
@@ -1,4 +1,4 @@
1
- import { Slideout, SlideoutFiltersExample } from "@/components/ui/expanded/Slideout"
1
+ import { Slideout } from "@/components/ui/expanded/Slideout"
2
2
 
3
3
  export function SlideoutDemo() {
4
4
  return (
@@ -9,7 +9,7 @@ export function SlideoutDemo() {
9
9
  secondaryActionLabel="Cancel"
10
10
  title="Heading"
11
11
  >
12
- <SlideoutFiltersExample />
12
+ <p>Slideout content</p>
13
13
  </Slideout>
14
14
  )
15
15
  }
@@ -21,7 +21,7 @@ const stepItems: StepItem[] = Array.from({ length: 6 }, (_, index) => ({
21
21
 
22
22
  export function StepsDemo() {
23
23
  return (
24
- <div className="grid gap-8">
24
+ <div className="grid gap-[var(--bh-space-6xl-32)]">
25
25
  <Steps items={stepItems} />
26
26
  <Steps direction="vertical" items={stepItems} />
27
27
  </div>
@@ -4,7 +4,7 @@ const tabItems = ["Overview", "Details", "Settings", "Activity", "Files"]
4
4
 
5
5
  export function TabsDemo() {
6
6
  return (
7
- <div className="grid gap-6">
7
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
8
8
  <Tabs ariaLabel="Tabs" items={tabItems} />
9
9
  <Tabs ariaLabel="Tabs" items={tabItems} variant="segment" />
10
10
  <Tabs ariaLabel="Tabs" items={tabItems} variant="rounded" />
@@ -10,7 +10,7 @@ const timelineSteps: TimelineStep[] = Array.from({ length: 6 }, (_, index) => ({
10
10
 
11
11
  export function TimelineDemo() {
12
12
  return (
13
- <div className="grid gap-8">
13
+ <div className="grid gap-[var(--bh-space-6xl-32)]">
14
14
  <Timeline ariaLabel="Timeline" steps={timelineSteps} />
15
15
  <Timeline ariaLabel="Timeline" orientation="horizontal" steps={timelineSteps} />
16
16
  </div>
@@ -7,11 +7,11 @@ import {
7
7
  export function HoverCardDemo() {
8
8
  return (
9
9
  <HoverCard>
10
- <HoverCardTrigger className="underline underline-offset-4">
10
+ <HoverCardTrigger className="underline underline-offset-[var(--bh-space-xs-4)]">
11
11
  Workspace profile
12
12
  </HoverCardTrigger>
13
13
  <HoverCardContent>
14
- <div className="grid gap-1">
14
+ <div className="grid gap-[var(--bh-space-xs-4)]">
15
15
  <strong>Design System</strong>
16
16
  <span className="text-sm text-[var(--bh-content-subtle)]">
17
17
  Tokens, components, and RTL-ready examples.
@@ -34,15 +34,15 @@ const demoRtlInputProps = {
34
34
 
35
35
  export function InputDemo() {
36
36
  return (
37
- <div className="grid gap-6">
38
- <div className="flex flex-wrap items-start gap-6">
37
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
38
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
39
39
  <Input {...demoInputProps} />
40
40
  <Input {...demoInputProps} state="filled" />
41
41
  <Input {...demoInputProps} state="error" />
42
42
  <Input {...demoInputProps} state="disabled" />
43
43
  </div>
44
44
 
45
- <div className="flex flex-wrap items-start gap-6">
45
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
46
46
  <Input {...demoInputProps} kind="shortcut" />
47
47
  <Input {...demoInputProps} kind="add-on" />
48
48
  <Input {...demoInputProps} kind="inline-add-on" />
@@ -55,7 +55,7 @@ export function InputDemo() {
55
55
  />
56
56
  </div>
57
57
 
58
- <div className="flex flex-wrap items-start gap-6">
58
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
59
59
  <Input {...demoInputProps} kind="leading-dropdown" />
60
60
  <Input {...demoInputProps} kind="trailing-dropdown" />
61
61
  <Input {...demoInputProps} kind="leading-button" />
@@ -64,13 +64,13 @@ export function InputDemo() {
64
64
  <Input {...demoInputProps} kind="quantity-2" state="filled" valueText="1" />
65
65
  </div>
66
66
 
67
- <div className="flex flex-wrap items-start gap-6">
67
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
68
68
  <Input {...demoInputProps} size="md" />
69
69
  <Input {...demoInputProps} size="md" variant="soft" />
70
70
  <Input {...demoInputProps} size="md" variant="soft" state="error" />
71
71
  </div>
72
72
 
73
- <div dir="rtl" className="flex flex-wrap items-start gap-6">
73
+ <div dir="rtl" className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
74
74
  <Input {...demoRtlInputProps} dir="rtl" />
75
75
  <Input {...demoRtlInputProps} dir="rtl" state="filled" />
76
76
  <Input {...demoRtlInputProps} dir="rtl" state="error" />
@@ -2,8 +2,8 @@ import { InputOTP } from "@/components/ui/input-otp"
2
2
 
3
3
  export function InputOTPDemo() {
4
4
  return (
5
- <div className="grid gap-6">
6
- <div className="flex flex-wrap items-start gap-6">
5
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
6
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
7
7
  <InputOTP
8
8
  label="Verification code"
9
9
  message="Enter the code from your authenticator."
@@ -27,7 +27,7 @@ export function InputOTPDemo() {
27
27
  />
28
28
  </div>
29
29
 
30
- <div className="flex flex-wrap items-start gap-6">
30
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
31
31
  <InputOTP
32
32
  defaultValue="482159"
33
33
  label="Masked code"
@@ -52,7 +52,7 @@ export function InputOTPDemo() {
52
52
  />
53
53
  </div>
54
54
 
55
- <div dir="rtl" className="flex flex-wrap items-start gap-6">
55
+ <div dir="rtl" className="flex flex-wrap items-start gap-[var(--bh-space-5xl-24)]">
56
56
  <InputOTP
57
57
  defaultValue="482159"
58
58
  dir="rtl"
@@ -0,0 +1,46 @@
1
+ import { ChevronRightIcon, FileTextIcon } from "lucide-react"
2
+
3
+ import { Button } from "@/components/ui/button"
4
+ import {
5
+ Item,
6
+ ItemActions,
7
+ ItemContent,
8
+ ItemDescription,
9
+ ItemGroup,
10
+ ItemMedia,
11
+ ItemSeparator,
12
+ ItemTitle,
13
+ } from "@/components/ui/item"
14
+
15
+ export function ItemDemo() {
16
+ return (
17
+ <ItemGroup aria-label="Recent documents">
18
+ <Item role="listitem" variant="outline">
19
+ <ItemMedia>
20
+ <FileTextIcon aria-hidden="true" />
21
+ </ItemMedia>
22
+ <ItemContent>
23
+ <ItemTitle>Launch checklist</ItemTitle>
24
+ <ItemDescription>Updated five minutes ago</ItemDescription>
25
+ </ItemContent>
26
+ <ItemActions>
27
+ <Button aria-label="Open Launch checklist" size="icon" variant="ghost">
28
+ <ChevronRightIcon aria-hidden="true" data-rtl-flip="true" />
29
+ </Button>
30
+ </ItemActions>
31
+ </Item>
32
+ <ItemSeparator />
33
+ <div dir="rtl">
34
+ <Item role="listitem" variant="muted">
35
+ <ItemMedia>
36
+ <FileTextIcon aria-hidden="true" />
37
+ </ItemMedia>
38
+ <ItemContent>
39
+ <ItemTitle>{"\u062e\u0637\u0629 \u0627\u0644\u0625\u0637\u0644\u0627\u0642"}</ItemTitle>
40
+ <ItemDescription>{"\u062a\u0645 \u0627\u0644\u062a\u062d\u062f\u064a\u062b \u0645\u0646\u0630 \u062e\u0645\u0633 \u062f\u0642\u0627\u0626\u0642"}</ItemDescription>
41
+ </ItemContent>
42
+ </Item>
43
+ </div>
44
+ </ItemGroup>
45
+ )
46
+ }