banhaten 0.1.3 → 0.3.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 (275) hide show
  1. package/CHANGELOG.md +73 -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-implementation-ownership-audit.md +244 -0
  12. package/docs/design-system/component-quality-audit-2026-08-20.md +223 -0
  13. package/docs/design-system/component-showcase-consistency-report.md +2 -0
  14. package/docs/design-system/component-token-consistency-audit.md +13 -3
  15. package/docs/design-system/components/README.md +4 -2
  16. package/docs/design-system/components/accordion.md +16 -0
  17. package/docs/design-system/components/activity-feed.md +17 -1
  18. package/docs/design-system/components/activity-heatmap.md +73 -0
  19. package/docs/design-system/components/alert-dialog.md +17 -0
  20. package/docs/design-system/components/alert.md +46 -14
  21. package/docs/design-system/components/aspect-ratio.md +15 -0
  22. package/docs/design-system/components/attribute.md +16 -0
  23. package/docs/design-system/components/autocomplete.md +19 -0
  24. package/docs/design-system/components/avatar.md +18 -0
  25. package/docs/design-system/components/badge.md +19 -0
  26. package/docs/design-system/components/banner.md +19 -1
  27. package/docs/design-system/components/breadcrumbs.md +17 -0
  28. package/docs/design-system/components/button-group.md +35 -0
  29. package/docs/design-system/components/button.md +18 -0
  30. package/docs/design-system/components/card.md +26 -1
  31. package/docs/design-system/components/carousel.md +20 -3
  32. package/docs/design-system/components/catalog-components.md +18 -1
  33. package/docs/design-system/components/chart.md +15 -0
  34. package/docs/design-system/components/checkbox.md +16 -0
  35. package/docs/design-system/components/collapsible.md +15 -0
  36. package/docs/design-system/components/command.md +15 -0
  37. package/docs/design-system/components/context-menu.md +15 -0
  38. package/docs/design-system/components/date-picker.md +21 -1
  39. package/docs/design-system/components/divider.md +16 -0
  40. package/docs/design-system/components/empty-state.md +17 -0
  41. package/docs/design-system/components/field.md +17 -0
  42. package/docs/design-system/components/file-upload.md +18 -0
  43. package/docs/design-system/components/hover-card.md +15 -0
  44. package/docs/design-system/components/input-group.md +17 -0
  45. package/docs/design-system/components/input-otp.md +18 -0
  46. package/docs/design-system/components/input.md +43 -7
  47. package/docs/design-system/components/item.md +72 -0
  48. package/docs/design-system/components/kbd.md +18 -0
  49. package/docs/design-system/components/label.md +16 -0
  50. package/docs/design-system/components/menu.md +17 -0
  51. package/docs/design-system/components/menubar.md +15 -0
  52. package/docs/design-system/components/modal.md +25 -4
  53. package/docs/design-system/components/native-select.md +18 -0
  54. package/docs/design-system/components/navigation-menu.md +15 -0
  55. package/docs/design-system/components/onboarding-step-list-item.md +16 -1
  56. package/docs/design-system/components/page-header.md +17 -1
  57. package/docs/design-system/components/pagination.md +31 -8
  58. package/docs/design-system/components/popover.md +19 -0
  59. package/docs/design-system/components/progress-slider.md +18 -0
  60. package/docs/design-system/components/progress.md +17 -0
  61. package/docs/design-system/components/radio-card.md +16 -0
  62. package/docs/design-system/components/radio-group.md +17 -0
  63. package/docs/design-system/components/resizable.md +15 -0
  64. package/docs/design-system/components/scroll-area.md +20 -1
  65. package/docs/design-system/components/segmented-control.md +71 -0
  66. package/docs/design-system/components/select.md +44 -7
  67. package/docs/design-system/components/sheet.md +17 -0
  68. package/docs/design-system/components/sidebar.md +17 -0
  69. package/docs/design-system/components/skeleton.md +18 -0
  70. package/docs/design-system/components/slideout.md +17 -0
  71. package/docs/design-system/components/slider.md +20 -0
  72. package/docs/design-system/components/social-button.md +21 -3
  73. package/docs/design-system/components/spinner.md +16 -0
  74. package/docs/design-system/components/steps.md +19 -0
  75. package/docs/design-system/components/table.md +36 -4
  76. package/docs/design-system/components/tabs.md +17 -0
  77. package/docs/design-system/components/tag.md +17 -0
  78. package/docs/design-system/components/textarea.md +16 -0
  79. package/docs/design-system/components/timeline.md +17 -0
  80. package/docs/design-system/components/toast.md +17 -0
  81. package/docs/design-system/components/toggle.md +17 -0
  82. package/docs/design-system/components/toolbar.md +21 -1
  83. package/docs/design-system/components/tooltip.md +18 -1
  84. package/docs/design-system/density-and-elevation.md +61 -0
  85. package/docs/design-system/direction-and-localization.md +23 -0
  86. package/docs/design-system/form-recipes.md +73 -0
  87. package/docs/design-system/gap-promotion-policy.md +21 -0
  88. package/docs/design-system/gap-promotion-report.md +100 -0
  89. package/docs/design-system/installation.md +68 -0
  90. package/docs/design-system/launch-comparison-shadcn.md +98 -0
  91. package/docs/design-system/registry-and-cli.md +30 -7
  92. package/docs/design-system/release-policy.md +30 -0
  93. package/docs/design-system/roadmap.md +14 -0
  94. package/docs/design-system/support-matrix.md +23 -0
  95. package/docs/design-system/tabs.md +1 -1
  96. package/docs/design-system/token-governance.md +23 -1
  97. package/package.json +30 -15
  98. package/registry/component-contract.json +40 -0
  99. package/registry/components/alert-dialog.tsx +2 -2
  100. package/registry/components/alert.tsx +101 -76
  101. package/registry/components/autocomplete.tsx +23 -9
  102. package/registry/components/avatar.tsx +14 -10
  103. package/registry/components/badge.tsx +18 -18
  104. package/registry/components/button-group.tsx +324 -5
  105. package/registry/components/button.tsx +38 -17
  106. package/registry/components/card.tsx +87 -62
  107. package/registry/components/carousel.tsx +67 -5
  108. package/registry/components/chart.tsx +36 -3
  109. package/registry/components/checkbox.tsx +3 -3
  110. package/registry/components/collapsible.tsx +1 -1
  111. package/registry/components/command.tsx +38 -4
  112. package/registry/components/context-menu.tsx +1 -1
  113. package/registry/components/date-picker.tsx +312 -135
  114. package/registry/components/expanded/ActivityFeed.tsx +9 -22
  115. package/registry/components/expanded/ActivityHeatmap.tsx +64 -0
  116. package/registry/components/expanded/Banner.tsx +3 -4
  117. package/registry/components/expanded/Breadcrumbs.tsx +8 -5
  118. package/registry/components/expanded/CatalogComponentsShowcase.tsx +16 -17
  119. package/registry/components/expanded/CatalogDivider.tsx +4 -3
  120. package/registry/components/expanded/EmptyState.tsx +1 -1
  121. package/registry/components/expanded/FileUpload.tsx +16 -7
  122. package/registry/components/expanded/OnboardingStepListItem.tsx +2 -6
  123. package/registry/components/expanded/PageHeader.tsx +47 -56
  124. package/registry/components/expanded/Slideout.tsx +29 -424
  125. package/registry/components/expanded/Steps.tsx +151 -13
  126. package/registry/components/expanded/Table.tsx +161 -82
  127. package/registry/components/expanded/Timeline.tsx +14 -27
  128. package/registry/components/expanded/activityFeed.css +9 -9
  129. package/registry/components/expanded/activityHeatmap.css +66 -0
  130. package/registry/components/expanded/banner.css +21 -11
  131. package/registry/components/expanded/breadcrumbs.css +2 -2
  132. package/registry/components/expanded/divider.css +1 -1
  133. package/registry/components/expanded/emptyState.css +1 -1
  134. package/registry/components/expanded/fileUpload.css +7 -7
  135. package/registry/components/expanded/onboardingStepListItem.css +2 -2
  136. package/registry/components/expanded/pageHeader.css +14 -11
  137. package/registry/components/expanded/slideout.css +10 -690
  138. package/registry/components/expanded/steps.css +78 -15
  139. package/registry/components/expanded/table.css +60 -69
  140. package/registry/components/expanded/timeline.css +19 -18
  141. package/registry/components/field.tsx +61 -8
  142. package/registry/components/input-content.ts +1 -0
  143. package/registry/components/input-otp.tsx +13 -3
  144. package/registry/components/input.tsx +68 -43
  145. package/registry/components/item.tsx +189 -0
  146. package/registry/components/kbd.tsx +111 -4
  147. package/registry/components/menu.tsx +87 -251
  148. package/registry/components/menubar.tsx +1 -1
  149. package/registry/components/modal.tsx +143 -103
  150. package/registry/components/native-select.tsx +2 -2
  151. package/registry/components/navigation-menu.tsx +1 -1
  152. package/registry/components/pagination.css +36 -0
  153. package/registry/components/pagination.tsx +88 -64
  154. package/registry/components/popover.tsx +162 -664
  155. package/registry/components/progress-slider.tsx +1 -1
  156. package/registry/components/radio-card.tsx +116 -87
  157. package/registry/components/resizable.tsx +36 -2
  158. package/registry/components/scroll-area.tsx +30 -6
  159. package/registry/components/segmented-control.tsx +87 -0
  160. package/registry/components/select-content.tsx +2 -2
  161. package/registry/components/select.tsx +86 -27
  162. package/registry/components/sheet.tsx +1 -1
  163. package/registry/components/sidebar.tsx +12 -6
  164. package/registry/components/skeleton.css +0 -3
  165. package/registry/components/social-button.tsx +59 -30
  166. package/registry/components/spinner.tsx +18 -55
  167. package/registry/components/table-elements.tsx +128 -0
  168. package/registry/components/tabs.css +1 -1
  169. package/registry/components/tabs.tsx +13 -14
  170. package/registry/components/tag.tsx +3 -3
  171. package/registry/components/textarea.tsx +3 -3
  172. package/registry/components/toast.tsx +16 -11
  173. package/registry/components/toggle.tsx +4 -4
  174. package/registry/components/toolbar.tsx +94 -22
  175. package/registry/components/tooltip.tsx +2 -2
  176. package/registry/examples/alert-demo.tsx +25 -5
  177. package/registry/examples/attribute-demo.tsx +1 -1
  178. package/registry/examples/autocomplete-demo.tsx +3 -3
  179. package/registry/examples/avatar-demo.tsx +14 -11
  180. package/registry/examples/badge-demo.tsx +1 -1
  181. package/registry/examples/button-demo.tsx +6 -6
  182. package/registry/examples/button-group-demo.tsx +23 -2
  183. package/registry/examples/card-demo.tsx +46 -8
  184. package/registry/examples/carousel-demo.tsx +20 -2
  185. package/registry/examples/chart-demo.tsx +1 -1
  186. package/registry/examples/checkbox-demo.tsx +5 -5
  187. package/registry/examples/collection-filter-bar-demo.tsx +135 -0
  188. package/registry/examples/command-demo.tsx +3 -3
  189. package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
  190. package/registry/examples/context-menu-demo.tsx +1 -1
  191. package/registry/examples/control-density-contract-demo.tsx +61 -0
  192. package/registry/examples/date-picker-demo.tsx +12 -12
  193. package/registry/examples/divider-demo.tsx +3 -3
  194. package/registry/examples/expanded/activity-heatmap-demo.tsx +29 -0
  195. package/registry/examples/expanded/banner-demo.tsx +1 -1
  196. package/registry/examples/expanded/breadcrumbs-demo.tsx +4 -4
  197. package/registry/examples/expanded/empty-state-demo.tsx +1 -1
  198. package/registry/examples/expanded/file-upload-demo.tsx +1 -1
  199. package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
  200. package/registry/examples/expanded/slideout-demo.tsx +2 -2
  201. package/registry/examples/expanded/steps-demo.tsx +1 -1
  202. package/registry/examples/expanded/tabs-demo.tsx +1 -1
  203. package/registry/examples/expanded/timeline-demo.tsx +1 -1
  204. package/registry/examples/hover-card-demo.tsx +2 -2
  205. package/registry/examples/input-demo.tsx +6 -6
  206. package/registry/examples/input-otp-demo.tsx +4 -4
  207. package/registry/examples/item-demo.tsx +46 -0
  208. package/registry/examples/kbd-demo.tsx +1 -1
  209. package/registry/examples/label-demo.tsx +1 -1
  210. package/registry/examples/menu-demo.tsx +1 -1
  211. package/registry/examples/modal-demo.tsx +67 -9
  212. package/registry/examples/navigation-menu-demo.tsx +1 -1
  213. package/registry/examples/pagination-demo.tsx +10 -7
  214. package/registry/examples/popover-demo.tsx +19 -19
  215. package/registry/examples/progress-demo.tsx +1 -1
  216. package/registry/examples/progress-slider-demo.tsx +1 -1
  217. package/registry/examples/radio-card-demo.tsx +4 -4
  218. package/registry/examples/radio-group-demo.tsx +2 -2
  219. package/registry/examples/resizable-demo.tsx +1 -1
  220. package/registry/examples/results-toolbar-demo.tsx +44 -0
  221. package/registry/examples/scroll-area-demo.tsx +3 -3
  222. package/registry/examples/segmented-control-demo.tsx +39 -0
  223. package/registry/examples/select-demo.tsx +1 -1
  224. package/registry/examples/sidebar-demo.tsx +5 -3
  225. package/registry/examples/slider-demo.tsx +3 -3
  226. package/registry/examples/social-button-demo.tsx +18 -8
  227. package/registry/examples/spinner-demo.tsx +13 -13
  228. package/registry/examples/tabs-demo.tsx +1 -1
  229. package/registry/examples/tag-demo.tsx +1 -1
  230. package/registry/examples/textarea-demo.tsx +4 -4
  231. package/registry/examples/toast-demo.tsx +1 -1
  232. package/registry/examples/toggle-demo.tsx +6 -6
  233. package/registry/examples/tooltip-demo.tsx +4 -4
  234. package/registry/guidance/USAGE.md +27 -0
  235. package/registry/hooks/use-direction.ts +193 -13
  236. package/registry/index.json +5668 -375
  237. package/registry/styles/globals.css +2404 -3999
  238. package/registry.json +156 -149
  239. package/schema/config.schema.json +11 -8
  240. package/schema/registry.schema.json +150 -45
  241. package/schema/tokens.schema.json +134 -34
  242. package/src/cli/command-line.js +194 -0
  243. package/src/cli/config-editors.js +9 -0
  244. package/src/cli/doctor.js +399 -0
  245. package/src/cli/file-transaction.js +295 -0
  246. package/src/cli/global-css.js +153 -0
  247. package/src/cli/index.js +567 -1613
  248. package/src/cli/install-plan.js +592 -0
  249. package/src/cli/install-receipt.js +171 -0
  250. package/src/cli/jsonc.js +203 -0
  251. package/src/cli/package-install-state.js +254 -0
  252. package/src/cli/package-manager.js +238 -0
  253. package/src/cli/package-plan.js +185 -0
  254. package/src/cli/package-version.js +97 -0
  255. package/src/cli/registry-query.js +207 -0
  256. package/src/cli/reporting.js +55 -0
  257. package/src/cli/schema-validation.js +19 -0
  258. package/src/cli/source-scanner.js +686 -0
  259. package/src/cli/vite-config.js +478 -0
  260. package/tokens/banhaten.tokens.json +4444 -331
  261. package/docs/design-system/components/command-bar.md +0 -57
  262. package/registry/components/expanded/BannerBoard.tsx +0 -225
  263. package/registry/components/expanded/CatalogTag.tsx +0 -85
  264. package/registry/components/expanded/CommandBar.tsx +0 -386
  265. package/registry/components/expanded/IconExplorer.tsx +0 -612
  266. package/registry/components/expanded/TimelineShowcase.tsx +0 -158
  267. package/registry/components/expanded/commandBar.css +0 -470
  268. package/registry/components/expanded/iconExplorer.css +0 -764
  269. package/registry/components/expanded/iconPacks.ts +0 -866
  270. package/registry/components/expanded/tag.css +0 -148
  271. package/registry/examples/expanded/icons-demo.tsx +0 -5
  272. package/tokens/Color mode.zip +0 -0
  273. package/tokens/Numbers.zip +0 -0
  274. package/tokens/Radius.zip +0 -0
  275. package/tokens/Theme.zip +0 -0
@@ -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
+ }
@@ -2,7 +2,7 @@ import { Kbd } from "@/components/ui/kbd"
2
2
 
3
3
  export function KbdDemo() {
4
4
  return (
5
- <div className="flex flex-wrap items-center gap-2">
5
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-md-8)]">
6
6
  <Kbd>⌘</Kbd>
7
7
  <Kbd>K</Kbd>
8
8
  <Kbd size="md">Shift</Kbd>
@@ -3,7 +3,7 @@ import { Label } from "@/components/ui/label"
3
3
 
4
4
  export function LabelDemo() {
5
5
  return (
6
- <div className="grid gap-4">
6
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
7
7
  <div className="flex items-center gap-[var(--bh-space-md-8)]">
8
8
  <Checkbox id="terms" />
9
9
  <Label htmlFor="terms">Accept terms and conditions</Label>
@@ -32,7 +32,7 @@ import {
32
32
 
33
33
  export function MenuDemo() {
34
34
  return (
35
- <div className="flex min-h-[var(--bh-space-16xl-256)] items-start justify-center p-6">
35
+ <div className="flex min-h-[var(--bh-space-16xl-256)] items-start justify-center p-[var(--bh-space-5xl-24)]">
36
36
  <MenuRoot>
37
37
  <MenuTrigger asChild>
38
38
  <Button size="sm" variant="outline">
@@ -1,15 +1,73 @@
1
- import { Modal } from "@/components/ui/modal"
1
+ import * as React from "react"
2
+
3
+ import { Button } from "@/components/ui/button"
4
+ import {
5
+ arabicModalMessages,
6
+ Modal,
7
+ ModalActionButton,
8
+ ModalActions,
9
+ ModalBody,
10
+ ModalCloseButton,
11
+ ModalContent,
12
+ ModalDescription,
13
+ ModalDivider,
14
+ ModalFooter,
15
+ ModalHeader,
16
+ ModalHeaderIcon,
17
+ ModalRoot,
18
+ ModalTitle,
19
+ ModalTrigger,
20
+ } from "@/components/ui/modal"
2
21
 
3
22
  export function ModalDemo() {
23
+ // The Modal shorthand builds the whole structure from props, so it is driven
24
+ // by open state rather than a trigger child.
25
+ const [confirmOpen, setConfirmOpen] = React.useState(false)
26
+
4
27
  return (
5
- <div className="grid gap-6">
6
- <div className="flex flex-wrap items-start gap-6">
7
- <Modal size="sm" />
8
- <Modal size="default" />
9
- </div>
10
- <div className="flex flex-wrap items-start gap-6">
11
- <Modal dir="rtl" size="sm" />
12
- <Modal dir="rtl" size="default" />
28
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
29
+ {/* Compose the primitives when a control in the page opens the modal. */}
30
+ <ModalRoot>
31
+ <ModalTrigger asChild>
32
+ <Button variant="outline">Publish release</Button>
33
+ </ModalTrigger>
34
+ <ModalContent size="default">
35
+ <ModalHeader>
36
+ <ModalHeaderIcon />
37
+ <ModalTitle>Publish this release?</ModalTitle>
38
+ <ModalCloseButton />
39
+ </ModalHeader>
40
+ <ModalBody>
41
+ <ModalDescription>
42
+ Everyone on the team will see the new version immediately. You can
43
+ roll it back from the releases page.
44
+ </ModalDescription>
45
+ </ModalBody>
46
+ <ModalDivider />
47
+ <ModalFooter>
48
+ <ModalActions>
49
+ <ModalActionButton variant="soft">Cancel</ModalActionButton>
50
+ <ModalActionButton>Publish</ModalActionButton>
51
+ </ModalActions>
52
+ </ModalFooter>
53
+ </ModalContent>
54
+ </ModalRoot>
55
+
56
+ {/* `messages` localizes the chrome; `title` and `description` are your
57
+ content, so the caller always supplies them. */}
58
+ <div dir="rtl">
59
+ <Button onClick={() => setConfirmOpen(true)} variant="outline">
60
+ نشر الإصدار
61
+ </Button>
62
+ <Modal
63
+ description="راجع التفاصيل قبل المتابعة. يمكنك التراجع لاحقًا من صفحة الإصدارات."
64
+ dir="rtl"
65
+ messages={arabicModalMessages}
66
+ onOpenChange={setConfirmOpen}
67
+ open={confirmOpen}
68
+ size="default"
69
+ title="هل تريد نشر هذا الإصدار؟"
70
+ />
13
71
  </div>
14
72
  </div>
15
73
  )
@@ -15,7 +15,7 @@ export function NavigationMenuDemo() {
15
15
  <NavigationMenuItem>
16
16
  <NavigationMenuTrigger>Product</NavigationMenuTrigger>
17
17
  <NavigationMenuContent>
18
- <div className="grid gap-2">
18
+ <div className="grid gap-[var(--bh-space-md-8)]">
19
19
  <NavigationMenuLink href="#">Components</NavigationMenuLink>
20
20
  <NavigationMenuLink href="#">Tokens</NavigationMenuLink>
21
21
  <NavigationMenuLink href="#">Patterns</NavigationMenuLink>
@@ -1,16 +1,19 @@
1
- import { Pagination } from "@/components/ui/pagination"
1
+ import {
2
+ arabicPaginationMessages,
3
+ Pagination,
4
+ } from "@/components/ui/pagination"
2
5
 
3
6
  export function PaginationDemo() {
4
7
  return (
5
- <div className="grid gap-6">
6
- <Pagination />
7
- <Pagination variant="ghost" />
8
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
9
+ <Pagination aria-label="Soft numeric pagination" />
10
+ <Pagination aria-label="Ghost numeric pagination" variant="ghost" />
8
11
 
9
- <Pagination type="simple" />
10
- <Pagination type="summary" />
12
+ <Pagination aria-label="Simple pagination" type="simple" />
13
+ <Pagination aria-label="Summary pagination" type="summary" />
11
14
 
12
15
  <div dir="rtl">
13
- <Pagination dir="rtl" />
16
+ <Pagination aria-label="ترقيم الصفحات العربية" dir="rtl" messages={arabicPaginationMessages} />
14
17
  </div>
15
18
  </div>
16
19
  )
@@ -19,7 +19,7 @@ import { Checkbox } from "@/components/ui/checkbox"
19
19
  import { Input } from "@/components/ui/input"
20
20
  import { cn } from "@/lib/utils"
21
21
  import {
22
- Menu,
22
+ MenuPreview,
23
23
  MenuItem,
24
24
  MenuItemIcon,
25
25
  MenuItemText,
@@ -46,8 +46,8 @@ const rtlDescription = "يظهر هذا المحتوى في الاتجاه من
46
46
 
47
47
  export function PopoverDemo() {
48
48
  return (
49
- <div className="grid min-w-0 gap-4">
50
- <div className="grid gap-4 xl:grid-cols-2 2xl:grid-cols-3">
49
+ <div className="grid min-w-0 gap-[var(--bh-space-3xl-16)]">
50
+ <div className="grid gap-[var(--bh-space-3xl-16)] xl:grid-cols-2 2xl:grid-cols-3">
51
51
  <PopoverExample title="Basic Bottom">
52
52
  <Popover defaultOpen>
53
53
  <PopoverTrigger asChild>
@@ -122,7 +122,7 @@ export function PopoverDemo() {
122
122
  </PopoverExample>
123
123
  </div>
124
124
 
125
- <div className="grid gap-4 xl:grid-cols-2 2xl:grid-cols-3">
125
+ <div className="grid gap-[var(--bh-space-3xl-16)] xl:grid-cols-2 2xl:grid-cols-3">
126
126
  <PopoverExample title="Icon Button Trigger">
127
127
  <Popover defaultOpen>
128
128
  <PopoverTrigger asChild>
@@ -199,7 +199,7 @@ export function PopoverDemo() {
199
199
  </PopoverExample>
200
200
  </div>
201
201
 
202
- <div className="grid gap-4 2xl:grid-cols-2">
202
+ <div className="grid gap-[var(--bh-space-3xl-16)] 2xl:grid-cols-2">
203
203
  <PopoverExample density="large" title="Large Content">
204
204
  <Popover defaultOpen>
205
205
  <PopoverTrigger asChild>
@@ -256,7 +256,7 @@ export function PopoverDemo() {
256
256
  </PopoverExample>
257
257
  </div>
258
258
 
259
- <div className="grid gap-4 2xl:grid-cols-2">
259
+ <div className="grid gap-[var(--bh-space-3xl-16)] 2xl:grid-cols-2">
260
260
  <PopoverExample density="matrix" title="Arrow Alignment">
261
261
  <div className="grid min-w-[calc(var(--bh-popover-sm-width)+var(--bh-popover-sm-width)+var(--bh-popover-sm-width)+var(--bh-space-18xl-320))] grid-cols-3 place-items-start gap-[var(--bh-space-6xl-32)]">
262
262
  {(["start", "center", "end"] as const).map((align) => (
@@ -304,7 +304,7 @@ export function PopoverDemo() {
304
304
  </PopoverTrigger>
305
305
  <PopoverContent align="start" dir="rtl" side="right" size="md">
306
306
  <PopoverHeader>
307
- <div className="grid min-w-0 gap-1">
307
+ <div className="grid min-w-0 gap-[var(--bh-space-xs-4)]">
308
308
  <PopoverTitle>{rtlTitle}</PopoverTitle>
309
309
  <PopoverDescription>{rtlDescription}</PopoverDescription>
310
310
  </div>
@@ -337,14 +337,14 @@ function PopoverExample({
337
337
  <div
338
338
  data-popover-example={title}
339
339
  className={cn(
340
- "rounded-md border border-border bg-background p-4",
340
+ "rounded-md border border-border bg-background p-[var(--bh-space-3xl-16)]",
341
341
  popoverExampleWidthClasses[density]
342
342
  )}
343
343
  >
344
344
  <p className="text-xs font-semibold text-muted-foreground">{title}</p>
345
345
  <div
346
346
  className={cn(
347
- "mt-4 flex overflow-visible",
347
+ "mt-[var(--bh-space-3xl-16)] flex overflow-visible",
348
348
  popoverExampleStageHeightClasses[density],
349
349
  popoverExamplePlacementClasses[placement]
350
350
  )}
@@ -391,7 +391,7 @@ function LargeContent() {
391
391
  return (
392
392
  <>
393
393
  <PopoverHeader>
394
- <div className="grid min-w-0 gap-1">
394
+ <div className="grid min-w-0 gap-[var(--bh-space-xs-4)]">
395
395
  <PopoverTitle>Details</PopoverTitle>
396
396
  <PopoverDescription>
397
397
  Larger content can hold explanations, lists, images, and actions.
@@ -400,9 +400,9 @@ function LargeContent() {
400
400
  <PopoverClose />
401
401
  </PopoverHeader>
402
402
  <PopoverBody>
403
- <div className="grid gap-3 rounded-[var(--bh-radius-lg-8)] bg-[var(--bh-bg-neutral-subtle)] p-3">
404
- <div className="h-16 rounded-[var(--bh-radius-md-6)] bg-[var(--bh-bg-raised)]" />
405
- <div className="flex flex-wrap gap-2">
403
+ <div className="grid gap-[var(--bh-space-xl-12)] rounded-[var(--bh-radius-lg-8)] bg-[var(--bh-bg-neutral-subtle)] p-[var(--bh-space-xl-12)]">
404
+ <div className="h-[var(--bh-space-9xl-64)] rounded-[var(--bh-radius-md-6)] bg-[var(--bh-bg-raised)]" />
405
+ <div className="flex flex-wrap gap-[var(--bh-space-md-8)]">
406
406
  <Badge color="green" type="dot">
407
407
  Ready
408
408
  </Badge>
@@ -424,7 +424,7 @@ function FilterContent() {
424
424
  return (
425
425
  <>
426
426
  <PopoverHeader>
427
- <div className="grid min-w-0 gap-1">
427
+ <div className="grid min-w-0 gap-[var(--bh-space-xs-4)]">
428
428
  <PopoverTitle>Status</PopoverTitle>
429
429
  <PopoverDescription>Narrow the table results.</PopoverDescription>
430
430
  </div>
@@ -438,10 +438,10 @@ function FilterContent() {
438
438
  placeholder="Search filters"
439
439
  size="md"
440
440
  />
441
- <div className="grid gap-2">
441
+ <div className="grid gap-[var(--bh-space-md-8)]">
442
442
  {filterOptions.map((option, index) => (
443
443
  <label
444
- className="flex items-center gap-2 text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-default)]"
444
+ className="flex items-center gap-[var(--bh-space-md-8)] text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-default)]"
445
445
  key={option}
446
446
  >
447
447
  <Checkbox defaultChecked={index === 0} />
@@ -472,7 +472,7 @@ function SettingsContent() {
472
472
  return (
473
473
  <>
474
474
  <PopoverHeader>
475
- <div className="grid min-w-0 gap-1">
475
+ <div className="grid min-w-0 gap-[var(--bh-space-xs-4)]">
476
476
  <PopoverTitle>Settings</PopoverTitle>
477
477
  <PopoverDescription>Update notification preferences.</PopoverDescription>
478
478
  </div>
@@ -501,7 +501,7 @@ function SettingsContent() {
501
501
 
502
502
  function ActionsContent() {
503
503
  return (
504
- <Menu
504
+ <MenuPreview
505
505
  aria-label="Popover actions"
506
506
  className="w-[var(--bh-popover-action-width,var(--bh-menu-width))] bg-transparent py-0 shadow-none"
507
507
  width="auto"
@@ -541,6 +541,6 @@ function ActionsContent() {
541
541
  </MenuItemTitle>
542
542
  </MenuItemText>
543
543
  </MenuItem>
544
- </Menu>
544
+ </MenuPreview>
545
545
  )
546
546
  }
@@ -2,7 +2,7 @@ import { Progress } from "@/components/ui/progress"
2
2
 
3
3
  export function ProgressDemo() {
4
4
  return (
5
- <div className="grid w-full max-w-md gap-6">
5
+ <div className="grid w-full max-w-md gap-[var(--bh-space-5xl-24)]">
6
6
  <Progress
7
7
  aria-label="Upload progress"
8
8
  helperText="Preparing the final file"
@@ -2,7 +2,7 @@ import { ProgressSlider } from "@/components/ui/progress-slider"
2
2
 
3
3
  export function ProgressSliderDemo() {
4
4
  return (
5
- <div className="grid gap-6">
5
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
6
6
  <ProgressSlider
7
7
  aria-label="Investment amount"
8
8
  defaultValue={28}
@@ -17,21 +17,21 @@ const radioCardRtlDemoProps = {
17
17
 
18
18
  export function RadioCardDemo() {
19
19
  return (
20
- <div className="grid gap-6">
21
- <div className="flex flex-wrap items-start gap-4">
20
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
21
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-3xl-16)]">
22
22
  <RadioCard {...radioCardDemoProps} type="with-icon" />
23
23
  <RadioCard {...radioCardDemoProps} type="icon-radio-right" />
24
24
  <RadioCard {...radioCardDemoProps} type="icon-radio-left" />
25
25
  <RadioCard {...radioCardDemoProps} type="radio-label" />
26
26
  </div>
27
27
 
28
- <div className="flex flex-wrap items-start gap-4">
28
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-3xl-16)]">
29
29
  <RadioCard {...radioCardDemoProps} checked type="with-avatar" />
30
30
  <RadioCard {...radioCardDemoProps} checked type="payment" />
31
31
  <RadioCard {...radioCardDemoProps} checked type="company-icon" />
32
32
  </div>
33
33
 
34
- <div className="flex flex-wrap items-start gap-4" dir="rtl">
34
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-3xl-16)]" dir="rtl">
35
35
  <RadioCard {...radioCardRtlDemoProps} direction="rtl" type="with-icon" />
36
36
  <RadioCard
37
37
  {...radioCardRtlDemoProps}
@@ -6,7 +6,7 @@ import {
6
6
 
7
7
  export function RadioGroupDemo() {
8
8
  return (
9
- <div className="grid gap-6">
9
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
10
10
  <RadioGroup
11
11
  defaultValue="monthly"
12
12
  description="Choose the cadence for generated invoices."
@@ -42,7 +42,7 @@ export function RadioGroupDemo() {
42
42
  <RadioGroupItem value="wallet" label="Wallet" />
43
43
  </RadioGroup>
44
44
 
45
- <div className="grid gap-3">
45
+ <div className="grid gap-[var(--bh-space-xl-12)]">
46
46
  <RadioField
47
47
  defaultChecked
48
48
  label="Use as default"
@@ -8,7 +8,7 @@ export function ResizableDemo() {
8
8
  return (
9
9
  <ResizablePanelGroup
10
10
  direction="horizontal"
11
- className="h-48 rounded-xl border border-[var(--bh-border-subtle)]"
11
+ className="h-[var(--bh-space-14xl-192)] rounded-xl border border-[var(--bh-border-subtle)]"
12
12
  >
13
13
  <ResizablePanel defaultSize={35}>
14
14
  <div className="flex size-full items-center justify-center text-sm">Sidebar</div>
@@ -0,0 +1,44 @@
1
+ import {
2
+ SegmentedControl,
3
+ SegmentedControlItem,
4
+ SegmentedControlLabel,
5
+ } from "@/components/ui/segmented-control"
6
+ import {
7
+ Toolbar,
8
+ ToolbarButton,
9
+ ToolbarSection,
10
+ ToolbarText,
11
+ } from "@/components/ui/toolbar"
12
+
13
+ export function ResultsToolbarDemo() {
14
+ return (
15
+ <Toolbar
16
+ aria-label="Bookmark results"
17
+ data-recipe="results-toolbar"
18
+ layout="split"
19
+ wrap
20
+ >
21
+ <ToolbarText density="default">
22
+ <strong>5,371</strong>&nbsp;bookmarks · keep scrolling to browse all
23
+ </ToolbarText>
24
+
25
+ <ToolbarSection align="end" wrap>
26
+ <SegmentedControl
27
+ aria-label="Cards per row"
28
+ defaultValue="4"
29
+ density="default"
30
+ >
31
+ <SegmentedControlLabel>Cards / row</SegmentedControlLabel>
32
+ {[3, 4, 5, 6].map((count) => (
33
+ <SegmentedControlItem key={count} value={String(count)}>
34
+ {count}
35
+ </SegmentedControlItem>
36
+ ))}
37
+ </SegmentedControl>
38
+ <ToolbarButton density="default" variant="outline">
39
+ Select
40
+ </ToolbarButton>
41
+ </ToolbarSection>
42
+ </Toolbar>
43
+ )
44
+ }
@@ -2,10 +2,10 @@ import { ScrollArea } from "@/components/ui/scroll-area"
2
2
 
3
3
  export function ScrollAreaDemo() {
4
4
  return (
5
- <ScrollArea className="h-48 w-72 rounded-xl border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)]">
6
- <div className="grid gap-2 p-4">
5
+ <ScrollArea className="h-[var(--bh-space-14xl-192)] w-[var(--bh-space-17xl-288)] rounded-xl border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)]">
6
+ <div className="grid gap-[var(--bh-space-md-8)] p-[var(--bh-space-3xl-16)]">
7
7
  {Array.from({ length: 12 }, (_, index) => (
8
- <div key={index} className="rounded-lg bg-[var(--bh-bg-neutral-subtle)] px-3 py-2 text-sm">
8
+ <div key={index} className="rounded-lg bg-[var(--bh-bg-neutral-subtle)] px-[var(--bh-space-xl-12)] py-[var(--bh-space-md-8)] text-sm">
9
9
  Activity item {index + 1}
10
10
  </div>
11
11
  ))}
@@ -0,0 +1,39 @@
1
+ import {
2
+ SegmentedControl,
3
+ SegmentedControlItem,
4
+ SegmentedControlLabel,
5
+ } from "@/components/ui/segmented-control"
6
+
7
+ export function SegmentedControlDemo() {
8
+ return (
9
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
10
+ <SegmentedControl
11
+ aria-label="Cards per row"
12
+ defaultValue="4"
13
+ density="default"
14
+ >
15
+ <SegmentedControlLabel>Cards / row</SegmentedControlLabel>
16
+ {[3, 4, 5, 6].map((count) => (
17
+ <SegmentedControlItem key={count} value={String(count)}>
18
+ {count}
19
+ </SegmentedControlItem>
20
+ ))}
21
+ </SegmentedControl>
22
+
23
+ <div dir="rtl">
24
+ <SegmentedControl
25
+ aria-label="عدد البطاقات في الصف"
26
+ defaultValue="4"
27
+ density="compact"
28
+ >
29
+ <SegmentedControlLabel>بطاقات / صف</SegmentedControlLabel>
30
+ {[3, 4, 5, 6].map((count) => (
31
+ <SegmentedControlItem key={count} value={String(count)}>
32
+ {count}
33
+ </SegmentedControlItem>
34
+ ))}
35
+ </SegmentedControl>
36
+ </div>
37
+ </div>
38
+ )
39
+ }
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  export function SelectDemo() {
9
9
  return (
10
- <div className="grid gap-8">
10
+ <div className="grid gap-[var(--bh-space-6xl-32)]">
11
11
  <Select
12
12
  helperText="This is a hint text"
13
13
  label="Label"
@@ -17,7 +17,7 @@ import {
17
17
 
18
18
  export function SidebarDemo() {
19
19
  return (
20
- <SidebarProvider className="flex h-80" defaultCollapsed={false}>
20
+ <SidebarProvider className="flex h-[var(--bh-space-18xl-320)]" defaultCollapsed={false}>
21
21
  <Sidebar>
22
22
  <SidebarHeader>
23
23
  <div className="min-w-0 flex-1 text-sm font-semibold group-data-[collapsed=true]/sidebar:hidden">
@@ -47,8 +47,10 @@ export function SidebarDemo() {
47
47
  <SidebarMenuButton icon={<SettingsIcon />}>Admin</SidebarMenuButton>
48
48
  </SidebarFooter>
49
49
  </Sidebar>
50
- <SidebarInset className="grid place-items-center bg-[var(--bh-bg-subtle)] p-[var(--bh-space-4xl-20)] text-sm text-[var(--bh-content-subtle)]">
51
- App content
50
+ <SidebarInset asChild>
51
+ <div className="grid min-w-0 flex-1 place-items-center bg-[var(--bh-bg-subtle)] p-[var(--bh-space-4xl-20)] text-sm text-[var(--bh-content-subtle)]">
52
+ App content
53
+ </div>
52
54
  </SidebarInset>
53
55
  </SidebarProvider>
54
56
  )
@@ -2,7 +2,7 @@ import { Slider } from "@/components/ui/slider"
2
2
 
3
3
  export function SliderDemo() {
4
4
  return (
5
- <div className="grid gap-8">
5
+ <div className="grid gap-[var(--bh-space-6xl-32)]">
6
6
  <Slider
7
7
  aria-label="Budget amount"
8
8
  defaultValue={[40]}
@@ -17,10 +17,10 @@ export function SliderDemo() {
17
17
  minStepsBetweenThumbs={4}
18
18
  />
19
19
 
20
- <div className="flex h-44 items-center">
20
+ <div className="flex h-[calc(var(--bh-space-13xl-160)_+_var(--bh-space-3xl-16))] items-center">
21
21
  <Slider
22
22
  aria-label="Risk tolerance"
23
- className="h-40"
23
+ className="h-[var(--bh-space-13xl-160)]"
24
24
  defaultValue={[60]}
25
25
  orientation="vertical"
26
26
  tone="warning"