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
@@ -9,6 +9,12 @@ import {
9
9
  } from "lucide-react"
10
10
 
11
11
  import { cn } from "@/lib/utils"
12
+ import {
13
+ KbdShortcut,
14
+ type ShortcutPlatform,
15
+ } from "@/components/ui/kbd"
16
+
17
+ type ControlDensity = "compact" | "default" | "comfortable"
12
18
 
13
19
  const toolbarVariants = cva(
14
20
  "flex w-full max-w-full min-w-0 gap-[var(--bh-space-3xl-16)] text-[var(--bh-content-default)]",
@@ -65,37 +71,44 @@ const toolbarSectionVariants = cva(
65
71
  )
66
72
 
67
73
  const toolbarButtonVariants = cva(
68
- "group/toolbar-button inline-flex min-w-0 items-center justify-center whitespace-nowrap rounded-[var(--bh-control-default)] text-[length:var(--bh-text-button-font-size)] font-[var(--bh-text-button-font-weight)] leading-[var(--bh-text-button-line-height)] tracking-[var(--bh-text-button-letter-spacing)] outline-none transition-[background-color,border-color,color,box-shadow] focus-visible:shadow-[var(--shadow-button-focus)] disabled:pointer-events-none disabled:shadow-none aria-invalid:border aria-invalid:border-destructive aria-invalid:shadow-[var(--shadow-button-danger-focus)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-[var(--bh-button-icon-size)] [&_svg[data-icon='inline-start']]:ms-[var(--bh-button-icon-offset)] [&_svg[data-icon='inline-end']]:me-[var(--bh-button-icon-offset)] rtl:[&_svg[data-rtl-flip='true']]:-scale-x-100",
74
+ "group/toolbar-button inline-flex min-w-0 items-center justify-center whitespace-nowrap rounded-[var(--bh-control-default)] text-[length:var(--bh-text-button-font-size)] font-[var(--bh-text-button-font-weight)] leading-[var(--bh-text-button-line-height)] tracking-[var(--bh-text-button-letter-spacing)] outline-none transition-[background-color,border-color,color,box-shadow] focus-visible:shadow-[var(--shadow-button-focus)] disabled:pointer-events-none disabled:shadow-none aria-invalid:border-[length:var(--bh-border-width-default)] aria-invalid:border-[var(--bh-border-danger-strong)] aria-invalid:shadow-[var(--shadow-button-danger-focus)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-[var(--bh-button-icon-size)] [&_svg[data-icon='inline-start']]:ms-[var(--bh-button-icon-offset)] [&_svg[data-icon='inline-end']]:me-[var(--bh-button-icon-offset)] rtl:[&_svg[data-rtl-flip='true']]:-scale-x-100",
69
75
  {
70
76
  variants: {
71
77
  variant: {
72
78
  default:
73
- "bg-primary text-primary-foreground shadow-[var(--shadow-button-raised)] hover:bg-[var(--primary-hover)] active:bg-[var(--primary-pressed)] disabled:bg-[var(--bh-interactive-brand-disabled)] disabled:text-[var(--bh-content-disabled)]",
74
- soft: "border border-transparent bg-[var(--soft)] text-foreground shadow-[var(--shadow-button-soft)] hover:bg-[var(--soft-hover)] active:bg-[var(--soft-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-soft-disabled)] disabled:text-[var(--bh-content-disabled)]",
79
+ "bg-[var(--bh-interactive-brand-default)] text-[var(--bh-content-on-brand)] shadow-[var(--shadow-button-raised)] hover:bg-[var(--bh-interactive-brand-hover)] active:bg-[var(--bh-interactive-brand-pressed)] disabled:bg-[var(--bh-interactive-brand-disabled)] disabled:text-[var(--bh-content-disabled)]",
80
+ soft: "border-[length:var(--bh-border-width-default)] border-transparent bg-[var(--bh-interactive-soft-default)] text-[var(--bh-content-default)] shadow-[var(--shadow-button-soft)] hover:bg-[var(--bh-interactive-soft-hover)] active:bg-[var(--bh-interactive-soft-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-soft-disabled)] disabled:text-[var(--bh-content-disabled)]",
75
81
  outline:
76
- "border border-[var(--bh-border-default)] bg-[var(--outline)] text-foreground hover:bg-[var(--outline-hover)] active:bg-[var(--outline-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:border-[var(--bh-border-disabled)] disabled:bg-[var(--bh-interactive-outlined-disabled)] disabled:text-[var(--bh-content-disabled)]",
82
+ "border-[length:var(--bh-border-width-default)] border-[var(--bh-border-default)] bg-[var(--bh-interactive-outlined-default)] text-[var(--bh-content-default)] hover:bg-[var(--bh-interactive-outlined-hover)] active:bg-[var(--bh-interactive-outlined-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:border-[var(--bh-border-disabled)] disabled:bg-[var(--bh-interactive-outlined-disabled)] disabled:text-[var(--bh-content-disabled)]",
77
83
  ghost:
78
- "border border-transparent bg-[var(--ghost)] text-foreground hover:bg-[var(--ghost-hover)] active:bg-[var(--ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
79
- link: "border border-transparent bg-[var(--ghost)] text-[var(--bh-content-brand-default)] hover:bg-[var(--ghost-hover)] active:bg-[var(--ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
84
+ "border-[length:var(--bh-border-width-default)] border-transparent bg-[var(--bh-interactive-ghost-default)] text-[var(--bh-content-default)] hover:bg-[var(--bh-interactive-ghost-hover)] active:bg-[var(--bh-interactive-ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
85
+ link: "border-[length:var(--bh-border-width-default)] border-transparent bg-[var(--bh-interactive-ghost-default)] text-[var(--bh-content-brand-default)] hover:bg-[var(--bh-interactive-ghost-hover)] active:bg-[var(--bh-interactive-ghost-pressed)] focus-visible:border-[var(--bh-border-brand-strong)] disabled:bg-[var(--bh-interactive-ghost-disabled)] disabled:text-[var(--bh-content-disabled)]",
80
86
  },
81
87
  size: {
88
+ xs: "h-[var(--bh-button-xs-height)] gap-[var(--bh-button-gap-xs)] px-[var(--bh-button-xs-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-xs-padding-x)]",
82
89
  sm: "h-[var(--bh-button-sm-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-sm-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-sm-padding-x)]",
83
90
  default: "h-[var(--bh-button-md-height)] gap-[var(--bh-button-gap)] px-[var(--bh-button-md-padding-x)] py-[var(--bh-button-sm-padding-y)] has-[>svg]:px-[var(--bh-button-md-padding-x)]",
91
+ "icon-xs": "size-[var(--bh-button-xs-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
84
92
  "icon-sm": "size-[var(--bh-button-sm-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
85
93
  icon: "size-[var(--bh-button-md-height)] gap-[var(--bh-space-none)] p-[var(--bh-space-none)]",
86
94
  },
87
95
  },
88
96
  defaultVariants: {
89
97
  variant: "soft",
90
- size: "default",
98
+ size: "sm",
91
99
  },
92
100
  }
93
101
  )
94
102
 
95
103
  const toolbarSearchVariants = cva(
96
- "flex h-[var(--bh-input-lg-height)] max-w-full min-w-0 items-center gap-[var(--bh-input-content-gap)] rounded-[var(--bh-input-radius)] bg-[var(--bh-interactive-input-default)] px-[var(--bh-input-lg-padding-x)] text-[var(--bh-content-default)] shadow-[var(--shadow-input)] transition-[background-color,box-shadow] focus-within:shadow-[var(--shadow-input-focus-ring)] data-[disabled=true]:pointer-events-none data-[disabled=true]:bg-[var(--bh-interactive-input-disabled)] data-[disabled=true]:text-[var(--bh-content-disabled)]",
104
+ "flex max-w-full min-w-0 items-center gap-[var(--bh-input-content-gap)] rounded-[var(--bh-input-radius)] bg-[var(--bh-interactive-input-default)] text-[var(--bh-content-default)] shadow-[var(--shadow-input)] transition-[background-color,box-shadow] focus-within:shadow-[var(--shadow-input-focus-ring)] data-[disabled=true]:pointer-events-none data-[disabled=true]:bg-[var(--bh-interactive-input-disabled)] data-[disabled=true]:text-[var(--bh-content-disabled)]",
97
105
  {
98
106
  variants: {
107
+ density: {
108
+ compact: "h-[var(--bh-input-md-height)] px-[var(--bh-input-md-padding-x)]",
109
+ default: "h-[var(--bh-input-lg-height)] px-[var(--bh-input-lg-padding-x)]",
110
+ comfortable: "h-[var(--bh-input-comfortable-height)] px-[var(--bh-input-comfortable-padding-x)]",
111
+ },
99
112
  width: {
100
113
  compact: "w-[calc(var(--bh-input-width)/2)]",
101
114
  default: "w-[var(--bh-input-width)]",
@@ -104,15 +117,21 @@ const toolbarSearchVariants = cva(
104
117
  },
105
118
  },
106
119
  defaultVariants: {
120
+ density: "default",
107
121
  width: "default",
108
122
  },
109
123
  }
110
124
  )
111
125
 
112
126
  const toolbarSelectVariants = cva(
113
- "inline-flex h-[var(--bh-input-lg-height)] max-w-full min-w-0 items-center justify-between gap-[var(--bh-space-md-8)] rounded-[var(--bh-input-radius)] bg-[var(--bh-interactive-input-default)] px-[var(--bh-select-trigger-padding-x)] text-start text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-default)] shadow-[var(--shadow-select-trigger)] outline-none transition-[background-color,box-shadow] hover:bg-[var(--bh-interactive-input-hover)] focus-visible:shadow-[var(--shadow-input-focus-ring)] disabled:pointer-events-none disabled:bg-[var(--bh-interactive-input-disabled)] disabled:text-[var(--bh-content-disabled)]",
127
+ "inline-flex max-w-full min-w-0 items-center justify-between gap-[var(--bh-space-md-8)] rounded-[var(--bh-input-radius)] bg-[var(--bh-interactive-input-default)] px-[var(--bh-select-trigger-padding-x)] text-start text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-default)] shadow-[var(--shadow-select-trigger)] outline-none transition-[background-color,box-shadow] hover:bg-[var(--bh-bg-default-hover)] focus-visible:shadow-[var(--shadow-input-focus-ring)] disabled:pointer-events-none disabled:bg-[var(--bh-interactive-input-disabled)] disabled:text-[var(--bh-content-disabled)]",
114
128
  {
115
129
  variants: {
130
+ density: {
131
+ compact: "h-[var(--bh-input-md-height)]",
132
+ default: "h-[var(--bh-input-lg-height)]",
133
+ comfortable: "h-[var(--bh-input-comfortable-height)]",
134
+ },
116
135
  width: {
117
136
  compact: "w-[calc(var(--bh-select-width)/2)]",
118
137
  default: "w-[var(--bh-select-width)]",
@@ -121,6 +140,7 @@ const toolbarSelectVariants = cva(
121
140
  },
122
141
  },
123
142
  defaultVariants: {
143
+ density: "default",
124
144
  width: "compact",
125
145
  },
126
146
  }
@@ -201,20 +221,39 @@ const ToolbarSpacer = React.forwardRef<HTMLDivElement, ToolbarSpacerProps>(
201
221
  type ToolbarButtonProps = React.ComponentProps<"button"> &
202
222
  VariantProps<typeof toolbarButtonVariants> & {
203
223
  asChild?: boolean
224
+ density?: ControlDensity
204
225
  }
205
226
 
227
+ type ToolbarButtonSize = NonNullable<
228
+ VariantProps<typeof toolbarButtonVariants>["size"]
229
+ >
230
+
206
231
  const ToolbarButton = React.forwardRef<HTMLButtonElement, ToolbarButtonProps>(
207
232
  function ToolbarButton(
208
- { className, variant, size, asChild = false, children, type = "button", ...props },
233
+ {
234
+ asChild = false,
235
+ children,
236
+ className,
237
+ density,
238
+ size,
239
+ type = "button",
240
+ variant,
241
+ ...props
242
+ },
209
243
  ref
210
244
  ) {
211
245
  const Comp = asChild ? Slot : "button"
246
+ const resolvedSize = resolveToolbarButtonSize(density, size)
212
247
 
213
248
  return (
214
249
  <Comp
250
+ data-density={density}
251
+ data-size={resolvedSize}
215
252
  data-slot="toolbar-button"
216
253
  ref={ref}
217
- className={cn(toolbarButtonVariants({ variant, size, className }))}
254
+ className={cn(
255
+ toolbarButtonVariants({ variant, size: resolvedSize, className })
256
+ )}
218
257
  {...(!asChild ? { type } : {})}
219
258
  {...props}
220
259
  >
@@ -271,7 +310,7 @@ const ToolbarMoreButton = React.forwardRef<
271
310
  HTMLButtonElement,
272
311
  ToolbarMoreButtonProps
273
312
  >(function ToolbarMoreButton(
274
- { label = "More actions", size = "icon", ...props },
313
+ { label = "More actions", size = "icon-sm", ...props },
275
314
  ref
276
315
  ) {
277
316
  return (
@@ -289,6 +328,8 @@ type ToolbarSearchProps = Omit<
289
328
  className?: string
290
329
  inputClassName?: string
291
330
  icon?: React.ReactNode
331
+ shortcutKeys?: readonly string[]
332
+ shortcutPlatform?: ShortcutPlatform
292
333
  }
293
334
 
294
335
  const ToolbarSearch = React.forwardRef<HTMLInputElement, ToolbarSearchProps>(
@@ -299,7 +340,10 @@ const ToolbarSearch = React.forwardRef<HTMLInputElement, ToolbarSearchProps>(
299
340
  icon,
300
341
  inputClassName,
301
342
  placeholder = "Search...",
343
+ shortcutKeys,
344
+ shortcutPlatform,
302
345
  type = "search",
346
+ density,
303
347
  width,
304
348
  ...props
305
349
  },
@@ -308,8 +352,9 @@ const ToolbarSearch = React.forwardRef<HTMLInputElement, ToolbarSearchProps>(
308
352
  return (
309
353
  <div
310
354
  data-disabled={disabled ? "true" : undefined}
355
+ data-density={density ?? "default"}
311
356
  data-slot="toolbar-search"
312
- className={cn(toolbarSearchVariants({ width, className }))}
357
+ className={cn(toolbarSearchVariants({ density, width, className }))}
313
358
  >
314
359
  <span
315
360
  aria-hidden="true"
@@ -329,6 +374,13 @@ const ToolbarSearch = React.forwardRef<HTMLInputElement, ToolbarSearchProps>(
329
374
  type={type}
330
375
  {...props}
331
376
  />
377
+ {shortcutKeys?.length ? (
378
+ <KbdShortcut
379
+ disabled={disabled}
380
+ keys={shortcutKeys}
381
+ platform={shortcutPlatform}
382
+ />
383
+ ) : null}
332
384
  </div>
333
385
  )
334
386
  }
@@ -349,6 +401,7 @@ const ToolbarSelect = React.forwardRef<HTMLButtonElement, ToolbarSelectProps>(
349
401
  placeholder = "Select",
350
402
  type = "button",
351
403
  value,
404
+ density,
352
405
  width,
353
406
  ...props
354
407
  },
@@ -357,10 +410,11 @@ const ToolbarSelect = React.forwardRef<HTMLButtonElement, ToolbarSelectProps>(
357
410
  return (
358
411
  <button
359
412
  aria-haspopup="listbox"
413
+ data-density={density ?? "default"}
360
414
  data-slot="toolbar-select"
361
415
  ref={ref}
362
416
  type={type}
363
- className={cn(toolbarSelectVariants({ width, className }))}
417
+ className={cn(toolbarSelectVariants({ density, width, className }))}
364
418
  {...props}
365
419
  >
366
420
  <span
@@ -415,16 +469,22 @@ const ToolbarBadge = React.forwardRef<HTMLSpanElement, ToolbarBadgeProps>(
415
469
  }
416
470
  )
417
471
 
418
- type ToolbarTextProps = React.ComponentProps<"span">
472
+ type ToolbarTextProps = React.ComponentProps<"span"> & {
473
+ density?: ControlDensity
474
+ }
419
475
 
420
476
  const ToolbarText = React.forwardRef<HTMLSpanElement, ToolbarTextProps>(
421
- function ToolbarText({ className, ...props }, ref) {
477
+ function ToolbarText({ className, density = "default", ...props }, ref) {
422
478
  return (
423
479
  <span
424
480
  data-slot="toolbar-text"
481
+ data-density={density}
425
482
  ref={ref}
426
483
  className={cn(
427
- "inline-flex h-[var(--bh-input-lg-height)] min-w-0 items-center text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-subtle)]",
484
+ "inline-flex min-w-0 items-center text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)] text-[var(--bh-content-subtle)]",
485
+ density === "compact" && "h-[var(--bh-input-md-height)]",
486
+ density === "default" && "h-[var(--bh-input-lg-height)]",
487
+ density === "comfortable" && "h-[var(--bh-input-comfortable-height)]",
428
488
  className
429
489
  )}
430
490
  {...props}
@@ -433,6 +493,17 @@ const ToolbarText = React.forwardRef<HTMLSpanElement, ToolbarTextProps>(
433
493
  }
434
494
  )
435
495
 
496
+ function resolveToolbarButtonSize(
497
+ density: ControlDensity | undefined,
498
+ size: ToolbarButtonSize | null | undefined
499
+ ): ToolbarButtonSize | null | undefined {
500
+ if (!density) return size
501
+ const iconOnly = size?.startsWith("icon") ?? false
502
+ if (density === "compact") return iconOnly ? "icon-xs" : "xs"
503
+ if (density === "default") return iconOnly ? "icon-sm" : "sm"
504
+ return iconOnly ? "icon" : "default"
505
+ }
506
+
436
507
  export {
437
508
  Toolbar,
438
509
  ToolbarBadge,
@@ -453,6 +524,7 @@ export {
453
524
  toolbarVariants,
454
525
  }
455
526
  export type {
527
+ ControlDensity,
456
528
  ToolbarBadgeProps,
457
529
  ToolbarButtonProps,
458
530
  ToolbarFilterButtonProps,
@@ -280,7 +280,7 @@ function TooltipCloseButton({
280
280
  <XIcon
281
281
  aria-hidden="true"
282
282
  className="size-[var(--bh-tooltip-close-icon-size)]"
283
- strokeWidth={2}
283
+ strokeWidth="var(--bh-icon-stroke-200)"
284
284
  />
285
285
  </button>
286
286
  )
@@ -2,13 +2,33 @@ import { Alert } from "@/components/ui/alert"
2
2
 
3
3
  export function AlertDemo() {
4
4
  return (
5
- <div className="grid gap-4">
6
- <Alert status="danger" />
7
- <Alert status="success" />
8
- <Alert isExpandable status="warning" />
5
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
6
+ <Alert status="danger" title="Payment failed" />
7
+ <Alert status="success" title="Changes saved" />
8
+ <Alert
9
+ actions={[
10
+ { label: "Review details", onClick: noop },
11
+ { label: "Dismiss", onClick: noop },
12
+ ]}
13
+ description="Update the payment method before the next billing attempt."
14
+ isExpandable
15
+ status="warning"
16
+ title="Payment method expires soon"
17
+ />
9
18
  <div dir="rtl">
10
- <Alert dir="rtl" isExpandable status="info" />
19
+ <Alert
20
+ actions={[
21
+ { label: "عرض التفاصيل", onClick: noop },
22
+ { label: "متابعة", onClick: noop },
23
+ ]}
24
+ description="يمكنك مراجعة التفاصيل أو المتابعة من لوحة التحكم."
25
+ isExpandable
26
+ status="info"
27
+ title="تم تحديث حسابك"
28
+ />
11
29
  </div>
12
30
  </div>
13
31
  )
14
32
  }
33
+
34
+ function noop() {}
@@ -11,7 +11,7 @@ import { Button } from "@/components/ui/button"
11
11
 
12
12
  export function AttributeDemo() {
13
13
  return (
14
- <div className="grid max-w-5xl gap-4 lg:grid-cols-2">
14
+ <div className="grid max-w-5xl gap-[var(--bh-space-3xl-16)] lg:grid-cols-2">
15
15
  <AttributeCard>
16
16
  <AttributeHeader
17
17
  title="Company profile"
@@ -61,8 +61,8 @@ const rtlOptions = [
61
61
 
62
62
  export function AutocompleteDemo() {
63
63
  return (
64
- <div className="grid w-full gap-5 lg:grid-cols-2">
65
- <div className="grid min-w-0 content-start gap-5">
64
+ <div className="grid w-full gap-[var(--bh-space-4xl-20)] lg:grid-cols-2">
65
+ <div className="grid min-w-0 content-start gap-[var(--bh-space-4xl-20)]">
66
66
  <Autocomplete
67
67
  className="mb-[var(--bh-space-13xl-160)]"
68
68
  defaultOpen
@@ -83,7 +83,7 @@ export function AutocompleteDemo() {
83
83
  />
84
84
  </div>
85
85
 
86
- <div className="grid min-w-0 content-start gap-5">
86
+ <div className="grid min-w-0 content-start gap-[var(--bh-space-4xl-20)]">
87
87
  <Autocomplete
88
88
  label="Project"
89
89
  options={projectOptions}
@@ -30,8 +30,8 @@ const secondaryStatusColumns = [
30
30
 
31
31
  export function AvatarDemo() {
32
32
  return (
33
- <div className="flex flex-col gap-7">
34
- <div className="grid w-fit grid-cols-5 gap-x-4 gap-y-4">
33
+ <div className="flex flex-col gap-[calc(var(--bh-space-5xl-24)_+_var(--bh-space-xs-4))]">
34
+ <div className="grid w-fit grid-cols-5 gap-x-[var(--bh-space-3xl-16)] gap-y-[var(--bh-space-3xl-16)]">
35
35
  {statusColumns.map((status, index) => (
36
36
  <Avatar key={`icon-${status}-${index}`} size="2xl">
37
37
  <AvatarIcon />
@@ -56,7 +56,7 @@ export function AvatarDemo() {
56
56
  ))}
57
57
  </div>
58
58
 
59
- <div className="flex flex-wrap items-center gap-5 ps-7">
59
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-4xl-20)] ps-[calc(var(--bh-space-5xl-24)_+_var(--bh-space-xs-4))]">
60
60
  <Avatar size="2xl">
61
61
  <AvatarImage src={avatarUrl} alt="Profile portrait" />
62
62
  <AvatarFallback>AG</AvatarFallback>
@@ -74,7 +74,7 @@ export function AvatarDemo() {
74
74
  </Avatar>
75
75
  </div>
76
76
 
77
- <div className="flex items-center gap-3">
77
+ <div className="flex items-center gap-[var(--bh-space-xl-12)]">
78
78
  <AvatarGroup>
79
79
  {Array.from({ length: 7 }).map((_, index) => (
80
80
  <Avatar key={index} size="md">
@@ -89,11 +89,11 @@ export function AvatarDemo() {
89
89
  className="border border-dashed border-[var(--bh-border-subtle)] bg-[var(--bh-bg-default)] text-[var(--bh-content-subtle)]"
90
90
  size="md"
91
91
  >
92
- <PlusIcon aria-hidden="true" className="size-4" />
92
+ <PlusIcon aria-hidden="true" className="size-[var(--bh-space-3xl-16)]" />
93
93
  </Avatar>
94
94
  </div>
95
95
 
96
- <div className="flex items-center gap-3">
96
+ <div className="flex items-center gap-[var(--bh-space-xl-12)]">
97
97
  <Avatar size="xl">
98
98
  <AvatarImage src={avatarUrl} alt="John Doe" />
99
99
  <AvatarFallback>JD</AvatarFallback>
@@ -109,7 +109,7 @@ export function AvatarDemo() {
109
109
  </div>
110
110
  </div>
111
111
 
112
- <div className="flex items-center gap-3">
112
+ <div className="flex items-center gap-[var(--bh-space-xl-12)]">
113
113
  <Avatar size="md">
114
114
  <AvatarImage src={avatarUrl} alt="John Doe" />
115
115
  <AvatarFallback>JD</AvatarFallback>
@@ -10,7 +10,7 @@ import { Spinner } from "@/components/ui/spinner"
10
10
 
11
11
  export function BadgeDemo() {
12
12
  return (
13
- <div className="flex flex-wrap items-center gap-2">
13
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-md-8)]">
14
14
  <Badge>Badge</Badge>
15
15
  <Badge badgeStyle="outline">Outline</Badge>
16
16
  <Badge badgeStyle="solid" color="blue">
@@ -5,8 +5,8 @@ import { Spinner } from "@/components/ui/spinner"
5
5
 
6
6
  export function ButtonDemo() {
7
7
  return (
8
- <div className="flex flex-col gap-6">
9
- <div className="flex flex-wrap items-center gap-3">
8
+ <div className="flex flex-col gap-[var(--bh-space-5xl-24)]">
9
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-xl-12)]">
10
10
  <Button>Primary</Button>
11
11
  <Button variant="secondary">Secondary</Button>
12
12
  <Button variant="soft">Soft</Button>
@@ -18,7 +18,7 @@ export function ButtonDemo() {
18
18
  <Button variant="white">White</Button>
19
19
  </div>
20
20
 
21
- <div className="flex flex-wrap items-center gap-3">
21
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-xl-12)]">
22
22
  <Button size="xs">XS</Button>
23
23
  <Button size="sm">Small</Button>
24
24
  <Button>Medium</Button>
@@ -26,7 +26,7 @@ export function ButtonDemo() {
26
26
  <Button size="xl">XL</Button>
27
27
  </div>
28
28
 
29
- <div className="flex flex-wrap items-center gap-3">
29
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-xl-12)]">
30
30
  <Button size="icon-xs" aria-label="Add item">
31
31
  <PlusIcon />
32
32
  </Button>
@@ -44,7 +44,7 @@ export function ButtonDemo() {
44
44
  </Button>
45
45
  </div>
46
46
 
47
- <div className="flex flex-wrap items-center gap-3">
47
+ <div className="flex flex-wrap items-center gap-[var(--bh-space-xl-12)]">
48
48
  <Button>
49
49
  <PlusIcon data-icon="inline-start" />
50
50
  New item
@@ -63,7 +63,7 @@ export function ButtonDemo() {
63
63
  </Button>
64
64
  </div>
65
65
 
66
- <div dir="rtl" className="flex flex-wrap items-center gap-3">
66
+ <div dir="rtl" className="flex flex-wrap items-center gap-[var(--bh-space-xl-12)]">
67
67
  <Button>إرسال</Button>
68
68
  <Button variant="outline">
69
69
  متابعة
@@ -1,10 +1,15 @@
1
1
  import { PlusIcon } from "lucide-react"
2
2
 
3
- import { ButtonGroup, ButtonGroupItem } from "@/components/ui/button-group"
3
+ import {
4
+ ButtonGroup,
5
+ ButtonGroupItem,
6
+ ToggleGroup,
7
+ ToggleGroupItem,
8
+ } from "@/components/ui/button-group"
4
9
 
5
10
  export function ButtonGroupDemo() {
6
11
  return (
7
- <div className="grid gap-6">
12
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
8
13
  <ButtonGroup aria-label="Button group">
9
14
  {Array.from({ length: 7 }).map((_, index) => (
10
15
  <ButtonGroupItem
@@ -37,6 +42,22 @@ export function ButtonGroupDemo() {
37
42
  ))}
38
43
  </ButtonGroup>
39
44
  </div>
45
+
46
+ <ToggleGroup aria-label="Text alignment" defaultValue="start">
47
+ <ToggleGroupItem value="start">Start</ToggleGroupItem>
48
+ <ToggleGroupItem value="center">Center</ToggleGroupItem>
49
+ <ToggleGroupItem value="end">End</ToggleGroupItem>
50
+ </ToggleGroup>
51
+
52
+ <ToggleGroup
53
+ aria-label="Text styles"
54
+ defaultValue={["bold"]}
55
+ type="multiple"
56
+ >
57
+ <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
58
+ <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
59
+ <ToggleGroupItem value="underline">Underline</ToggleGroupItem>
60
+ </ToggleGroup>
40
61
  </div>
41
62
  )
42
63
  }
@@ -4,28 +4,65 @@ const cardImage = new URL("../assets/images/art-01.jpg", import.meta.url).href
4
4
 
5
5
  const rtlCardCopy = {
6
6
  action: "\u0627\u0646\u0642\u0631 \u0647\u0646\u0627",
7
+ description:
8
+ "\u0627\u0646\u0637\u0644\u0642 \u0641\u064a \u0631\u062d\u0644\u0629 \u0639\u0628\u0631 \u0627\u0644\u0632\u0645\u0646 \u0644\u0627\u0633\u062a\u0643\u0634\u0627\u0641 \u0623\u0633\u0631\u0627\u0631 \u0627\u0644\u0623\u0647\u0631\u0627\u0645\u0627\u062a \u0627\u0644\u0643\u0628\u0631\u0649.",
7
9
  subtitle:
8
10
  "\u0639\u0646\u0648\u0627\u0646 \u0641\u0631\u0639\u064a \u0644\u0644\u0628\u0637\u0627\u0642\u0629",
9
11
  title:
10
12
  "\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0628\u0637\u0627\u0642\u0629",
11
13
  }
12
14
 
15
+ const ltrCardCopy = {
16
+ action: "Explore",
17
+ description:
18
+ "Journey through time as we explore the mysteries of the Great Pyramids and the Sphinx.",
19
+ subtitle: "Ancient Egypt",
20
+ title: "The Great Pyramids",
21
+ }
22
+
13
23
  export function CardDemo() {
14
24
  return (
15
- <div className="grid gap-6">
16
- <div className="flex flex-wrap items-start gap-4">
17
- <Card imageSrc={cardImage} />
18
- <Card imageSrc={cardImage} type="full-image" />
25
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
26
+ <div className="flex flex-wrap items-start gap-[var(--bh-space-3xl-16)]">
27
+ <Card
28
+ description={ltrCardCopy.description}
29
+ imageSrc={cardImage}
30
+ primaryActionLabel={ltrCardCopy.action}
31
+ subtitle={ltrCardCopy.subtitle}
32
+ title={ltrCardCopy.title}
33
+ />
34
+ <Card
35
+ imageSrc={cardImage}
36
+ subtitle={ltrCardCopy.subtitle}
37
+ title={ltrCardCopy.title}
38
+ type="full-image"
39
+ />
19
40
  </div>
20
41
 
21
- <div className="grid gap-4">
22
- <Card imageSrc={cardImage} orientation="horizontal" />
23
- <Card imageSrc={cardImage} orientation="horizontal" type="trailing-image" />
42
+ <div className="grid gap-[var(--bh-space-3xl-16)]">
43
+ <Card
44
+ description={ltrCardCopy.description}
45
+ imageSrc={cardImage}
46
+ orientation="horizontal"
47
+ primaryActionLabel={ltrCardCopy.action}
48
+ subtitle={ltrCardCopy.subtitle}
49
+ title={ltrCardCopy.title}
50
+ />
51
+ <Card
52
+ description={ltrCardCopy.description}
53
+ imageSrc={cardImage}
54
+ orientation="horizontal"
55
+ primaryActionLabel={ltrCardCopy.action}
56
+ subtitle={ltrCardCopy.subtitle}
57
+ title={ltrCardCopy.title}
58
+ type="trailing-image"
59
+ />
24
60
  </div>
25
61
 
26
- <div dir="rtl" className="flex flex-wrap items-start gap-4">
62
+ <div dir="rtl" className="flex flex-wrap items-start gap-[var(--bh-space-3xl-16)]">
27
63
  <Card
28
64
  dir="rtl"
65
+ description={rtlCardCopy.description}
29
66
  primaryActionLabel={rtlCardCopy.action}
30
67
  secondaryActionLabel={rtlCardCopy.action}
31
68
  imageSrc={cardImage}
@@ -35,6 +72,7 @@ export function CardDemo() {
35
72
  <Card
36
73
  breakpoint="mobile"
37
74
  dir="rtl"
75
+ description={rtlCardCopy.description}
38
76
  orientation="horizontal"
39
77
  primaryActionLabel={rtlCardCopy.action}
40
78
  secondaryActionLabel={rtlCardCopy.action}
@@ -1,4 +1,5 @@
1
1
  import {
2
+ arabicCarouselMessages,
2
3
  Carousel,
3
4
  CarouselContent,
4
5
  CarouselItem,
@@ -8,7 +9,24 @@ import {
8
9
 
9
10
  export function CarouselDemo() {
10
11
  return (
11
- <Carousel className="w-full max-w-sm">
12
+ <div className="grid gap-[var(--bh-space-5xl-24)]">
13
+ <Carousel className="w-full max-w-sm">
14
+ <CarouselSlides />
15
+ </Carousel>
16
+ <Carousel
17
+ className="w-full max-w-sm"
18
+ dir="rtl"
19
+ messages={arabicCarouselMessages}
20
+ >
21
+ <CarouselSlides />
22
+ </Carousel>
23
+ </div>
24
+ )
25
+ }
26
+
27
+ function CarouselSlides() {
28
+ return (
29
+ <>
12
30
  <CarouselContent>
13
31
  {[1, 2, 3].map((item) => (
14
32
  <CarouselItem key={item}>
@@ -20,6 +38,6 @@ export function CarouselDemo() {
20
38
  </CarouselContent>
21
39
  <CarouselPrevious />
22
40
  <CarouselNext />
23
- </Carousel>
41
+ </>
24
42
  )
25
43
  }
@@ -24,7 +24,7 @@ export function ChartDemo() {
24
24
  dataKey="revenue"
25
25
  type="monotone"
26
26
  stroke="var(--color-revenue)"
27
- strokeWidth={2}
27
+ strokeWidth="var(--bh-icon-stroke-200)"
28
28
  dot={false}
29
29
  />
30
30
  </LineChart>