banhaten 0.1.2 → 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 (365) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/CONTRIBUTING.md +44 -0
  3. package/README.md +145 -328
  4. package/SECURITY.md +15 -0
  5. package/banhaten.config.example.json +1 -3
  6. package/docs/design-system/README.md +20 -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 +189 -0
  10. package/docs/design-system/appearances/default.md +94 -0
  11. package/docs/design-system/appearances/rounded.md +95 -0
  12. package/docs/design-system/appearances/sharp.md +95 -0
  13. package/docs/design-system/component-docs-pattern.md +81 -0
  14. package/docs/design-system/component-showcase-consistency-report.md +217 -0
  15. package/docs/design-system/component-token-consistency-audit.md +173 -0
  16. package/docs/design-system/components/README.md +75 -0
  17. package/docs/design-system/components/accordion.md +67 -0
  18. package/docs/design-system/components/activity-feed.md +106 -0
  19. package/docs/design-system/components/alert-dialog.md +87 -0
  20. package/docs/design-system/components/alert.md +111 -0
  21. package/docs/design-system/components/aspect-ratio.md +59 -0
  22. package/docs/design-system/components/attribute.md +103 -0
  23. package/docs/design-system/components/autocomplete.md +93 -0
  24. package/docs/design-system/components/avatar.md +70 -0
  25. package/docs/design-system/components/badge.md +72 -0
  26. package/docs/design-system/components/banner.md +99 -0
  27. package/docs/design-system/components/breadcrumbs.md +188 -0
  28. package/docs/design-system/components/button-group.md +117 -0
  29. package/docs/design-system/components/button.md +95 -0
  30. package/docs/design-system/components/card.md +95 -0
  31. package/docs/design-system/components/carousel.md +61 -0
  32. package/docs/design-system/components/catalog-components.md +59 -0
  33. package/docs/design-system/components/chart.md +58 -0
  34. package/docs/design-system/components/checkbox.md +68 -0
  35. package/docs/design-system/components/collapsible.md +63 -0
  36. package/docs/design-system/components/command.md +75 -0
  37. package/docs/design-system/components/context-menu.md +59 -0
  38. package/docs/design-system/components/date-picker.md +97 -0
  39. package/docs/design-system/components/divider.md +117 -0
  40. package/docs/design-system/components/empty-state.md +72 -0
  41. package/docs/design-system/components/field.md +86 -0
  42. package/docs/design-system/components/file-upload.md +199 -0
  43. package/docs/design-system/components/hover-card.md +61 -0
  44. package/docs/design-system/components/icons.md +48 -0
  45. package/docs/design-system/components/input-group.md +73 -0
  46. package/docs/design-system/components/input-otp.md +73 -0
  47. package/docs/design-system/components/input.md +84 -0
  48. package/docs/design-system/components/item.md +72 -0
  49. package/docs/design-system/components/kbd.md +62 -0
  50. package/docs/design-system/components/label.md +64 -0
  51. package/docs/design-system/components/menu.md +76 -0
  52. package/docs/design-system/components/menubar.md +60 -0
  53. package/docs/design-system/components/modal.md +119 -0
  54. package/docs/design-system/components/native-select.md +70 -0
  55. package/docs/design-system/components/navigation-menu.md +63 -0
  56. package/docs/design-system/components/onboarding-step-list-item.md +94 -0
  57. package/docs/design-system/components/page-header.md +98 -0
  58. package/docs/design-system/components/pagination.md +71 -0
  59. package/docs/design-system/components/popover.md +77 -0
  60. package/docs/design-system/components/progress-slider.md +66 -0
  61. package/docs/design-system/components/progress.md +92 -0
  62. package/docs/design-system/components/radio-card.md +65 -0
  63. package/docs/design-system/components/radio-group.md +72 -0
  64. package/docs/design-system/components/resizable.md +57 -0
  65. package/docs/design-system/components/scroll-area.md +60 -0
  66. package/docs/design-system/components/segmented-control.md +71 -0
  67. package/docs/design-system/components/select.md +87 -0
  68. package/docs/design-system/components/sheet.md +82 -0
  69. package/docs/design-system/components/sidebar.md +83 -0
  70. package/docs/design-system/components/skeleton.md +91 -0
  71. package/docs/design-system/components/slideout.md +77 -0
  72. package/docs/design-system/components/slider.md +81 -0
  73. package/docs/design-system/components/social-button.md +65 -0
  74. package/docs/design-system/components/spinner.md +77 -0
  75. package/docs/design-system/components/steps.md +77 -0
  76. package/docs/design-system/components/table.md +411 -0
  77. package/docs/design-system/components/tabs.md +69 -0
  78. package/docs/design-system/components/tag.md +95 -0
  79. package/docs/design-system/components/textarea.md +64 -0
  80. package/docs/design-system/components/timeline.md +95 -0
  81. package/docs/design-system/components/toast.md +73 -0
  82. package/docs/design-system/components/toggle.md +96 -0
  83. package/docs/design-system/components/toolbar.md +105 -0
  84. package/docs/design-system/components/tooltip.md +107 -0
  85. package/docs/design-system/components/typography.md +18 -0
  86. package/docs/design-system/density-and-elevation.md +44 -0
  87. package/docs/design-system/design-system-test-missing-items.md +368 -0
  88. package/docs/design-system/direction-and-localization.md +23 -0
  89. package/docs/design-system/form-recipes.md +73 -0
  90. package/docs/design-system/gap-promotion-policy.md +21 -0
  91. package/docs/design-system/gap-promotion-report.md +166 -0
  92. package/docs/design-system/icons.md +69 -0
  93. package/docs/design-system/installation.md +68 -0
  94. package/docs/design-system/launch-comparison-shadcn.md +98 -0
  95. package/docs/design-system/registry-and-cli.md +64 -0
  96. package/docs/design-system/release-policy.md +30 -0
  97. package/docs/design-system/roadmap.md +14 -0
  98. package/docs/design-system/support-matrix.md +23 -0
  99. package/docs/design-system/tabs.md +53 -0
  100. package/docs/design-system/token-governance.md +60 -0
  101. package/package.json +97 -65
  102. package/registry/component-contract.json +40 -0
  103. package/registry/components/alert-dialog.tsx +297 -0
  104. package/registry/components/alert.tsx +86 -65
  105. package/registry/components/aspect-ratio.tsx +30 -0
  106. package/registry/components/autocomplete.tsx +23 -9
  107. package/registry/components/avatar.tsx +7 -7
  108. package/registry/components/badge.tsx +1 -1
  109. package/registry/components/button-group.tsx +321 -4
  110. package/registry/components/button.tsx +38 -17
  111. package/registry/components/card.tsx +68 -59
  112. package/registry/components/carousel.tsx +282 -0
  113. package/registry/components/chart.tsx +203 -0
  114. package/registry/components/checkbox.tsx +3 -3
  115. package/registry/components/collapsible.tsx +69 -0
  116. package/registry/components/command.tsx +174 -0
  117. package/registry/components/context-menu.tsx +236 -0
  118. package/registry/components/date-picker.tsx +246 -105
  119. package/registry/components/expanded/ActivityFeed.tsx +6 -15
  120. package/registry/components/expanded/Banner.tsx +3 -3
  121. package/registry/components/expanded/Breadcrumbs.tsx +5 -5
  122. package/registry/components/expanded/CatalogComponentsShowcase.tsx +13 -13
  123. package/registry/components/expanded/CatalogDivider.tsx +1 -1
  124. package/registry/components/expanded/EmptyState.tsx +1 -1
  125. package/registry/components/expanded/FileUpload.tsx +9 -2
  126. package/registry/components/expanded/OnboardingStepListItem.tsx +2 -4
  127. package/registry/components/expanded/PageHeader.tsx +14 -14
  128. package/registry/components/expanded/Slideout.tsx +15 -415
  129. package/registry/components/expanded/Steps.tsx +4 -4
  130. package/registry/components/expanded/Table.tsx +116 -69
  131. package/registry/components/expanded/Timeline.tsx +3 -3
  132. package/registry/components/expanded/activityFeed.css +1 -1
  133. package/registry/components/expanded/breadcrumbs.css +139 -139
  134. package/registry/components/expanded/catalogComponentsShowcase.css +83 -83
  135. package/registry/components/expanded/divider.css +1 -1
  136. package/registry/components/expanded/emptyState.css +1 -1
  137. package/registry/components/expanded/fileUpload.css +6 -6
  138. package/registry/components/expanded/slideout.css +9 -685
  139. package/registry/components/expanded/steps.css +274 -274
  140. package/registry/components/expanded/table.css +2 -2
  141. package/registry/components/expanded/timeline.css +264 -264
  142. package/registry/components/field.tsx +230 -0
  143. package/registry/components/hover-card.tsx +48 -0
  144. package/registry/components/input-content.ts +1 -0
  145. package/registry/components/input-group.tsx +130 -0
  146. package/registry/components/input-otp.tsx +13 -3
  147. package/registry/components/input.tsx +70 -45
  148. package/registry/components/item.tsx +189 -0
  149. package/registry/components/kbd.tsx +151 -0
  150. package/registry/components/label.tsx +78 -0
  151. package/registry/components/menu.tsx +34 -246
  152. package/registry/components/menubar.tsx +226 -0
  153. package/registry/components/modal.tsx +216 -143
  154. package/registry/components/native-select.tsx +205 -0
  155. package/registry/components/navigation-menu.tsx +171 -0
  156. package/registry/components/pagination.tsx +80 -58
  157. package/registry/components/popover.tsx +162 -664
  158. package/registry/components/radio-card.tsx +116 -87
  159. package/registry/components/radio-group.tsx +1 -1
  160. package/registry/components/resizable.tsx +74 -0
  161. package/registry/components/scroll-area.tsx +67 -0
  162. package/registry/components/segmented-control.tsx +87 -0
  163. package/registry/components/select-content.tsx +2 -2
  164. package/registry/components/select.tsx +54 -20
  165. package/registry/components/sheet.tsx +305 -0
  166. package/registry/components/sidebar.tsx +352 -0
  167. package/registry/components/skeleton.css +0 -3
  168. package/registry/components/social-button.tsx +116 -30
  169. package/registry/components/spinner.tsx +18 -55
  170. package/registry/components/{expanded/tabs.css → tabs.css} +127 -106
  171. package/registry/components/tabs.tsx +246 -0
  172. package/registry/components/tag.tsx +2 -2
  173. package/registry/components/textarea.tsx +4 -4
  174. package/registry/components/toast.tsx +136 -0
  175. package/registry/components/toggle.tsx +2 -2
  176. package/registry/components/toolbar.tsx +89 -17
  177. package/registry/components/tooltip.tsx +1 -1
  178. package/registry/examples/alert-demo.tsx +25 -5
  179. package/registry/examples/alert-dialog-demo.tsx +42 -0
  180. package/registry/examples/aspect-ratio-demo.tsx +11 -0
  181. package/registry/examples/attribute-demo.tsx +1 -1
  182. package/registry/examples/autocomplete-demo.tsx +3 -3
  183. package/registry/examples/avatar-demo.tsx +7 -7
  184. package/registry/examples/badge-demo.tsx +1 -1
  185. package/registry/examples/button-demo.tsx +6 -6
  186. package/registry/examples/button-group-demo.tsx +23 -2
  187. package/registry/examples/card-demo.tsx +46 -8
  188. package/registry/examples/carousel-demo.tsx +43 -0
  189. package/registry/examples/chart-demo.tsx +33 -0
  190. package/registry/examples/checkbox-demo.tsx +5 -5
  191. package/registry/examples/collapsible-demo.tsx +16 -0
  192. package/registry/examples/collection-filter-bar-demo.tsx +135 -0
  193. package/registry/examples/command-demo.tsx +42 -0
  194. package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
  195. package/registry/examples/context-menu-demo.tsx +29 -0
  196. package/registry/examples/control-density-contract-demo.tsx +61 -0
  197. package/registry/examples/date-picker-demo.tsx +12 -12
  198. package/registry/examples/divider-demo.tsx +3 -3
  199. package/registry/examples/expanded/banner-demo.tsx +1 -1
  200. package/registry/examples/expanded/breadcrumbs-demo.tsx +1 -1
  201. package/registry/examples/expanded/empty-state-demo.tsx +1 -1
  202. package/registry/examples/expanded/file-upload-demo.tsx +1 -1
  203. package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
  204. package/registry/examples/expanded/slideout-demo.tsx +2 -2
  205. package/registry/examples/expanded/steps-demo.tsx +1 -1
  206. package/registry/examples/expanded/tabs-demo.tsx +2 -2
  207. package/registry/examples/expanded/timeline-demo.tsx +1 -1
  208. package/registry/examples/field-demo.tsx +51 -0
  209. package/registry/examples/hover-card-demo.tsx +23 -0
  210. package/registry/examples/input-demo.tsx +6 -6
  211. package/registry/examples/input-group-demo.tsx +16 -0
  212. package/registry/examples/input-otp-demo.tsx +4 -4
  213. package/registry/examples/item-demo.tsx +46 -0
  214. package/registry/examples/kbd-demo.tsx +11 -0
  215. package/registry/examples/label-demo.tsx +20 -0
  216. package/registry/examples/menu-demo.tsx +1 -1
  217. package/registry/examples/menubar-demo.tsx +34 -0
  218. package/registry/examples/modal-demo.tsx +67 -9
  219. package/registry/examples/native-select-demo.tsx +16 -0
  220. package/registry/examples/navigation-menu-demo.tsx +29 -0
  221. package/registry/examples/pagination-demo.tsx +6 -3
  222. package/registry/examples/popover-demo.tsx +19 -19
  223. package/registry/examples/progress-demo.tsx +1 -1
  224. package/registry/examples/progress-slider-demo.tsx +1 -1
  225. package/registry/examples/radio-card-demo.tsx +4 -4
  226. package/registry/examples/radio-group-demo.tsx +2 -2
  227. package/registry/examples/resizable-demo.tsx +22 -0
  228. package/registry/examples/results-toolbar-demo.tsx +44 -0
  229. package/registry/examples/scroll-area-demo.tsx +15 -0
  230. package/registry/examples/segmented-control-demo.tsx +39 -0
  231. package/registry/examples/select-demo.tsx +1 -1
  232. package/registry/examples/sheet-demo.tsx +47 -0
  233. package/registry/examples/sidebar-demo.tsx +55 -0
  234. package/registry/examples/slider-demo.tsx +3 -3
  235. package/registry/examples/social-button-demo.tsx +18 -8
  236. package/registry/examples/spinner-demo.tsx +13 -13
  237. package/registry/examples/tabs-demo.tsx +13 -0
  238. package/registry/examples/tag-demo.tsx +1 -1
  239. package/registry/examples/textarea-demo.tsx +4 -4
  240. package/registry/examples/toast-demo.tsx +35 -0
  241. package/registry/examples/toggle-demo.tsx +6 -6
  242. package/registry/examples/tooltip-demo.tsx +4 -4
  243. package/registry/guidance/USAGE.md +27 -0
  244. package/registry/hooks/use-direction.ts +193 -13
  245. package/registry/index.json +6010 -432
  246. package/registry/styles/globals.css +3112 -4690
  247. package/registry.json +1582 -0
  248. package/schema/config.schema.json +51 -0
  249. package/schema/registry.schema.json +190 -0
  250. package/schema/tokens.schema.json +163 -0
  251. package/src/cli/command-line.js +194 -0
  252. package/src/cli/config-editors.js +9 -0
  253. package/src/cli/doctor.js +399 -0
  254. package/src/cli/file-transaction.js +295 -0
  255. package/src/cli/global-css.js +153 -0
  256. package/src/cli/index.js +639 -1391
  257. package/src/cli/install-plan.js +592 -0
  258. package/src/cli/install-receipt.js +171 -0
  259. package/src/cli/jsonc.js +203 -0
  260. package/src/cli/package-install-state.js +254 -0
  261. package/src/cli/package-manager.js +238 -0
  262. package/src/cli/package-plan.js +185 -0
  263. package/src/cli/package-version.js +97 -0
  264. package/src/cli/registry-query.js +207 -0
  265. package/src/cli/reporting.js +55 -0
  266. package/src/cli/schema-validation.js +19 -0
  267. package/src/cli/source-scanner.js +686 -0
  268. package/src/cli/vite-config.js +478 -0
  269. package/tokens/banhaten.tokens.json +4313 -310
  270. package/registry/assets/avatars/avatar-02.jpg +0 -0
  271. package/registry/assets/avatars/avatar-03.jpg +0 -0
  272. package/registry/assets/avatars/avatar-04.jpg +0 -0
  273. package/registry/assets/avatars/avatar-05.jpg +0 -0
  274. package/registry/assets/avatars/avatar-06.jpg +0 -0
  275. package/registry/assets/avatars/avatar-07.jpg +0 -0
  276. package/registry/assets/avatars/avatar-08.jpg +0 -0
  277. package/registry/assets/avatars/avatar-09.jpg +0 -0
  278. package/registry/assets/avatars/avatar-10.jpg +0 -0
  279. package/registry/assets/avatars/avatar-11.jpg +0 -0
  280. package/registry/assets/avatars/avatar-12.jpg +0 -0
  281. package/registry/assets/avatars/avatar-13.jpg +0 -0
  282. package/registry/assets/avatars/avatar-14.jpg +0 -0
  283. package/registry/assets/avatars/avatar-15.jpg +0 -0
  284. package/registry/assets/avatars/avatar-16.jpg +0 -0
  285. package/registry/assets/avatars/avatar-17.jpg +0 -0
  286. package/registry/assets/avatars/avatar-18.jpg +0 -0
  287. package/registry/assets/avatars/avatar-19.jpg +0 -0
  288. package/registry/assets/avatars/avatar-20.jpg +0 -0
  289. package/registry/assets/avatars/avatar-21.jpg +0 -0
  290. package/registry/assets/avatars/avatar-22.jpg +0 -0
  291. package/registry/assets/avatars/avatar-23.jpg +0 -0
  292. package/registry/assets/avatars/avatar-24.jpg +0 -0
  293. package/registry/assets/avatars/avatar-25.jpg +0 -0
  294. package/registry/assets/avatars/avatar-26.jpg +0 -0
  295. package/registry/assets/avatars/avatar-27.jpg +0 -0
  296. package/registry/assets/avatars/avatar-28.jpg +0 -0
  297. package/registry/assets/avatars/avatar-29.jpg +0 -0
  298. package/registry/assets/avatars/avatar-30.jpg +0 -0
  299. package/registry/assets/avatars/avatar-31.jpg +0 -0
  300. package/registry/assets/avatars/avatar-32.jpg +0 -0
  301. package/registry/assets/avatars/avatar-33.jpg +0 -0
  302. package/registry/assets/avatars/avatar-34.jpg +0 -0
  303. package/registry/assets/avatars/avatar-35.jpg +0 -0
  304. package/registry/assets/image-assets.json +0 -744
  305. package/registry/assets/images/art-02.jpg +0 -0
  306. package/registry/assets/images/art-03.jpg +0 -0
  307. package/registry/assets/images/art-04.jpg +0 -0
  308. package/registry/assets/images/art-05.jpg +0 -0
  309. package/registry/assets/images/art-06.jpg +0 -0
  310. package/registry/assets/images/art-07.jpg +0 -0
  311. package/registry/assets/images/art-08.jpg +0 -0
  312. package/registry/assets/images/art-09.jpg +0 -0
  313. package/registry/assets/images/art-10.jpg +0 -0
  314. package/registry/assets/images/art-11.jpg +0 -0
  315. package/registry/assets/images/art-12.jpg +0 -0
  316. package/registry/assets/images/art-13.jpg +0 -0
  317. package/registry/assets/images/art-14.jpg +0 -0
  318. package/registry/assets/images/art-15.jpg +0 -0
  319. package/registry/assets/images/art-16.jpg +0 -0
  320. package/registry/assets/images/art-17.jpg +0 -0
  321. package/registry/assets/images/art-18.jpg +0 -0
  322. package/registry/assets/images/art-19.jpg +0 -0
  323. package/registry/assets/images/art-20.jpg +0 -0
  324. package/registry/assets/images/art-21.jpg +0 -0
  325. package/registry/assets/images/art-22.jpg +0 -0
  326. package/registry/assets/images/art-23.jpg +0 -0
  327. package/registry/assets/images/art-24.jpg +0 -0
  328. package/registry/assets/images/art-25.jpg +0 -0
  329. package/registry/assets/images/art-26.jpg +0 -0
  330. package/registry/assets/images/art-27.jpg +0 -0
  331. package/registry/assets/images/nature-01.jpg +0 -0
  332. package/registry/assets/images/nature-02.jpg +0 -0
  333. package/registry/assets/images/nature-03.jpg +0 -0
  334. package/registry/assets/images/nature-04.jpg +0 -0
  335. package/registry/assets/images/nature-05.jpg +0 -0
  336. package/registry/assets/images/nature-06.jpg +0 -0
  337. package/registry/assets/images/nature-07.jpg +0 -0
  338. package/registry/assets/images/nature-08.jpg +0 -0
  339. package/registry/assets/images/nature-09.jpg +0 -0
  340. package/registry/assets/images/nature-10.jpg +0 -0
  341. package/registry/assets/images/nature-11.jpg +0 -0
  342. package/registry/assets/images/nature-12.jpg +0 -0
  343. package/registry/assets/images/nature-13.jpg +0 -0
  344. package/registry/assets/images/nature-14.jpg +0 -0
  345. package/registry/assets/images/nature-15.jpg +0 -0
  346. package/registry/assets/images/nature-16.jpg +0 -0
  347. package/registry/assets/images/nature-17.jpg +0 -0
  348. package/registry/assets/images/nature-18.jpg +0 -0
  349. package/registry/assets/images/nature-19.jpg +0 -0
  350. package/registry/assets/images/nature-20.jpg +0 -0
  351. package/registry/components/expanded/BannerBoard.tsx +0 -225
  352. package/registry/components/expanded/CatalogTag.tsx +0 -85
  353. package/registry/components/expanded/CommandBar.tsx +0 -386
  354. package/registry/components/expanded/IconExplorer.tsx +0 -612
  355. package/registry/components/expanded/Tabs.tsx +0 -86
  356. package/registry/components/expanded/TimelineShowcase.tsx +0 -158
  357. package/registry/components/expanded/commandBar.css +0 -470
  358. package/registry/components/expanded/iconExplorer.css +0 -764
  359. package/registry/components/expanded/iconPacks.ts +0 -866
  360. package/registry/components/expanded/tag.css +0 -148
  361. package/registry/examples/expanded/icons-demo.tsx +0 -5
  362. package/tokens/Color mode.zip +0 -0
  363. package/tokens/Numbers.zip +0 -0
  364. package/tokens/Radius.zip +0 -0
  365. package/tokens/Theme.zip +0 -0
@@ -5,14 +5,38 @@ import * as DialogPrimitive from "@radix-ui/react-dialog"
5
5
  import { cva, type VariantProps } from "class-variance-authority"
6
6
  import { InfoIcon, TriangleAlertIcon, XIcon } from "lucide-react"
7
7
 
8
+ import {
9
+ AlertDialog,
10
+ AlertDialogAction,
11
+ AlertDialogCancel,
12
+ AlertDialogContent,
13
+ AlertDialogDescription,
14
+ AlertDialogTitle,
15
+ type AlertDialogContentProps,
16
+ } from "@/components/ui/alert-dialog"
8
17
  import { Button, type ButtonProps } from "@/components/ui/button"
9
18
  import { Checkbox, type CheckboxProps } from "@/components/ui/checkbox"
10
19
  import { Spinner } from "@/components/ui/spinner"
11
20
  import { cn } from "@/lib/utils"
21
+ import { useResolvedDirection } from "@/hooks/use-direction"
12
22
 
13
23
  type ModalSize = "sm" | "default" | "lg"
14
24
  type ModalIntent = "default" | "warning" | "danger"
15
25
 
26
+ type ModalMessages = {
27
+ checkboxLabel: React.ReactNode
28
+ closeLabel: string
29
+ primaryActionLabel: React.ReactNode
30
+ secondaryActionLabel: React.ReactNode
31
+ }
32
+
33
+ type ConfirmModalMessages = {
34
+ cancelLabel: React.ReactNode
35
+ closeLabel: string
36
+ confirmLabel: React.ReactNode
37
+ confirmLoadingLabel: React.ReactNode
38
+ }
39
+
16
40
  const modalSurfaceBaseClassName = [
17
41
  "flex max-h-[calc(100vh-(var(--bh-space-8xl-48)*2))] w-[var(--bh-modal-width)] max-w-[calc(100vw-(var(--bh-space-4xl-20)*2))] flex-col overflow-hidden rounded-[var(--bh-radius-2xl-12)] bg-[var(--bh-bg-raised)] text-[var(--bh-content-default)] shadow-[var(--shadow-modal)] outline-none",
18
42
  "[--bh-modal-border:var(--bh-border-subtle)] [--shadow-modal:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-modal-border),var(--shadow-component-default)]",
@@ -57,6 +81,12 @@ const modalHeaderIconIntentClassNames: Record<ModalIntent, string> = {
57
81
  "rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-warning-subtle)] text-[var(--bh-content-warning-default)]",
58
82
  }
59
83
 
84
+ const modalTitleClassName =
85
+ "min-w-0 flex-1 text-start text-[length:var(--bh-text-heading-sm-semibold-font-size)] font-[var(--bh-text-heading-sm-semibold-font-weight)] leading-[var(--bh-text-heading-sm-semibold-line-height)] tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)] text-[var(--bh-content-default)]"
86
+
87
+ const modalDescriptionClassName =
88
+ "min-w-0 flex-1 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-subtle)]"
89
+
60
90
  type ModalRootProps = React.ComponentProps<typeof DialogPrimitive.Root>
61
91
  type ModalContentProps = React.ComponentPropsWithoutRef<
62
92
  typeof DialogPrimitive.Content
@@ -79,6 +109,7 @@ type ModalHeaderIconProps = React.ComponentProps<"span"> & {
79
109
  type ModalCloseButtonProps = React.ComponentProps<"button"> & {
80
110
  label?: string
81
111
  }
112
+ type ConfirmModalContentProps = AlertDialogContentProps
82
113
  type ModalFooterCheckboxProps = Omit<React.ComponentProps<"div">, "children"> & {
83
114
  checked?: CheckboxProps["checked"]
84
115
  defaultChecked?: CheckboxProps["defaultChecked"]
@@ -93,9 +124,11 @@ type ModalProps = Omit<ModalRootProps, "children"> &
93
124
  checkboxLabel?: React.ReactNode
94
125
  children?: React.ReactNode
95
126
  className?: string
127
+ closeLabel?: string
96
128
  description?: React.ReactNode
97
129
  dir?: "ltr" | "rtl"
98
130
  footer?: React.ReactNode
131
+ messages?: Partial<ModalMessages>
99
132
  overlayClassName?: string
100
133
  primaryActionLabel?: React.ReactNode
101
134
  secondaryActionLabel?: React.ReactNode
@@ -104,13 +137,14 @@ type ModalProps = Omit<ModalRootProps, "children"> &
104
137
  showDivider?: boolean
105
138
  showFooter?: boolean
106
139
  showIcon?: boolean
107
- title?: React.ReactNode
140
+ title: React.ReactNode
108
141
  }
109
142
 
110
143
  type ConfirmModalProps = Omit<
111
144
  ModalProps,
112
145
  | "checkboxLabel"
113
146
  | "footer"
147
+ | "messages"
114
148
  | "primaryActionLabel"
115
149
  | "secondaryActionLabel"
116
150
  | "showCheckbox"
@@ -126,38 +160,42 @@ type ConfirmModalProps = Omit<
126
160
  confirmLoadingLabel?: React.ReactNode
127
161
  confirmVariant?: ModalActionButtonProps["variant"]
128
162
  intent?: ModalIntent
163
+ messages?: Partial<ConfirmModalMessages>
129
164
  onCancel?: React.MouseEventHandler<HTMLButtonElement>
130
165
  onConfirm?: React.MouseEventHandler<HTMLButtonElement>
131
166
  onEscapeKeyDown?: ModalContentProps["onEscapeKeyDown"]
132
- onInteractOutside?: ModalContentProps["onInteractOutside"]
133
167
  onOpenAutoFocus?: ModalContentProps["onOpenAutoFocus"]
134
- onPointerDownOutside?: ModalContentProps["onPointerDownOutside"]
135
168
  preventEscapeDismiss?: boolean
136
- preventOutsideDismiss?: boolean
137
169
  showCancelButton?: boolean
138
170
  }
139
171
 
140
- const defaultModalTitle = "Modal Title"
141
- const defaultModalDescription =
142
- "Are you sure you want to proceed with this action? Please review your choices before confirming."
143
- const defaultModalCheckboxLabel = "Don't show me again"
144
- const defaultConfirmTitle = "Confirm action"
145
- const defaultConfirmDescription =
146
- "This action may affect saved data. Review the details before confirming."
147
- const defaultConfirmCancelLabel = "Cancel"
148
- const defaultConfirmActionLabel = "Confirm"
149
- const defaultConfirmLoadingLabel = "Confirming"
150
- const defaultRtlModalTitle = "\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0646\u0645\u0648\u0630\u062c"
151
- const defaultRtlModalDescription =
152
- "\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0623\u0646\u0643 \u062a\u0631\u064a\u062f \u0627\u0644\u0645\u062a\u0627\u0628\u0639\u0629 \u0645\u0639 \u0647\u0630\u0627 \u0627\u0644\u0625\u062c\u0631\u0627\u0621\u061f \u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629 \u062e\u064a\u0627\u0631\u0627\u062a\u0643 \u0642\u0628\u0644 \u0627\u0644\u062a\u0623\u0643\u064a\u062f."
153
- const defaultRtlModalCheckboxLabel = "\u0627\u0644\u062a\u0633\u0645\u064a\u0629"
154
- const defaultRtlActionLabel = "\u0627\u0646\u0642\u0631 \u0647\u0646\u0627"
155
- const defaultRtlConfirmTitle = "\u062a\u0623\u0643\u064a\u062f \u0627\u0644\u0625\u062c\u0631\u0627\u0621"
156
- const defaultRtlConfirmDescription =
157
- "\u0642\u062f \u064a\u0624\u062b\u0631 \u0647\u0630\u0627 \u0627\u0644\u0625\u062c\u0631\u0627\u0621 \u0639\u0644\u0649 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u062d\u0641\u0648\u0638\u0629. \u0631\u0627\u062c\u0639 \u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 \u0642\u0628\u0644 \u0627\u0644\u062a\u0623\u0643\u064a\u062f."
158
- const defaultRtlConfirmCancelLabel = "\u0625\u0644\u063a\u0627\u0621"
159
- const defaultRtlConfirmActionLabel = "\u062a\u0623\u0643\u064a\u062f"
160
- const defaultRtlConfirmLoadingLabel = "\u062c\u0627\u0631\u064a \u0627\u0644\u062a\u0623\u0643\u064a\u062f"
172
+ const defaultModalMessages: ModalMessages = {
173
+ checkboxLabel: "Don't show me again",
174
+ closeLabel: "Close modal",
175
+ primaryActionLabel: "Action",
176
+ secondaryActionLabel: "Action",
177
+ }
178
+
179
+ const arabicModalMessages: ModalMessages = {
180
+ checkboxLabel: "\u0627\u0644\u062a\u0633\u0645\u064a\u0629",
181
+ closeLabel: "\u0625\u063a\u0644\u0627\u0642 \u0627\u0644\u0646\u0645\u0648\u0630\u062c",
182
+ primaryActionLabel: "\u0627\u0646\u0642\u0631 \u0647\u0646\u0627",
183
+ secondaryActionLabel: "\u0627\u0646\u0642\u0631 \u0647\u0646\u0627",
184
+ }
185
+
186
+ const defaultConfirmModalMessages: ConfirmModalMessages = {
187
+ cancelLabel: "Cancel",
188
+ closeLabel: "Close modal",
189
+ confirmLabel: "Confirm",
190
+ confirmLoadingLabel: "Confirming",
191
+ }
192
+
193
+ const arabicConfirmModalMessages: ConfirmModalMessages = {
194
+ cancelLabel: "\u0625\u0644\u063a\u0627\u0621",
195
+ closeLabel: "\u0625\u063a\u0644\u0627\u0642 \u0627\u0644\u0646\u0645\u0648\u0630\u062c",
196
+ confirmLabel: "\u062a\u0623\u0643\u064a\u062f",
197
+ confirmLoadingLabel: "\u062c\u0627\u0631\u064a \u0627\u0644\u062a\u0623\u0643\u064a\u062f",
198
+ }
161
199
 
162
200
  const ModalRoot = DialogPrimitive.Root
163
201
  const ModalTrigger = DialogPrimitive.Trigger
@@ -182,16 +220,33 @@ const ModalContent = React.forwardRef<
182
220
  React.ElementRef<typeof DialogPrimitive.Content>,
183
221
  ModalContentProps
184
222
  >(function ModalContent(
185
- { children, className, overlayClassName, size, ...props },
223
+ { children, className, dir, overlayClassName, size, ...props },
186
224
  ref
187
225
  ) {
226
+ const contentRef = React.useRef<
227
+ React.ElementRef<typeof DialogPrimitive.Content> | null
228
+ >(null)
229
+ const resolvedDirection = useResolvedDirection(
230
+ dir === "ltr" || dir === "rtl" ? dir : undefined,
231
+ contentRef
232
+ )
233
+ const setContentRef = React.useCallback(
234
+ (node: React.ElementRef<typeof DialogPrimitive.Content> | null) => {
235
+ contentRef.current = node
236
+ if (typeof ref === "function") ref(node)
237
+ else if (ref) ref.current = node
238
+ },
239
+ [ref]
240
+ )
241
+
188
242
  return (
189
243
  <ModalPortal>
190
244
  <ModalOverlay className={overlayClassName} />
191
245
  <DialogPrimitive.Content
192
246
  data-size={size ?? "sm"}
193
247
  data-slot="modal-content"
194
- ref={ref}
248
+ dir={resolvedDirection}
249
+ ref={setContentRef}
195
250
  className={cn(modalContentVariants({ size, className }))}
196
251
  {...props}
197
252
  >
@@ -238,13 +293,10 @@ const ModalTitle = React.forwardRef<
238
293
  >(function ModalTitle({ className, dir = "auto", ...props }, ref) {
239
294
  return (
240
295
  <DialogPrimitive.Title
241
- data-slot="modal-title"
242
- dir={dir}
243
- ref={ref}
244
- className={cn(
245
- "min-w-0 flex-1 text-start text-[length:var(--bh-text-heading-sm-semibold-font-size)] font-[var(--bh-text-heading-sm-semibold-font-weight)] leading-[var(--bh-text-heading-sm-semibold-line-height)] tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)] text-[var(--bh-content-default)]",
246
- className
247
- )}
296
+ data-slot="modal-title"
297
+ dir={dir}
298
+ ref={ref}
299
+ className={cn(modalTitleClassName, className)}
248
300
  {...props}
249
301
  />
250
302
  )
@@ -256,15 +308,56 @@ const ModalDescription = React.forwardRef<
256
308
  >(function ModalDescription({ className, dir = "auto", ...props }, ref) {
257
309
  return (
258
310
  <DialogPrimitive.Description
259
- data-slot="modal-description"
260
- dir={dir}
311
+ data-slot="modal-description"
312
+ dir={dir}
313
+ ref={ref}
314
+ className={cn(modalDescriptionClassName, className)}
315
+ {...props}
316
+ />
317
+ )
318
+ })
319
+
320
+ // One close affordance, two dismissal wrappers. Dialog uses ModalClose and
321
+ // AlertDialog uses AlertDialogCancel, but the button itself is identical — so
322
+ // an a11y or focus-ring fix here reaches both instead of one.
323
+ const ModalCloseButtonSurface = React.forwardRef<
324
+ HTMLButtonElement,
325
+ ModalCloseButtonProps
326
+ >(function ModalCloseButtonSurface(
327
+ { children, className, label = "Close modal", type = "button", ...props },
328
+ ref
329
+ ) {
330
+ return (
331
+ <button
332
+ aria-label={label}
333
+ data-slot="modal-close"
261
334
  ref={ref}
335
+ type={type}
262
336
  className={cn(
263
- "min-w-0 flex-1 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-subtle)]",
337
+ "absolute end-[var(--bh-space-3xl-16)] top-1/2 inline-flex size-[var(--bh-space-6xl-32)] -translate-y-1/2 items-center justify-center rounded-[var(--bh-radius-full)] border-0 bg-transparent p-0 text-[var(--bh-content-subtle)] outline-none transition-[background-color,box-shadow,color] hover:bg-[var(--bh-interactive-ghost-hover)] hover:text-[var(--bh-content-default)] focus-visible:shadow-[var(--shadow-button-focus)]",
264
338
  className
265
339
  )}
266
340
  {...props}
267
- />
341
+ >
342
+ {children ?? (
343
+ <XIcon
344
+ aria-hidden="true"
345
+ className="size-[var(--bh-space-5xl-24)]"
346
+ strokeWidth="var(--bh-icon-stroke-200)"
347
+ />
348
+ )}
349
+ </button>
350
+ )
351
+ })
352
+
353
+ const ConfirmModalCloseButton = React.forwardRef<
354
+ HTMLButtonElement,
355
+ ModalCloseButtonProps
356
+ >(function ConfirmModalCloseButton(props, ref) {
357
+ return (
358
+ <AlertDialogCancel asChild>
359
+ <ModalCloseButtonSurface ref={ref} {...props} />
360
+ </AlertDialogCancel>
268
361
  )
269
362
  })
270
363
 
@@ -335,38 +428,17 @@ function ModalHeaderIcon({
335
428
  {...props}
336
429
  >
337
430
  {children ?? (
338
- <InfoIcon className="size-[var(--bh-space-3xl-16)]" strokeWidth={2} />
431
+ <InfoIcon className="size-[var(--bh-space-3xl-16)]" strokeWidth="var(--bh-icon-stroke-200)" />
339
432
  )}
340
433
  </span>
341
434
  )
342
435
  }
343
436
 
344
437
  const ModalCloseButton = React.forwardRef<HTMLButtonElement, ModalCloseButtonProps>(
345
- function ModalCloseButton(
346
- { children, className, label = "Close modal", type = "button", ...props },
347
- ref
348
- ) {
438
+ function ModalCloseButton(props, ref) {
349
439
  return (
350
440
  <ModalClose asChild>
351
- <button
352
- aria-label={label}
353
- data-slot="modal-close"
354
- ref={ref}
355
- type={type}
356
- className={cn(
357
- "absolute end-[var(--bh-space-3xl-16)] top-1/2 inline-flex size-[var(--bh-space-6xl-32)] -translate-y-1/2 items-center justify-center rounded-[var(--bh-radius-full)] border-0 bg-transparent p-0 text-[var(--bh-content-subtle)] outline-none transition-[background-color,box-shadow,color] hover:bg-[var(--bh-interactive-ghost-hover)] hover:text-[var(--bh-content-default)] focus-visible:shadow-[var(--shadow-button-focus)]",
358
- className
359
- )}
360
- {...props}
361
- >
362
- {children ?? (
363
- <XIcon
364
- aria-hidden="true"
365
- className="size-[var(--bh-space-5xl-24)]"
366
- strokeWidth={2}
367
- />
368
- )}
369
- </button>
441
+ <ModalCloseButtonSurface ref={ref} {...props} />
370
442
  </ModalClose>
371
443
  )
372
444
  }
@@ -377,7 +449,7 @@ function ModalFooterCheckbox({
377
449
  className,
378
450
  defaultChecked,
379
451
  disabled,
380
- label = defaultModalCheckboxLabel,
452
+ label = defaultModalMessages.checkboxLabel,
381
453
  onCheckedChange,
382
454
  ...props
383
455
  }: ModalFooterCheckboxProps) {
@@ -449,10 +521,12 @@ function Modal({
449
521
  checkboxLabel,
450
522
  children,
451
523
  className,
452
- defaultOpen = true,
524
+ closeLabel,
525
+ defaultOpen = false,
453
526
  description,
454
527
  dir,
455
528
  footer,
529
+ messages: messageOverrides,
456
530
  modal = true,
457
531
  onOpenChange,
458
532
  open,
@@ -468,20 +542,20 @@ function Modal({
468
542
  title,
469
543
  ...props
470
544
  }: ModalProps) {
471
- const isRtl = dir === "rtl"
472
545
  const rootProps =
473
546
  open === undefined
474
547
  ? { defaultOpen, modal, onOpenChange }
475
548
  : { modal, onOpenChange, open }
476
- const resolvedTitle = title ?? (isRtl ? defaultRtlModalTitle : defaultModalTitle)
477
- const resolvedDescription =
478
- description ?? (isRtl ? defaultRtlModalDescription : defaultModalDescription)
549
+ const messages = { ...defaultModalMessages, ...messageOverrides }
550
+ const resolvedTitle = title
551
+ const resolvedDescription = description
479
552
  const resolvedCheckboxLabel =
480
- checkboxLabel ?? (isRtl ? defaultRtlModalCheckboxLabel : defaultModalCheckboxLabel)
553
+ checkboxLabel ?? messages.checkboxLabel
481
554
  const resolvedPrimaryAction =
482
- primaryActionLabel ?? (isRtl ? defaultRtlActionLabel : "Action")
555
+ primaryActionLabel ?? messages.primaryActionLabel
483
556
  const resolvedSecondaryAction =
484
- secondaryActionLabel ?? (isRtl ? defaultRtlActionLabel : "Action")
557
+ secondaryActionLabel ?? messages.secondaryActionLabel
558
+ const resolvedCloseLabel = closeLabel ?? messages.closeLabel
485
559
 
486
560
  return (
487
561
  <ModalRoot {...rootProps}>
@@ -496,7 +570,7 @@ function Modal({
496
570
  <ModalHeader>
497
571
  {showIcon ? <ModalHeaderIcon /> : null}
498
572
  <ModalTitle>{resolvedTitle}</ModalTitle>
499
- {showCloseButton ? <ModalCloseButton /> : null}
573
+ {showCloseButton ? <ModalCloseButton label={resolvedCloseLabel} /> : null}
500
574
  </ModalHeader>
501
575
  <ModalBody>
502
576
  {children ?? <ModalDescription>{resolvedDescription}</ModalDescription>}
@@ -527,6 +601,7 @@ function ConfirmModal({
527
601
  cancelLabel,
528
602
  children,
529
603
  className,
604
+ closeLabel,
530
605
  closeOnCancel = true,
531
606
  closeOnConfirm = true,
532
607
  confirmButtonProps,
@@ -535,22 +610,20 @@ function ConfirmModal({
535
610
  confirmLoading = false,
536
611
  confirmLoadingLabel,
537
612
  confirmVariant,
538
- defaultOpen = true,
613
+ defaultOpen = false,
539
614
  description,
540
615
  dir,
541
616
  intent = "danger",
617
+ messages: messageOverrides,
542
618
  modal = true,
543
619
  onCancel,
544
620
  onConfirm,
545
621
  onEscapeKeyDown,
546
- onInteractOutside,
547
622
  onOpenAutoFocus,
548
623
  onOpenChange,
549
- onPointerDownOutside,
550
624
  open,
551
625
  overlayClassName,
552
626
  preventEscapeDismiss = false,
553
- preventOutsideDismiss = true,
554
627
  showCancelButton = true,
555
628
  showCloseButton = false,
556
629
  showDivider = true,
@@ -562,21 +635,24 @@ function ConfirmModal({
562
635
  }: ConfirmModalProps) {
563
636
  const cancelButtonRef = React.useRef<HTMLButtonElement>(null)
564
637
  const confirmButtonRef = React.useRef<HTMLButtonElement>(null)
565
- const isRtl = dir === "rtl"
638
+ const directionBoundaryRef = React.useRef<
639
+ React.ElementRef<typeof AlertDialogContent> | null
640
+ >(null)
641
+ const resolvedDirection = useResolvedDirection(dir, directionBoundaryRef)
566
642
  const rootProps =
567
643
  open === undefined
568
644
  ? { defaultOpen, modal, onOpenChange }
569
645
  : { modal, onOpenChange, open }
570
- const resolvedTitle = title ?? (isRtl ? defaultRtlConfirmTitle : defaultConfirmTitle)
571
- const resolvedDescription =
572
- description ?? (isRtl ? defaultRtlConfirmDescription : defaultConfirmDescription)
646
+ const messages = { ...defaultConfirmModalMessages, ...messageOverrides }
647
+ const resolvedTitle = title
648
+ const resolvedDescription = description
573
649
  const resolvedCancelLabel =
574
- cancelLabel ?? (isRtl ? defaultRtlConfirmCancelLabel : defaultConfirmCancelLabel)
650
+ cancelLabel ?? messages.cancelLabel
575
651
  const resolvedConfirmLabel =
576
- confirmLabel ?? (isRtl ? defaultRtlConfirmActionLabel : defaultConfirmActionLabel)
652
+ confirmLabel ?? messages.confirmLabel
577
653
  const resolvedConfirmLoadingLabel =
578
- confirmLoadingLabel ??
579
- (isRtl ? defaultRtlConfirmLoadingLabel : defaultConfirmLoadingLabel)
654
+ confirmLoadingLabel ?? messages.confirmLoadingLabel
655
+ const resolvedCloseLabel = closeLabel ?? messages.closeLabel
580
656
  const {
581
657
  children: cancelButtonChildren,
582
658
  onClick: cancelButtonOnClick,
@@ -592,57 +668,35 @@ function ConfirmModal({
592
668
  } = confirmButtonProps ?? {}
593
669
  const isConfirmDisabled = confirmDisabled || confirmLoading || confirmButtonDisabled
594
670
 
595
- const handleOpenAutoFocus: NonNullable<ModalContentProps["onOpenAutoFocus"]> =
596
- React.useCallback(
597
- (event) => {
598
- onOpenAutoFocus?.(event)
599
- if (event.defaultPrevented) return
671
+ const handleOpenAutoFocus: NonNullable<
672
+ ConfirmModalContentProps["onOpenAutoFocus"]
673
+ > = React.useCallback(
674
+ (event) => {
675
+ onOpenAutoFocus?.(event)
676
+ if (event.defaultPrevented) return
600
677
 
601
- const focusTarget = showCancelButton
602
- ? cancelButtonRef.current
603
- : confirmButtonRef.current
604
- if (!focusTarget) return
678
+ const focusTarget = showCancelButton
679
+ ? cancelButtonRef.current
680
+ : confirmButtonRef.current
681
+ if (!focusTarget) return
605
682
 
606
- event.preventDefault()
607
- focusTarget.focus()
608
- },
609
- [onOpenAutoFocus, showCancelButton]
610
- )
683
+ event.preventDefault()
684
+ focusTarget.focus()
685
+ },
686
+ [onOpenAutoFocus, showCancelButton]
687
+ )
611
688
 
612
- const handlePointerDownOutside: NonNullable<
613
- ModalContentProps["onPointerDownOutside"]
689
+ const handleEscapeKeyDown: NonNullable<
690
+ ConfirmModalContentProps["onEscapeKeyDown"]
614
691
  > = React.useCallback(
615
692
  (event) => {
616
- onPointerDownOutside?.(event)
617
- if (!event.defaultPrevented && preventOutsideDismiss) {
693
+ onEscapeKeyDown?.(event)
694
+ if (!event.defaultPrevented && preventEscapeDismiss) {
618
695
  event.preventDefault()
619
696
  }
620
697
  },
621
- [onPointerDownOutside, preventOutsideDismiss]
698
+ [onEscapeKeyDown, preventEscapeDismiss]
622
699
  )
623
-
624
- const handleInteractOutside: NonNullable<ModalContentProps["onInteractOutside"]> =
625
- React.useCallback(
626
- (event) => {
627
- onInteractOutside?.(event)
628
- if (!event.defaultPrevented && preventOutsideDismiss) {
629
- event.preventDefault()
630
- }
631
- },
632
- [onInteractOutside, preventOutsideDismiss]
633
- )
634
-
635
- const handleEscapeKeyDown: NonNullable<ModalContentProps["onEscapeKeyDown"]> =
636
- React.useCallback(
637
- (event) => {
638
- onEscapeKeyDown?.(event)
639
- if (!event.defaultPrevented && preventEscapeDismiss) {
640
- event.preventDefault()
641
- }
642
- },
643
- [onEscapeKeyDown, preventEscapeDismiss]
644
- )
645
-
646
700
  const handleCancel: React.MouseEventHandler<HTMLButtonElement> = (event) => {
647
701
  cancelButtonOnClick?.(event)
648
702
  if (!event.defaultPrevented) {
@@ -691,59 +745,74 @@ function ConfirmModal({
691
745
  )
692
746
 
693
747
  return (
694
- <ModalRoot {...rootProps}>
695
- <ModalContent
748
+ <AlertDialog {...rootProps}>
749
+ <AlertDialogContent
696
750
  data-intent={intent}
751
+ data-size={size}
697
752
  data-slot="confirm-modal"
698
- dir={dir}
753
+ dir={resolvedDirection}
754
+ ref={directionBoundaryRef}
755
+ className={cn(modalContentVariants({ size, className }))}
699
756
  overlayClassName={overlayClassName}
700
- role="alertdialog"
701
- size={size}
702
- className={className}
703
757
  onEscapeKeyDown={handleEscapeKeyDown}
704
- onInteractOutside={handleInteractOutside}
705
758
  onOpenAutoFocus={handleOpenAutoFocus}
706
- onPointerDownOutside={handlePointerDownOutside}
707
759
  {...props}
708
760
  >
709
761
  <ModalHeader>
710
762
  {showIcon ? (
711
763
  <ModalHeaderIcon intent={intent}>
712
764
  {intent === "default" ? (
713
- <InfoIcon className="size-[var(--bh-space-3xl-16)]" strokeWidth={2} />
765
+ <InfoIcon
766
+ className="size-[var(--bh-space-3xl-16)]"
767
+ strokeWidth="var(--bh-icon-stroke-200)"
768
+ />
714
769
  ) : (
715
770
  <TriangleAlertIcon
716
771
  className="size-[var(--bh-space-3xl-16)]"
717
- strokeWidth={2}
772
+ strokeWidth="var(--bh-icon-stroke-200)"
718
773
  />
719
774
  )}
720
775
  </ModalHeaderIcon>
721
776
  ) : null}
722
- <ModalTitle>{resolvedTitle}</ModalTitle>
723
- {showCloseButton ? <ModalCloseButton /> : null}
777
+ <AlertDialogTitle
778
+ data-slot="modal-title"
779
+ className={modalTitleClassName}
780
+ >
781
+ {resolvedTitle}
782
+ </AlertDialogTitle>
783
+ {showCloseButton ? (
784
+ <ConfirmModalCloseButton label={resolvedCloseLabel} />
785
+ ) : null}
724
786
  </ModalHeader>
725
787
  <ModalBody>
726
- {children ?? <ModalDescription>{resolvedDescription}</ModalDescription>}
788
+ {children ?? (
789
+ <AlertDialogDescription
790
+ data-slot="modal-description"
791
+ className={modalDescriptionClassName}
792
+ >
793
+ {resolvedDescription}
794
+ </AlertDialogDescription>
795
+ )}
727
796
  </ModalBody>
728
797
  {showDivider ? <ModalDivider /> : null}
729
798
  {showFooter ? (
730
799
  <ModalFooter>
731
800
  <ModalActions>
732
801
  {cancelAction && closeOnCancel ? (
733
- <ModalClose asChild>{cancelAction}</ModalClose>
802
+ <AlertDialogCancel asChild>{cancelAction}</AlertDialogCancel>
734
803
  ) : (
735
804
  cancelAction
736
805
  )}
737
806
  {closeOnConfirm ? (
738
- <ModalClose asChild>{confirmAction}</ModalClose>
807
+ <AlertDialogAction asChild>{confirmAction}</AlertDialogAction>
739
808
  ) : (
740
809
  confirmAction
741
810
  )}
742
811
  </ModalActions>
743
812
  </ModalFooter>
744
813
  ) : null}
745
- </ModalContent>
746
- </ModalRoot>
814
+ </AlertDialogContent>
815
+ </AlertDialog>
747
816
  )
748
817
  }
749
818
 
@@ -756,6 +825,8 @@ function getConfirmActionVariant(
756
825
  }
757
826
 
758
827
  export {
828
+ arabicConfirmModalMessages,
829
+ arabicModalMessages,
759
830
  ConfirmModal,
760
831
  Modal,
761
832
  ModalActionButton,
@@ -780,6 +851,7 @@ export {
780
851
  modalSurfaceVariants,
781
852
  }
782
853
  export type {
854
+ ConfirmModalMessages,
783
855
  ConfirmModalProps,
784
856
  ModalActionButtonProps,
785
857
  ModalActionsProps,
@@ -791,6 +863,7 @@ export type {
791
863
  ModalHeaderIconProps,
792
864
  ModalHeaderProps,
793
865
  ModalIntent,
866
+ ModalMessages,
794
867
  ModalOverlayProps,
795
868
  ModalProps,
796
869
  ModalRootProps,