@dxos/react-ui 0.8.4-main.8360d9e660 → 0.8.4-main.8baae0fced

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 (300) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/chunk-A5QCIG5R.mjs +24 -0
  4. package/dist/lib/browser/chunk-A5QCIG5R.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-EJSGYGYH.mjs → chunk-LY5XDQR5.mjs} +84 -12
  6. package/dist/lib/browser/chunk-LY5XDQR5.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +1322 -811
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/testing/index.mjs +30 -24
  11. package/dist/lib/browser/testing/index.mjs.map +3 -3
  12. package/dist/lib/browser/translations.mjs +9 -0
  13. package/dist/lib/browser/translations.mjs.map +7 -0
  14. package/dist/lib/node-esm/{chunk-B7MXDDMJ.mjs → chunk-NGKLIKP3.mjs} +84 -12
  15. package/dist/lib/node-esm/chunk-NGKLIKP3.mjs.map +7 -0
  16. package/dist/lib/node-esm/chunk-XCFLA74M.mjs +26 -0
  17. package/dist/lib/node-esm/chunk-XCFLA74M.mjs.map +7 -0
  18. package/dist/lib/node-esm/index.mjs +1322 -811
  19. package/dist/lib/node-esm/index.mjs.map +4 -4
  20. package/dist/lib/node-esm/meta.json +1 -1
  21. package/dist/lib/node-esm/testing/index.mjs +30 -24
  22. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  23. package/dist/lib/node-esm/translations.mjs +10 -0
  24. package/dist/lib/node-esm/translations.mjs.map +7 -0
  25. package/dist/types/src/components/Avatars/Avatar.d.ts +1 -1
  26. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  27. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  30. package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  32. package/dist/types/src/components/Button/Button.stories.d.ts +1 -1
  33. package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/Button/IconButton.d.ts +1 -0
  35. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  36. package/dist/types/src/components/Button/IconButton.stories.d.ts +3 -0
  37. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/Button/ToggleGroup.d.ts +2 -2
  40. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts +2 -2
  41. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/Card/Card.d.ts +59 -42
  43. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  44. package/dist/types/src/components/Card/Card.stories.d.ts +2 -2
  45. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -1
  46. package/dist/types/src/components/Carousel/Carousel.d.ts +106 -0
  47. package/dist/types/src/components/Carousel/Carousel.d.ts.map +1 -0
  48. package/dist/types/src/components/Carousel/index.d.ts +2 -0
  49. package/dist/types/src/components/Carousel/index.d.ts.map +1 -0
  50. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  51. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  52. package/dist/types/src/components/Clipboard/index.d.ts +1 -1
  53. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  54. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  55. package/dist/types/src/components/Dialog/AlertDialog.d.ts +34 -23
  56. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  57. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/Dialog/Dialog.d.ts +38 -21
  59. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  60. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +3 -2
  61. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  62. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  63. package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts.map +1 -1
  64. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -1
  65. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +14 -3
  66. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
  67. package/dist/types/src/components/ErrorFallback/ThrowError.d.ts.map +1 -1
  68. package/dist/types/src/components/Focus/Focus.d.ts +36 -0
  69. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -0
  70. package/dist/types/src/components/Focus/Focus.stories.d.ts +9 -0
  71. package/dist/types/src/components/Focus/Focus.stories.d.ts.map +1 -0
  72. package/dist/types/src/components/Focus/index.d.ts +2 -0
  73. package/dist/types/src/components/Focus/index.d.ts.map +1 -0
  74. package/dist/types/src/components/Icon/Icon.d.ts +4 -0
  75. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  76. package/dist/types/src/components/Icon/Icon.stories.d.ts +11 -3
  77. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -1
  78. package/dist/types/src/components/Image/Image.d.ts +2 -1
  79. package/dist/types/src/components/Image/Image.d.ts.map +1 -1
  80. package/dist/types/src/components/Image/Image.stories.d.ts +3 -2
  81. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -1
  82. package/dist/types/src/components/Input/Input.d.ts +12 -15
  83. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  84. package/dist/types/src/components/Input/Input.stories.d.ts +3 -3
  85. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  86. package/dist/types/src/components/Link/Link.d.ts.map +1 -1
  87. package/dist/types/src/components/Link/Link.stories.d.ts.map +1 -1
  88. package/dist/types/src/components/List/List.d.ts +5 -3
  89. package/dist/types/src/components/List/List.d.ts.map +1 -1
  90. package/dist/types/src/components/List/List.stories.d.ts +3 -1
  91. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  92. package/dist/types/src/components/List/ListDropIndicator.d.ts.map +1 -1
  93. package/dist/types/src/components/List/Tree.d.ts +2 -2
  94. package/dist/types/src/components/List/Tree.d.ts.map +1 -1
  95. package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -1
  96. package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +1 -1
  97. package/dist/types/src/components/List/Treegrid.d.ts +5 -9
  98. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
  99. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -1
  100. package/dist/types/src/components/Main/Main.d.ts +7 -3
  101. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  102. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/Main/useSwipeToDismiss.d.ts.map +1 -1
  104. package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts +46 -0
  105. package/dist/types/src/components/MediaPlayer/MediaPlayer.d.ts.map +1 -0
  106. package/dist/types/src/components/MediaPlayer/MediaPlayer.stories.d.ts +16 -0
  107. package/dist/types/src/components/MediaPlayer/MediaPlayer.stories.d.ts.map +1 -0
  108. package/dist/types/src/components/MediaPlayer/index.d.ts +2 -0
  109. package/dist/types/src/components/MediaPlayer/index.d.ts.map +1 -0
  110. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
  111. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -1
  112. package/dist/types/src/components/Menu/DropdownMenu.d.ts +13 -6
  113. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  114. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts +9 -1
  115. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
  116. package/dist/types/src/components/Message/Message.d.ts +1 -1
  117. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  118. package/dist/types/src/components/Message/Message.stories.d.ts +2 -2
  119. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  120. package/dist/types/src/components/Popover/Popover.d.ts +14 -3
  121. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  122. package/dist/types/src/components/Popover/Popover.stories.d.ts.map +1 -1
  123. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +12 -9
  124. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  125. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +18 -5
  126. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  127. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +42 -13
  128. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  129. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +5 -6
  130. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  131. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  132. package/dist/types/src/components/Select/Select.stories.d.ts +2 -2
  133. package/dist/types/src/components/Select/Select.stories.d.ts.map +1 -1
  134. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -1
  135. package/dist/types/src/components/Splitter/Splitter.d.ts +19 -17
  136. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -1
  137. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -1
  138. package/dist/types/src/components/Status/Status.d.ts +3 -4
  139. package/dist/types/src/components/Status/Status.d.ts.map +1 -1
  140. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  141. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  142. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -1
  143. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  144. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts +1 -1
  145. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  146. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +54 -55
  147. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  148. package/dist/types/src/components/ThemeProvider/index.d.ts +1 -1
  149. package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
  150. package/dist/types/src/components/Toast/Toast.d.ts +4 -4
  151. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  152. package/dist/types/src/components/Toast/Toast.stories.d.ts.map +1 -1
  153. package/dist/types/src/components/Toolbar/Toolbar.d.ts +11 -15
  154. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  155. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  156. package/dist/types/src/components/Tooltip/Tooltip.d.ts +8 -8
  157. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  158. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +2 -2
  159. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  160. package/dist/types/src/components/index.d.ts +3 -0
  161. package/dist/types/src/components/index.d.ts.map +1 -1
  162. package/dist/types/src/exemplars/generics.stories.d.ts +6 -5
  163. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -1
  164. package/dist/types/src/exemplars/slot.stories.d.ts +1 -0
  165. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -1
  166. package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -1
  167. package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -1
  168. package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
  169. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  170. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  171. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  172. package/dist/types/src/hooks/useSafeArea.d.ts.map +1 -1
  173. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -1
  174. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  175. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  176. package/dist/types/src/playground/Custom.stories.d.ts +1 -1
  177. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
  178. package/dist/types/src/playground/Typography.stories.d.ts.map +1 -1
  179. package/dist/types/src/primitives/Column/Column.d.ts +21 -14
  180. package/dist/types/src/primitives/Column/Column.d.ts.map +1 -1
  181. package/dist/types/src/primitives/Column/Column.stories.d.ts +19 -0
  182. package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -1
  183. package/dist/types/src/primitives/Container/Container.d.ts +4 -5
  184. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -1
  185. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -1
  186. package/dist/types/src/primitives/Flex/Flex.d.ts +5 -7
  187. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -1
  188. package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -1
  189. package/dist/types/src/primitives/Grid/Grid.d.ts +3 -8
  190. package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -1
  191. package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -1
  192. package/dist/types/src/primitives/Panel/Panel.d.ts +24 -15
  193. package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -1
  194. package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -1
  195. package/dist/types/src/testing/Loading.d.ts.map +1 -1
  196. package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
  197. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
  198. package/dist/types/src/testing/decorators/withTheme.d.ts +1 -1
  199. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  200. package/dist/types/src/translations.d.ts +8 -3
  201. package/dist/types/src/translations.d.ts.map +1 -1
  202. package/dist/types/src/util/usePx.d.ts.map +1 -1
  203. package/dist/types/tsconfig.tsbuildinfo +1 -1
  204. package/package.json +29 -26
  205. package/src/components/Avatars/Avatar.stories.tsx +2 -3
  206. package/src/components/Avatars/Avatar.tsx +1 -2
  207. package/src/components/Avatars/AvatarGroup.stories.tsx +0 -1
  208. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -2
  209. package/src/components/Button/Button.stories.tsx +0 -1
  210. package/src/components/Button/Button.tsx +3 -11
  211. package/src/components/Button/IconButton.stories.tsx +6 -4
  212. package/src/components/Button/IconButton.tsx +3 -3
  213. package/src/components/Button/Toggle.stories.tsx +0 -1
  214. package/src/components/Button/ToggleGroup.stories.tsx +0 -1
  215. package/src/components/Card/Card.stories.tsx +15 -15
  216. package/src/components/Card/Card.tsx +190 -66
  217. package/src/components/Carousel/Carousel.tsx +379 -0
  218. package/src/components/Carousel/index.ts +5 -0
  219. package/src/components/Clipboard/CopyButton.tsx +5 -6
  220. package/src/components/Dialog/AlertDialog.stories.tsx +5 -6
  221. package/src/components/Dialog/AlertDialog.tsx +51 -93
  222. package/src/components/Dialog/Dialog.stories.tsx +64 -9
  223. package/src/components/Dialog/Dialog.tsx +66 -56
  224. package/src/components/ErrorFallback/ErrorFallback.stories.tsx +3 -8
  225. package/src/components/ErrorFallback/ErrorStack.tsx +36 -2
  226. package/src/components/Focus/AUDIT.md +43 -0
  227. package/src/components/Focus/Focus.stories.tsx +230 -0
  228. package/src/components/Focus/Focus.tsx +201 -0
  229. package/src/components/Focus/index.ts +5 -0
  230. package/src/components/Icon/Icon.stories.tsx +43 -13
  231. package/src/components/Icon/Icon.tsx +13 -3
  232. package/src/components/Image/Image.stories.tsx +3 -3
  233. package/src/components/Image/Image.tsx +31 -8
  234. package/src/components/Input/Input.stories.tsx +3 -4
  235. package/src/components/Input/Input.tsx +3 -3
  236. package/src/components/Link/Link.stories.tsx +0 -1
  237. package/src/components/Link/Link.tsx +10 -2
  238. package/src/components/List/List.stories.tsx +1 -2
  239. package/src/components/List/List.tsx +7 -6
  240. package/src/components/List/ListDropIndicator.tsx +0 -1
  241. package/src/components/List/Tree.stories.tsx +2 -3
  242. package/src/components/List/Tree.tsx +0 -1
  243. package/src/components/List/Treegrid.stories.tsx +26 -27
  244. package/src/components/List/Treegrid.tsx +14 -14
  245. package/src/components/Main/Main.stories.tsx +0 -1
  246. package/src/components/Main/Main.tsx +0 -1
  247. package/src/components/MediaPlayer/MediaPlayer.stories.tsx +50 -0
  248. package/src/components/MediaPlayer/MediaPlayer.tsx +153 -0
  249. package/src/components/MediaPlayer/index.ts +5 -0
  250. package/src/components/Menu/ContextMenu.stories.tsx +0 -1
  251. package/src/components/Menu/DropdownMenu.stories.tsx +0 -1
  252. package/src/components/Menu/DropdownMenu.tsx +3 -3
  253. package/src/components/Message/Message.stories.tsx +7 -8
  254. package/src/components/Message/Message.tsx +23 -10
  255. package/src/components/Popover/Popover.stories.tsx +4 -5
  256. package/src/components/Popover/Popover.tsx +1 -1
  257. package/src/components/ScrollArea/ScrollArea.stories.tsx +89 -30
  258. package/src/components/ScrollArea/ScrollArea.tsx +39 -23
  259. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +19 -17
  260. package/src/components/ScrollContainer/ScrollContainer.tsx +199 -92
  261. package/src/components/Select/Select.stories.tsx +5 -6
  262. package/src/components/Skeleton/Skeleton.stories.tsx +0 -1
  263. package/src/components/Splitter/Splitter.stories.tsx +29 -29
  264. package/src/components/Splitter/Splitter.tsx +35 -34
  265. package/src/components/Status/Status.stories.tsx +0 -1
  266. package/src/components/Status/Status.tsx +8 -5
  267. package/src/components/Tag/Tag.stories.tsx +0 -1
  268. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +0 -1
  269. package/src/components/ThemeProvider/ThemeProvider.tsx +5 -4
  270. package/src/components/ThemeProvider/index.ts +1 -1
  271. package/src/components/Toast/Toast.stories.tsx +0 -1
  272. package/src/components/Toolbar/Toolbar.stories.tsx +0 -1
  273. package/src/components/Toolbar/Toolbar.tsx +19 -15
  274. package/src/components/Tooltip/Tooltip.stories.tsx +7 -8
  275. package/src/components/Tooltip/Tooltip.tsx +14 -13
  276. package/src/components/index.ts +3 -0
  277. package/src/exemplars/generics.stories.tsx +7 -15
  278. package/src/exemplars/slot.stories.tsx +65 -57
  279. package/src/exemplars/tabster.stories.tsx +1 -1
  280. package/src/exemplars/virtualizer.stories.tsx +4 -5
  281. package/src/hooks/useDensityContext.ts +2 -2
  282. package/src/playground/Custom.stories.tsx +6 -9
  283. package/src/primitives/Column/AUDIT.md +148 -0
  284. package/src/primitives/Column/Column.stories.tsx +122 -19
  285. package/src/primitives/Column/Column.tsx +73 -41
  286. package/src/primitives/Container/Container.stories.tsx +0 -1
  287. package/src/primitives/Container/Container.tsx +5 -8
  288. package/src/primitives/Flex/Flex.stories.tsx +0 -1
  289. package/src/primitives/Flex/Flex.tsx +10 -12
  290. package/src/primitives/Grid/Grid.stories.tsx +0 -1
  291. package/src/primitives/Grid/Grid.tsx +4 -9
  292. package/src/primitives/Panel/Panel.stories.tsx +8 -7
  293. package/src/primitives/Panel/Panel.tsx +64 -63
  294. package/src/testing/Loading.tsx +25 -4
  295. package/src/testing/decorators/withLayout.tsx +7 -17
  296. package/src/testing/decorators/withTheme.tsx +10 -7
  297. package/src/translations.ts +8 -3
  298. package/src/util/usePx.ts +1 -0
  299. package/dist/lib/browser/chunk-EJSGYGYH.mjs.map +0 -7
  300. package/dist/lib/node-esm/chunk-B7MXDDMJ.mjs.map +0 -7
@@ -0,0 +1,379 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
6
+ import React, {
7
+ createContext,
8
+ type KeyboardEvent,
9
+ type PropsWithChildren,
10
+ type ReactNode,
11
+ useCallback,
12
+ useContext,
13
+ useEffect,
14
+ useMemo,
15
+ useState,
16
+ } from 'react';
17
+
18
+ import { mx } from '@dxos/ui-theme';
19
+
20
+ import { translationKey } from '../../translations';
21
+ import { type ThemedClassName } from '../../util';
22
+ import { IconButton } from '../Button';
23
+ import { MediaPlayer, type MediaKind } from '../MediaPlayer';
24
+ import { useTranslation } from '../ThemeProvider';
25
+
26
+ // TODO(burdon): Move per-element class strings to `@dxos/ui-theme` (theme tokens)
27
+ // so callers can re-theme via the same mechanism the rest of `react-ui` uses.
28
+
29
+ //
30
+ // Context
31
+ //
32
+
33
+ type CarouselContextValue = {
34
+ index: number;
35
+ count: number;
36
+ setIndex: (index: number) => void;
37
+ next: () => void;
38
+ prev: () => void;
39
+ };
40
+
41
+ const CarouselContext = createContext<CarouselContextValue | null>(null);
42
+
43
+ /** Returns the current carousel state. Must be used within {@link Carousel.Root}. */
44
+ export const useCarousel = (): CarouselContextValue => {
45
+ const context = useContext(CarouselContext);
46
+ if (!context) {
47
+ throw new Error('useCarousel must be used within Carousel.Root');
48
+ }
49
+ return context;
50
+ };
51
+
52
+ //
53
+ // Root
54
+ //
55
+
56
+ export type CarouselRootProps = ThemedClassName<
57
+ PropsWithChildren<{
58
+ /** Total number of slides; drives auto-advance and indicator counts. */
59
+ count: number;
60
+ /** Whether to auto-advance slides on mount. Defaults to `false`. */
61
+ autorun?: boolean;
62
+ /** Auto-advance interval in milliseconds. Set 0 to disable. */
63
+ intervalMs?: number;
64
+ defaultIndex?: number;
65
+ }>
66
+ >;
67
+
68
+ const CarouselRoot = ({
69
+ classNames,
70
+ children,
71
+ count,
72
+ autorun = false,
73
+ intervalMs = 5_000,
74
+ defaultIndex = 0,
75
+ }: CarouselRootProps) => {
76
+ const [index, setIndexState] = useState(defaultIndex);
77
+ const [autoAdvance, setAutoAdvance] = useState(autorun);
78
+
79
+ // Reset to first slide if the slide count shrinks below the current index.
80
+ useEffect(() => {
81
+ if (index >= count) {
82
+ setIndexState(0);
83
+ }
84
+ }, [count, index]);
85
+
86
+ // Auto-advance — stops permanently once the user interacts with any control.
87
+ useEffect(() => {
88
+ if (!autoAdvance || count <= 1 || intervalMs <= 0) {
89
+ return;
90
+ }
91
+ const handle = setInterval(() => setIndexState((i) => (i + 1) % count), intervalMs);
92
+ return () => clearInterval(handle);
93
+ }, [autoAdvance, count, intervalMs]);
94
+
95
+ const setIndex = useCallback((next: number) => {
96
+ setAutoAdvance(false);
97
+ setIndexState(next);
98
+ }, []);
99
+ const next = useCallback(() => {
100
+ setAutoAdvance(false);
101
+ setIndexState((i) => (i + 1) % count);
102
+ }, [count]);
103
+ const prev = useCallback(() => {
104
+ setAutoAdvance(false);
105
+ setIndexState((i) => (i - 1 + count) % count);
106
+ }, [count]);
107
+
108
+ const value = useMemo(() => ({ index, count, setIndex, next, prev }), [index, count, setIndex, next, prev]);
109
+
110
+ if (count === 0) {
111
+ return null;
112
+ }
113
+
114
+ return (
115
+ <CarouselContext.Provider value={value}>
116
+ {/*
117
+ * Rows are `[1fr, auto]`: row 1 (Previous|Viewport|Next) stretches when the parent
118
+ * gives the carousel a definite height, and row 2 (Indicators / Caption) sticks to
119
+ * its content height. With no parent height constraint, the `1fr` row simply tracks
120
+ * row-1 content — preserving the existing aspect-video behaviour for unbounded use.
121
+ */}
122
+ {/* TODO(burdon): Move to ui-theme. */}
123
+ <div
124
+ className={mx(
125
+ 'w-full grid grid-cols-[min-content_1fr_min-content] grid-rows-[minmax(0,1fr)_auto] gap-4 items-center',
126
+ classNames,
127
+ )}
128
+ >
129
+ {children}
130
+ </div>
131
+ </CarouselContext.Provider>
132
+ );
133
+ };
134
+
135
+ CarouselRoot.displayName = 'Carousel.Root';
136
+
137
+ //
138
+ // Viewport
139
+ //
140
+
141
+ export type CarouselViewportProps = ThemedClassName<PropsWithChildren<{}>>;
142
+
143
+ const CarouselViewport = ({ children, classNames }: CarouselViewportProps) => {
144
+ const { t } = useTranslation(translationKey);
145
+ const { count, next, prev } = useCarousel();
146
+ const handleKeyDown = useCallback(
147
+ (event: KeyboardEvent<HTMLDivElement>) => {
148
+ if (count <= 1) {
149
+ return;
150
+ }
151
+ if (event.key === 'ArrowLeft') {
152
+ event.preventDefault();
153
+ prev();
154
+ } else if (event.key === 'ArrowRight') {
155
+ event.preventDefault();
156
+ next();
157
+ }
158
+ },
159
+ [count, next, prev],
160
+ );
161
+
162
+ return (
163
+ <div
164
+ // TODO(burdon): Move to ui-theme.
165
+ className={mx(
166
+ 'relative w-full aspect-video overflow-hidden',
167
+ 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
168
+ classNames,
169
+ )}
170
+ tabIndex={0}
171
+ role='region'
172
+ aria-roledescription='carousel'
173
+ aria-label={t('carousel-viewport.label')}
174
+ onKeyDown={handleKeyDown}
175
+ >
176
+ {children}
177
+ </div>
178
+ );
179
+ };
180
+
181
+ CarouselViewport.displayName = 'Carousel.Viewport';
182
+
183
+ //
184
+ // Slide
185
+ //
186
+
187
+ export type CarouselSlideProps = ThemedClassName<{
188
+ index: number;
189
+ /** Media source URL — rendered via the embedded {@link MediaPlayer}. */
190
+ src: string;
191
+ /** Override media auto-detection (`'video' | 'audio'`). */
192
+ kind?: MediaKind;
193
+ /** Accessible label / `<img alt>` fallback. */
194
+ alt?: string;
195
+ /** Class names forwarded to the inner `<img>` when MediaPlayer resolves to an image. */
196
+ imgClassNames?: string;
197
+ /** Class names forwarded to the inner `<video>` / `<audio>` / `<iframe>`. */
198
+ mediaClassNames?: string;
199
+ controls?: boolean;
200
+ autoPlay?: boolean;
201
+ loop?: boolean;
202
+ muted?: boolean;
203
+ crossOrigin?: 'anonymous' | 'use-credentials' | '';
204
+ }>;
205
+
206
+ const CarouselSlide = ({
207
+ index,
208
+ classNames,
209
+ src,
210
+ kind,
211
+ alt,
212
+ imgClassNames,
213
+ mediaClassNames,
214
+ controls,
215
+ autoPlay,
216
+ loop,
217
+ muted,
218
+ crossOrigin,
219
+ }: CarouselSlideProps) => {
220
+ const { index: active } = useCarousel();
221
+ if (active !== index) {
222
+ return null;
223
+ }
224
+
225
+ return (
226
+ <div className={mx('absolute inset-0 w-full h-full bg-baseSurface', classNames)}>
227
+ <MediaPlayer
228
+ src={src}
229
+ kind={kind}
230
+ alt={alt}
231
+ classNames='w-full h-full'
232
+ imgClassNames={mx('object-cover', imgClassNames)}
233
+ mediaClassNames={mediaClassNames}
234
+ controls={controls}
235
+ autoPlay={autoPlay}
236
+ loop={loop}
237
+ muted={muted}
238
+ crossOrigin={crossOrigin}
239
+ />
240
+ </div>
241
+ );
242
+ };
243
+
244
+ CarouselSlide.displayName = 'Carousel.Slide';
245
+
246
+ //
247
+ // Previous / Next
248
+ //
249
+
250
+ export type CarouselButtonProps = ThemedClassName<{}>;
251
+
252
+ const CarouselPrevious = ({ classNames }: CarouselButtonProps) => {
253
+ const { t } = useTranslation(translationKey);
254
+ const { count, prev } = useCarousel();
255
+ if (count <= 1) {
256
+ return <div />;
257
+ }
258
+
259
+ return (
260
+ <IconButton
261
+ classNames={mx('self-center', classNames)}
262
+ square
263
+ variant='ghost'
264
+ icon='ph--caret-left--regular'
265
+ iconOnly
266
+ label={t('carousel-prev.label')}
267
+ onClick={prev}
268
+ />
269
+ );
270
+ };
271
+
272
+ CarouselPrevious.displayName = 'Carousel.Previous';
273
+
274
+ const CarouselNext = ({ classNames }: CarouselButtonProps) => {
275
+ const { t } = useTranslation(translationKey);
276
+ const { count, next } = useCarousel();
277
+ if (count <= 1) {
278
+ return <div />;
279
+ }
280
+
281
+ return (
282
+ <IconButton
283
+ classNames={mx('self-center', classNames)}
284
+ square
285
+ variant='ghost'
286
+ icon='ph--caret-right--regular'
287
+ iconOnly
288
+ label={t('carousel-next.label')}
289
+ onClick={next}
290
+ />
291
+ );
292
+ };
293
+
294
+ CarouselNext.displayName = 'Carousel.Next';
295
+
296
+ //
297
+ // Indicators
298
+ //
299
+
300
+ export type CarouselIndicatorsProps = ThemedClassName<{}>;
301
+
302
+ /** Tab-strip of slide indicators. Sits in the centre column so it matches the viewport's width. */
303
+ const CarouselIndicators = ({ classNames }: CarouselIndicatorsProps) => {
304
+ const { t } = useTranslation(translationKey);
305
+ const { count, index, setIndex } = useCarousel();
306
+ const arrowNavigationAttrs = useArrowNavigationGroup({ axis: 'horizontal', memorizeCurrent: true });
307
+ if (count <= 1) {
308
+ return null;
309
+ }
310
+
311
+ return (
312
+ <div className='col-start-2 overflow-hidden'>
313
+ <div
314
+ {...arrowNavigationAttrs}
315
+ className={mx('flex items-center justify-center', classNames)}
316
+ role='tablist'
317
+ aria-label={t('carousel-indicators.label')}
318
+ >
319
+ {Array.from({ length: count }).map((_, i) => (
320
+ <IconButton
321
+ key={i}
322
+ role='tab'
323
+ aria-selected={i === index}
324
+ classNames={i === index ? 'text-primary-500' : 'text-description'}
325
+ icon={i === index ? 'ph--circle--fill' : 'ph--circle--regular'}
326
+ iconOnly
327
+ label={t('carousel-go-to.label', { index: i + 1 })}
328
+ onClick={() => setIndex(i)}
329
+ onFocus={() => setIndex(i)}
330
+ size={3}
331
+ variant='ghost'
332
+ />
333
+ ))}
334
+ </div>
335
+ </div>
336
+ );
337
+ };
338
+
339
+ CarouselIndicators.displayName = 'Carousel.Indicators';
340
+
341
+ //
342
+ // Caption
343
+ //
344
+
345
+ export type CarouselCaptionProps = ThemedClassName<{
346
+ /** Render prop receiving the active slide index. */
347
+ children: (index: number) => ReactNode;
348
+ }>;
349
+
350
+ /** Caption sized to the viewport's column. */
351
+ const CarouselCaption = ({ children, classNames }: CarouselCaptionProps) => {
352
+ const { index } = useCarousel();
353
+ const content = children(index);
354
+ if (content == null || content === false || content === '') {
355
+ return null;
356
+ }
357
+ return (
358
+ // TODO(burdon): Move to ui-theme.
359
+ <div className='col-start-2'>
360
+ <p className={mx('text-center text-description', classNames)}>{content}</p>
361
+ </div>
362
+ );
363
+ };
364
+
365
+ CarouselCaption.displayName = 'Carousel.Caption';
366
+
367
+ //
368
+ // Carousel
369
+ //
370
+
371
+ export const Carousel = {
372
+ Root: CarouselRoot,
373
+ Viewport: CarouselViewport,
374
+ Slide: CarouselSlide,
375
+ Previous: CarouselPrevious,
376
+ Next: CarouselNext,
377
+ Indicators: CarouselIndicators,
378
+ Caption: CarouselCaption,
379
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './Carousel';
@@ -10,7 +10,6 @@ import { Button, type ButtonProps, IconButton } from '../Button';
10
10
  import { Icon, type IconProps } from '../Icon';
11
11
  import { useTranslation } from '../ThemeProvider';
12
12
  import { type TooltipScopedProps, useTooltipContext } from '../Tooltip';
13
-
14
13
  import { useClipboard } from './ClipboardProvider';
15
14
 
16
15
  export type CopyButtonProps = ButtonProps &
@@ -31,12 +30,12 @@ export const CopyButton = ({ classNames, value, size = 5, ...props }: CopyButton
31
30
  onClick={() => setTextValue(value)}
32
31
  data-testid='copy-invitation'
33
32
  >
34
- <div role='none' className={mx('flex gap-1 items-center', isCopied && inactiveLabelStyles)}>
35
- <span className='px-1'>{t('copy label')}</span>
33
+ <div className={mx('flex gap-1 items-center', isCopied && inactiveLabelStyles)}>
34
+ <span className='px-1'>{t('copy.label')}</span>
36
35
  <Icon icon='ph--copy--regular' size={size} />
37
36
  </div>
38
- <div role='none' className={mx('flex gap-1 items-center', !isCopied && inactiveLabelStyles)}>
39
- <span className='px-1'>{t('copy success label')}</span>
37
+ <div className={mx('flex gap-1 items-center', !isCopied && inactiveLabelStyles)}>
38
+ <span className='px-1'>{t('copy-success.label')}</span>
40
39
  <Icon icon='ph--check--regular' size={size} />
41
40
  </div>
42
41
  </Button>
@@ -58,7 +57,7 @@ export const CopyButtonIconOnly = ({
58
57
  const { t } = useTranslation(osTranslations);
59
58
  const { textValue, setTextValue } = useClipboard();
60
59
  const isCopied = textValue === value;
61
- const label = isCopied ? t('copy success label') : (props.label ?? t('copy label'));
60
+ const label = isCopied ? t('copy-success.label') : (props.label ?? t('copy.label'));
62
61
  const { onOpen } = useTooltipContext('CopyButton', __scopeTooltip);
63
62
  return (
64
63
  <IconButton
@@ -5,14 +5,13 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React from 'react';
7
7
 
8
- import { faker } from '@dxos/random';
8
+ import { random } from '@dxos/random';
9
9
 
10
10
  import { withTheme } from '../../testing';
11
11
  import { Button } from '../Button';
12
-
13
12
  import { AlertDialog } from './AlertDialog';
14
13
 
15
- type StoryProps = Partial<{
14
+ type DefaultStoryProps = Partial<{
16
15
  title: string;
17
16
  description: string;
18
17
  openTrigger: string;
@@ -20,7 +19,7 @@ type StoryProps = Partial<{
20
19
  actionTrigger: string;
21
20
  }>;
22
21
 
23
- const DefaultStory = ({ title, description, openTrigger, cancelTrigger, actionTrigger }: StoryProps) => {
22
+ const DefaultStory = ({ title, description, openTrigger, cancelTrigger, actionTrigger }: DefaultStoryProps) => {
24
23
  return (
25
24
  <AlertDialog.Root defaultOpen>
26
25
  <AlertDialog.Trigger asChild>
@@ -60,8 +59,8 @@ type Story = StoryObj<typeof meta>;
60
59
 
61
60
  export const Default: Story = {
62
61
  args: {
63
- title: faker.lorem.sentence(3),
64
- description: faker.lorem.paragraph(1),
62
+ title: random.lorem.sentence(3),
63
+ description: random.lorem.paragraph(1),
65
64
  openTrigger: 'Open AlertDialog',
66
65
  cancelTrigger: 'Cancel',
67
66
  actionTrigger: 'Action',
@@ -4,12 +4,7 @@
4
4
 
5
5
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
6
6
  import { createContext } from '@radix-ui/react-context';
7
- import React, {
8
- type ForwardRefExoticComponent,
9
- type FunctionComponent,
10
- type PropsWithChildren,
11
- forwardRef,
12
- } from 'react';
7
+ import React, { type ForwardRefExoticComponent, type FunctionComponent, forwardRef } from 'react';
13
8
 
14
9
  import { type DialogSize } from '@dxos/ui-theme';
15
10
 
@@ -17,6 +12,13 @@ import { useThemeContext } from '../../hooks';
17
12
  import { Column } from '../../primitives';
18
13
  import { type ThemedClassName } from '../../util';
19
14
  import { ElevationProvider } from '../ElevationProvider';
15
+ import {
16
+ Dialog,
17
+ type DialogHeaderProps,
18
+ type DialogBodyProps,
19
+ type DialogActionBarProps,
20
+ type DialogCloseIconButtonProps,
21
+ } from './Dialog';
20
22
 
21
23
  //
22
24
  // Root
@@ -63,68 +65,26 @@ type AlertDialogActionProps = AlertDialogPrimitive.AlertDialogActionProps;
63
65
  const AlertDialogAction: FunctionComponent<AlertDialogActionProps> = AlertDialogPrimitive.Action;
64
66
 
65
67
  //
66
- // Title
67
- //
68
-
69
- type AlertDialogTitleProps = ThemedClassName<AlertDialogPrimitive.AlertDialogTitleProps> & { srOnly?: boolean };
70
-
71
- const AlertDialogTitle: ForwardRefExoticComponent<AlertDialogTitleProps> = forwardRef<
72
- HTMLHeadingElement,
73
- AlertDialogTitleProps
74
- >(({ classNames, srOnly, ...props }, forwardedRef) => {
75
- const { tx } = useThemeContext();
76
- return (
77
- <AlertDialogPrimitive.Title {...props} className={tx('dialog.title', { srOnly }, classNames)} ref={forwardedRef} />
78
- );
79
- });
80
-
81
- //
82
- // Description
68
+ // Context
83
69
  //
84
70
 
85
- type AlertDialogDescriptionProps = ThemedClassName<AlertDialogPrimitive.AlertDialogDescriptionProps> & {
86
- srOnly?: boolean;
87
- };
88
-
89
- const AlertDialogDescription: ForwardRefExoticComponent<AlertDialogTitleProps> = forwardRef<
90
- HTMLParagraphElement,
91
- AlertDialogDescriptionProps
92
- >(({ classNames, srOnly, ...props }, forwardedRef) => {
93
- const { tx } = useThemeContext();
94
- return (
95
- <AlertDialogPrimitive.Description
96
- {...props}
97
- className={tx('dialog.description', { srOnly }, classNames)}
98
- ref={forwardedRef}
99
- />
100
- );
101
- });
102
-
103
71
  type OverlayLayoutContextValue = { inOverlayLayout?: boolean };
104
72
 
105
- //
106
- // Context
107
- //
108
-
109
73
  const ALERT_DIALOG_OVERLAY_NAME = 'AlertDialogOverlay';
110
74
  const ALERT_DIALOG_CONTENT_NAME = 'AlertDialogContent';
111
- const ALERT_DIALOG_BODY_NAME = 'AlertDialogBody';
112
- const ALERT_DIALOG_ACTIONBAR_NAME = 'AlertDialogActionBar';
113
75
 
114
76
  const [OverlayLayoutProvider, useOverlayLayoutContext] = createContext<OverlayLayoutContextValue>(
115
77
  ALERT_DIALOG_OVERLAY_NAME,
116
- {
117
- inOverlayLayout: false,
118
- },
78
+ { inOverlayLayout: false },
119
79
  );
120
80
 
121
81
  //
122
82
  // Overlay
123
83
  //
124
84
 
125
- type AlertDialogOverlayProps = ThemedClassName<AlertDialogPrimitive.AlertDialogOverlayProps> & {
126
- blockAlign?: 'center' | 'start' | 'end';
127
- };
85
+ type AlertDialogOverlayProps = ThemedClassName<
86
+ AlertDialogPrimitive.AlertDialogOverlayProps & { blockAlign?: 'center' | 'start' | 'end' }
87
+ >;
128
88
 
129
89
  const AlertDialogOverlay: ForwardRefExoticComponent<AlertDialogOverlayProps> = forwardRef<
130
90
  HTMLDivElement,
@@ -135,15 +95,7 @@ const AlertDialogOverlay: ForwardRefExoticComponent<AlertDialogOverlayProps> = f
135
95
  <AlertDialogPrimitive.Overlay
136
96
  {...props}
137
97
  data-block-align={blockAlign}
138
- className={tx(
139
- 'dialog.overlay',
140
- {},
141
- classNames,
142
- // TODO(burdon): Move to dialog.ts.
143
- 'data-[h-align=start]:justify-center',
144
- 'data-[h-align=start]:items-start',
145
- 'data-[h-align=center]:place-content-center',
146
- )}
98
+ className={tx('dialog.overlay', {}, classNames)}
147
99
  ref={forwardedRef}
148
100
  >
149
101
  <OverlayLayoutProvider inOverlayLayout>{children}</OverlayLayoutProvider>
@@ -169,9 +121,14 @@ const AlertDialogContent: ForwardRefExoticComponent<AlertDialogContentProps> = f
169
121
  <AlertDialogPrimitive.Content
170
122
  {...props}
171
123
  className={tx('dialog.content', { inOverlayLayout, size }, classNames)}
124
+ // NOTE: Radix warning unless set to undefined.
125
+ // https://www.radix-ui.com/primitives/docs/components/dialog#description
126
+ aria-describedby={undefined}
172
127
  ref={forwardedRef}
173
128
  >
174
- <Column.Root>{children}</Column.Root>
129
+ <Column.Root classNames='dx-expander' gutter='sm'>
130
+ {children}
131
+ </Column.Root>
175
132
  </AlertDialogPrimitive.Content>
176
133
  );
177
134
  });
@@ -179,49 +136,43 @@ const AlertDialogContent: ForwardRefExoticComponent<AlertDialogContentProps> = f
179
136
  AlertDialogContent.displayName = ALERT_DIALOG_CONTENT_NAME;
180
137
 
181
138
  //
182
- // Body
139
+ // Title
183
140
  //
184
141
 
185
- type AlertDialogBodyProps = PropsWithChildren;
142
+ type AlertDialogTitleProps = ThemedClassName<AlertDialogPrimitive.AlertDialogTitleProps> & { srOnly?: boolean };
186
143
 
187
- const AlertDialogBody: ForwardRefExoticComponent<AlertDialogBodyProps> = forwardRef<
188
- HTMLDivElement,
189
- AlertDialogBodyProps
190
- >(({ children, ...props }, forwardedRef) => {
144
+ const AlertDialogTitle: ForwardRefExoticComponent<AlertDialogTitleProps> = forwardRef<
145
+ HTMLHeadingElement,
146
+ AlertDialogTitleProps
147
+ >(({ classNames, srOnly, ...props }, forwardedRef) => {
191
148
  const { tx } = useThemeContext();
192
149
  return (
193
- <Column.Segment asChild>
194
- <div role='none' {...props} className={tx('dialog.body')} ref={forwardedRef}>
195
- {children}
196
- </div>
197
- </Column.Segment>
150
+ <AlertDialogPrimitive.Title {...props} className={tx('dialog.title', { srOnly }, classNames)} ref={forwardedRef} />
198
151
  );
199
152
  });
200
153
 
201
- AlertDialogBody.displayName = ALERT_DIALOG_BODY_NAME;
202
-
203
154
  //
204
- // ActionBar
155
+ // Description
205
156
  //
206
157
 
207
- type AlertDialogActionBarProps = ThemedClassName<PropsWithChildren>;
158
+ type AlertDialogDescriptionProps = ThemedClassName<AlertDialogPrimitive.AlertDialogDescriptionProps> & {
159
+ srOnly?: boolean;
160
+ };
208
161
 
209
- const AlertDialogActionBar: ForwardRefExoticComponent<AlertDialogActionBarProps> = forwardRef<
210
- HTMLDivElement,
211
- AlertDialogActionBarProps
212
- >(({ children, classNames, ...props }, forwardedRef) => {
162
+ const AlertDialogDescription: ForwardRefExoticComponent<AlertDialogDescriptionProps> = forwardRef<
163
+ HTMLParagraphElement,
164
+ AlertDialogDescriptionProps
165
+ >(({ classNames, srOnly, ...props }, forwardedRef) => {
213
166
  const { tx } = useThemeContext();
214
167
  return (
215
- <Column.Segment asChild>
216
- <div {...props} className={tx('dialog.actionbar', {}, classNames)} ref={forwardedRef}>
217
- {children}
218
- </div>
219
- </Column.Segment>
168
+ <AlertDialogPrimitive.Description
169
+ {...props}
170
+ className={tx('dialog.description', { srOnly }, classNames)}
171
+ ref={forwardedRef}
172
+ />
220
173
  );
221
174
  });
222
175
 
223
- AlertDialogActionBar.displayName = ALERT_DIALOG_ACTIONBAR_NAME;
224
-
225
176
  //
226
177
  // AlertDialog
227
178
  //
@@ -232,10 +183,14 @@ export const AlertDialog = {
232
183
  Portal: AlertDialogPortal,
233
184
  Overlay: AlertDialogOverlay,
234
185
  Content: AlertDialogContent,
235
- Body: AlertDialogBody,
186
+ // Shared with Dialog.
187
+ Header: Dialog.Header,
188
+ Body: Dialog.Body,
236
189
  Title: AlertDialogTitle,
237
190
  Description: AlertDialogDescription,
238
- ActionBar: AlertDialogActionBar,
191
+ ActionBar: Dialog.ActionBar,
192
+ CloseIconButton: Dialog.CloseIconButton,
193
+ // AlertDialog-specific dismissal.
239
194
  Cancel: AlertDialogCancel,
240
195
  Action: AlertDialogAction,
241
196
  };
@@ -246,10 +201,13 @@ export type {
246
201
  AlertDialogPortalProps,
247
202
  AlertDialogOverlayProps,
248
203
  AlertDialogContentProps,
249
- AlertDialogBodyProps,
250
204
  AlertDialogTitleProps,
251
205
  AlertDialogDescriptionProps,
252
- AlertDialogActionBarProps,
253
206
  AlertDialogCancelProps,
254
207
  AlertDialogActionProps,
208
+ // Re-export shared types.
209
+ DialogHeaderProps as AlertDialogHeaderProps,
210
+ DialogBodyProps as AlertDialogBodyProps,
211
+ DialogActionBarProps as AlertDialogActionBarProps,
212
+ DialogCloseIconButtonProps as AlertDialogCloseIconButtonProps,
255
213
  };