@dxos/react-ui 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963

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 (301) hide show
  1. package/dist/lib/browser/{chunk-2FKSMWNY.mjs → chunk-BDBC6H6V.mjs} +79 -5
  2. package/dist/lib/browser/chunk-BDBC6H6V.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1203 -1020
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +44 -14
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/browser/translations.mjs +18 -0
  9. package/dist/lib/browser/translations.mjs.map +7 -0
  10. package/dist/lib/node-esm/{chunk-ZNBLTSHI.mjs → chunk-3JSJK2ZY.mjs} +79 -5
  11. package/dist/lib/node-esm/chunk-3JSJK2ZY.mjs.map +7 -0
  12. package/dist/lib/node-esm/index.mjs +1203 -1020
  13. package/dist/lib/node-esm/index.mjs.map +4 -4
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/testing/index.mjs +44 -14
  16. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/translations.mjs +20 -0
  18. package/dist/lib/node-esm/translations.mjs.map +7 -0
  19. package/dist/types/src/components/Avatars/Avatar.d.ts +1 -1
  20. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  21. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  24. package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Button/Button.d.ts +2 -2
  26. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  27. package/dist/types/src/components/Button/Button.stories.d.ts +1 -1
  28. package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Button/IconButton.d.ts +1 -0
  30. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  31. package/dist/types/src/components/Button/IconButton.stories.d.ts +3 -0
  32. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/Button/Toggle.d.ts +2 -2
  34. package/dist/types/src/components/Button/Toggle.d.ts.map +1 -1
  35. package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Button/ToggleGroup.d.ts +6 -6
  37. package/dist/types/src/components/Button/ToggleGroup.d.ts.map +1 -1
  38. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts +2 -2
  39. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -1
  40. package/dist/types/src/components/Card/Card.d.ts +70 -64
  41. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  42. package/dist/types/src/components/Card/Card.stories.d.ts +2 -2
  43. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  45. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  46. package/dist/types/src/components/Clipboard/index.d.ts +10 -1
  47. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  48. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  49. package/dist/types/src/components/Dialog/AlertDialog.d.ts +42 -31
  50. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  51. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/Dialog/Dialog.d.ts +47 -30
  53. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  54. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +3 -2
  55. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  56. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  57. package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts.map +1 -1
  58. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +14 -3
  60. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
  61. package/dist/types/src/components/ErrorFallback/ThrowError.d.ts.map +1 -1
  62. package/dist/types/src/components/Focus/Focus.d.ts +36 -0
  63. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -0
  64. package/dist/types/src/components/Focus/Focus.stories.d.ts +9 -0
  65. package/dist/types/src/components/Focus/Focus.stories.d.ts.map +1 -0
  66. package/dist/types/src/components/Focus/index.d.ts +2 -0
  67. package/dist/types/src/components/Focus/index.d.ts.map +1 -0
  68. package/dist/types/src/components/Icon/Icon.d.ts +3 -0
  69. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  70. package/dist/types/src/components/Icon/Icon.stories.d.ts +11 -3
  71. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -1
  72. package/dist/types/src/components/Image/Image.d.ts +2 -1
  73. package/dist/types/src/components/Image/Image.d.ts.map +1 -1
  74. package/dist/types/src/components/Image/Image.stories.d.ts +3 -2
  75. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/Input/Input.d.ts +14 -17
  77. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  78. package/dist/types/src/components/Input/Input.stories.d.ts +3 -3
  79. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  80. package/dist/types/src/components/Link/Link.stories.d.ts.map +1 -1
  81. package/dist/types/src/components/List/List.d.ts +5 -3
  82. package/dist/types/src/components/List/List.d.ts.map +1 -1
  83. package/dist/types/src/components/List/List.stories.d.ts +3 -1
  84. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  85. package/dist/types/src/components/List/ListDropIndicator.d.ts.map +1 -1
  86. package/dist/types/src/components/List/Tree.d.ts +2 -2
  87. package/dist/types/src/components/List/Tree.d.ts.map +1 -1
  88. package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -1
  89. package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +1 -1
  90. package/dist/types/src/components/List/Treegrid.d.ts +5 -9
  91. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
  92. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -1
  93. package/dist/types/src/components/Main/Main.d.ts +7 -3
  94. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  95. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  96. package/dist/types/src/components/Main/useSwipeToDismiss.d.ts.map +1 -1
  97. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
  98. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -1
  99. package/dist/types/src/components/Menu/DropdownMenu.d.ts +58 -49
  100. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  101. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts +14 -1
  102. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/Message/Message.d.ts +1 -1
  104. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  105. package/dist/types/src/components/Message/Message.stories.d.ts +2 -2
  106. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  107. package/dist/types/src/components/Popover/Popover.d.ts +38 -22
  108. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  109. package/dist/types/src/components/Popover/Popover.stories.d.ts.map +1 -1
  110. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +12 -11
  111. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  112. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +21 -10
  113. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  114. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +42 -13
  115. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  116. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +5 -6
  117. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  118. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  119. package/dist/types/src/components/Select/Select.stories.d.ts +2 -2
  120. package/dist/types/src/components/Select/Select.stories.d.ts.map +1 -1
  121. package/dist/types/src/components/Separator/Separator.d.ts +3 -3
  122. package/dist/types/src/components/Separator/Separator.d.ts.map +1 -1
  123. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -1
  124. package/dist/types/src/components/Splitter/Splitter.d.ts +19 -21
  125. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -1
  126. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -1
  127. package/dist/types/src/components/Status/Status.d.ts +3 -4
  128. package/dist/types/src/components/Status/Status.d.ts.map +1 -1
  129. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  130. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  131. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -1
  132. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  133. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts +1 -1
  134. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  135. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +54 -55
  136. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  137. package/dist/types/src/components/ThemeProvider/index.d.ts +1 -1
  138. package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
  139. package/dist/types/src/components/Toast/Toast.d.ts +16 -16
  140. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  141. package/dist/types/src/components/Toast/Toast.stories.d.ts.map +1 -1
  142. package/dist/types/src/components/Toolbar/Toolbar.d.ts +10 -20
  143. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  144. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  145. package/dist/types/src/components/Tooltip/Tooltip.d.ts +10 -10
  146. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  147. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +2 -2
  148. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  149. package/dist/types/src/components/index.d.ts +1 -0
  150. package/dist/types/src/components/index.d.ts.map +1 -1
  151. package/dist/types/src/exemplars/generics.stories.d.ts +6 -5
  152. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -1
  153. package/dist/types/src/exemplars/slot.stories.d.ts +1 -0
  154. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -1
  155. package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -1
  156. package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -1
  157. package/dist/types/src/hooks/index.d.ts +1 -0
  158. package/dist/types/src/hooks/index.d.ts.map +1 -1
  159. package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
  160. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  161. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  162. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  163. package/dist/types/src/hooks/useSafeArea.d.ts.map +1 -1
  164. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -1
  165. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  166. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  167. package/dist/types/src/playground/Custom.stories.d.ts +1 -1
  168. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
  169. package/dist/types/src/playground/Typography.stories.d.ts.map +1 -1
  170. package/dist/types/src/primitives/Column/Column.d.ts +20 -19
  171. package/dist/types/src/primitives/Column/Column.d.ts.map +1 -1
  172. package/dist/types/src/primitives/Column/Column.stories.d.ts +19 -0
  173. package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -1
  174. package/dist/types/src/primitives/Container/Container.d.ts +7 -0
  175. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -0
  176. package/dist/types/src/primitives/Container/Container.stories.d.ts +6 -0
  177. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -0
  178. package/dist/types/src/primitives/Container/index.d.ts +2 -0
  179. package/dist/types/src/primitives/Container/index.d.ts.map +1 -0
  180. package/dist/types/src/primitives/Flex/Flex.d.ts +8 -5
  181. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -1
  182. package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -1
  183. package/dist/types/src/primitives/Grid/Grid.d.ts +6 -5
  184. package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -1
  185. package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -1
  186. package/dist/types/src/primitives/Panel/Panel.d.ts +23 -22
  187. package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -1
  188. package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -1
  189. package/dist/types/src/primitives/index.d.ts +1 -0
  190. package/dist/types/src/primitives/index.d.ts.map +1 -1
  191. package/dist/types/src/testing/Loading.d.ts +9 -0
  192. package/dist/types/src/testing/Loading.d.ts.map +1 -0
  193. package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
  194. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
  195. package/dist/types/src/testing/decorators/withTheme.d.ts +1 -1
  196. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  197. package/dist/types/src/testing/index.d.ts +1 -0
  198. package/dist/types/src/testing/index.d.ts.map +1 -1
  199. package/dist/types/src/translations.d.ts +3 -3
  200. package/dist/types/src/translations.d.ts.map +1 -1
  201. package/dist/types/src/util/usePx.d.ts.map +1 -1
  202. package/dist/types/tsconfig.tsbuildinfo +1 -1
  203. package/package.json +28 -25
  204. package/src/components/Avatars/Avatar.stories.tsx +2 -3
  205. package/src/components/Avatars/Avatar.tsx +1 -2
  206. package/src/components/Avatars/AvatarGroup.stories.tsx +0 -1
  207. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -2
  208. package/src/components/Button/Button.stories.tsx +0 -1
  209. package/src/components/Button/Button.tsx +5 -13
  210. package/src/components/Button/IconButton.stories.tsx +6 -4
  211. package/src/components/Button/IconButton.tsx +3 -4
  212. package/src/components/Button/Toggle.stories.tsx +0 -1
  213. package/src/components/Button/Toggle.tsx +4 -4
  214. package/src/components/Button/ToggleGroup.stories.tsx +0 -1
  215. package/src/components/Button/ToggleGroup.tsx +12 -16
  216. package/src/components/Card/Card.stories.tsx +12 -12
  217. package/src/components/Card/Card.tsx +283 -128
  218. package/src/components/Clipboard/CopyButton.tsx +3 -4
  219. package/src/components/Dialog/AlertDialog.stories.tsx +5 -6
  220. package/src/components/Dialog/AlertDialog.tsx +67 -126
  221. package/src/components/Dialog/Dialog.stories.tsx +64 -9
  222. package/src/components/Dialog/Dialog.tsx +84 -88
  223. package/src/components/ErrorFallback/ErrorFallback.stories.tsx +3 -8
  224. package/src/components/ErrorFallback/ErrorStack.tsx +36 -2
  225. package/src/components/Focus/AUDIT.md +43 -0
  226. package/src/components/Focus/Focus.stories.tsx +230 -0
  227. package/src/components/Focus/Focus.tsx +201 -0
  228. package/src/components/Focus/index.ts +5 -0
  229. package/src/components/Icon/Icon.stories.tsx +43 -13
  230. package/src/components/Icon/Icon.tsx +5 -1
  231. package/src/components/Image/Image.stories.tsx +3 -3
  232. package/src/components/Image/Image.tsx +31 -8
  233. package/src/components/Input/Input.stories.tsx +3 -4
  234. package/src/components/Input/Input.tsx +7 -7
  235. package/src/components/Link/Link.stories.tsx +0 -1
  236. package/src/components/List/List.stories.tsx +2 -3
  237. package/src/components/List/List.tsx +6 -5
  238. package/src/components/List/Tree.stories.tsx +1 -2
  239. package/src/components/List/Tree.tsx +0 -1
  240. package/src/components/List/TreeDropIndicator.tsx +1 -1
  241. package/src/components/List/Treegrid.stories.tsx +26 -27
  242. package/src/components/List/Treegrid.tsx +14 -14
  243. package/src/components/Main/Main.stories.tsx +0 -1
  244. package/src/components/Main/Main.tsx +1 -2
  245. package/src/components/Menu/ContextMenu.stories.tsx +0 -1
  246. package/src/components/Menu/DropdownMenu.stories.tsx +0 -1
  247. package/src/components/Menu/DropdownMenu.tsx +48 -42
  248. package/src/components/Message/Message.stories.tsx +7 -8
  249. package/src/components/Message/Message.tsx +23 -10
  250. package/src/components/Popover/Popover.stories.tsx +4 -5
  251. package/src/components/Popover/Popover.tsx +42 -42
  252. package/src/components/ScrollArea/ScrollArea.stories.tsx +93 -30
  253. package/src/components/ScrollArea/ScrollArea.tsx +41 -25
  254. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +20 -18
  255. package/src/components/ScrollContainer/ScrollContainer.tsx +200 -91
  256. package/src/components/Select/Select.stories.tsx +5 -6
  257. package/src/components/Separator/Separator.tsx +4 -7
  258. package/src/components/Skeleton/Skeleton.stories.tsx +0 -1
  259. package/src/components/Splitter/Splitter.stories.tsx +29 -29
  260. package/src/components/Splitter/Splitter.tsx +35 -46
  261. package/src/components/Status/Status.stories.tsx +0 -1
  262. package/src/components/Status/Status.tsx +8 -5
  263. package/src/components/Tag/Tag.stories.tsx +0 -1
  264. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +0 -1
  265. package/src/components/ThemeProvider/ThemeProvider.tsx +5 -4
  266. package/src/components/ThemeProvider/index.ts +1 -1
  267. package/src/components/Toast/Toast.stories.tsx +0 -1
  268. package/src/components/Toast/Toast.tsx +16 -31
  269. package/src/components/Toolbar/Toolbar.stories.tsx +0 -1
  270. package/src/components/Toolbar/Toolbar.tsx +34 -47
  271. package/src/components/Tooltip/Tooltip.stories.tsx +6 -7
  272. package/src/components/Tooltip/Tooltip.tsx +15 -16
  273. package/src/components/index.ts +1 -0
  274. package/src/exemplars/generics.stories.tsx +7 -15
  275. package/src/exemplars/slot.stories.tsx +66 -68
  276. package/src/exemplars/tabster.stories.tsx +1 -1
  277. package/src/exemplars/virtualizer.stories.tsx +4 -4
  278. package/src/hooks/index.ts +1 -0
  279. package/src/hooks/useDensityContext.ts +2 -2
  280. package/src/playground/Custom.stories.tsx +6 -9
  281. package/src/primitives/Column/AUDIT.md +148 -0
  282. package/src/primitives/Column/Column.stories.tsx +128 -19
  283. package/src/primitives/Column/Column.tsx +89 -80
  284. package/src/primitives/Container/Container.stories.tsx +29 -0
  285. package/src/primitives/Container/Container.tsx +19 -0
  286. package/src/primitives/Container/index.ts +5 -0
  287. package/src/primitives/Flex/Flex.stories.tsx +0 -1
  288. package/src/primitives/Flex/Flex.tsx +20 -20
  289. package/src/primitives/Grid/Grid.stories.tsx +0 -1
  290. package/src/primitives/Grid/Grid.tsx +23 -36
  291. package/src/primitives/Panel/Panel.stories.tsx +9 -8
  292. package/src/primitives/Panel/Panel.tsx +43 -60
  293. package/src/primitives/index.ts +1 -0
  294. package/src/testing/Loading.tsx +47 -0
  295. package/src/testing/decorators/withLayout.tsx +6 -6
  296. package/src/testing/decorators/withTheme.tsx +10 -7
  297. package/src/testing/index.ts +2 -0
  298. package/src/translations.ts +3 -3
  299. package/src/util/usePx.ts +1 -0
  300. package/dist/lib/browser/chunk-2FKSMWNY.mjs.map +0 -7
  301. package/dist/lib/node-esm/chunk-ZNBLTSHI.mjs.map +0 -7
@@ -3,13 +3,16 @@
3
3
  //
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
- import React, { type ReactElement, type Ref, forwardRef } from 'react';
6
+ import React from 'react';
7
7
 
8
- import { type SlottableProps } from '@dxos/ui-types';
8
+ import { slottable } from '@dxos/ui-theme';
9
9
 
10
10
  import { withTheme } from '../testing';
11
11
 
12
- const ComponentInner = forwardRef<HTMLDivElement, ComponentProps>(({ children, ...props }, forwardedRef) => {
12
+ /**
13
+ * Generic component pattern using the slottable factory.
14
+ */
15
+ const Component = slottable<HTMLDivElement>(({ children, ...props }, forwardedRef) => {
13
16
  return (
14
17
  <div {...props} ref={forwardedRef}>
15
18
  {children}
@@ -17,21 +20,10 @@ const ComponentInner = forwardRef<HTMLDivElement, ComponentProps>(({ children, .
17
20
  );
18
21
  });
19
22
 
20
- ComponentInner.displayName = 'Component';
21
-
22
- /**
23
- * Generic component pattern.
24
- */
25
- type ComponentProps<P extends HTMLElement = any> = SlottableProps<P>;
26
-
27
- const Component = ComponentInner as <P extends HTMLElement>(
28
- props: SlottableProps<P> & { ref?: Ref<P> },
29
- ) => ReactElement;
30
-
31
23
  const meta = {
32
24
  title: 'ui/react-ui-core/exemplars/generics',
33
25
  component: Component,
34
- render: (props) => <Component<HTMLDivElement> {...props} />,
26
+ render: (props) => <Component {...props} />,
35
27
  decorators: [withTheme()],
36
28
  parameters: {
37
29
  layout: 'centered',
@@ -5,94 +5,64 @@
5
5
  import { Primitive } from '@radix-ui/react-primitive';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
7
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
- import React, { type PropsWithChildren, forwardRef } from 'react';
8
+ import React, { PropsWithChildren } from 'react';
9
9
 
10
- import { useComposableProps } from '@dxos/ui-theme';
11
- import { type ComposableProps, type SlottableProps, type ThemedClassName } from '@dxos/ui-types';
10
+ import { composable, composableProps, mx, slottable } from '@dxos/ui-theme';
12
11
 
13
12
  import { withTheme } from '../testing';
13
+ import { ThemedClassName } from '../util';
14
14
 
15
15
  /**
16
- * Composition
17
- *
16
+ * Radix-style composition.
18
17
  * All Radix primitive parts that render a DOM element accept an asChild prop.
19
- * When asChild is set to true, Radix will not render a default DOM element, instead cloning the part's child and passing it the props and behavior required to make it functional.
18
+ * When asChild is set to true, Radix will not render a default DOM element,
19
+ * instead cloning the part's child and passing it the props and behavior required to make it functional.
20
20
  * https://www.radix-ui.com/primitives/docs/guides/composition
21
21
  */
22
22
 
23
- // Outer primitive (like Tooltip.Trigger or Focus.Group).
24
- const Outer = forwardRef<HTMLDivElement, SlottableProps<HTMLDivElement>>(
25
- ({ children, asChild, ...props }, forwardedRef) => {
26
- const { className, ...rest } = useComposableProps(props);
23
+ const Outer = slottable<HTMLDivElement, { priority?: number }>(
24
+ ({ children, asChild, priority, ...props }, forwardedRef) => {
27
25
  const Comp = asChild ? Slot : Primitive.div;
28
26
  return (
29
- <Comp {...rest} className={className} data-outer='true' ref={forwardedRef}>
27
+ <Comp
28
+ {...composableProps<HTMLDivElement>(props, { classNames: 'p-2 border border-red-500 rounded' })}
29
+ ref={forwardedRef}
30
+ >
30
31
  {children}
31
32
  </Comp>
32
33
  );
33
34
  },
34
35
  );
35
36
 
36
- // Middle primitive (like Dialog.Trigger or Mosaic.Cell).
37
- const Middle = forwardRef<HTMLDivElement, SlottableProps<HTMLDivElement>>(
38
- ({ children, asChild, ...props }, forwardedRef) => {
39
- const { className, ...rest } = useComposableProps(props);
40
- const Comp = asChild ? Slot : Primitive.div;
41
- return (
42
- <Comp {...rest} className={className} data-middle='true' ref={forwardedRef}>
43
- {children}
44
- </Comp>
45
- );
46
- },
47
- );
48
-
49
- // Leaf component (like Card.Root).
50
- const Leaf = forwardRef<HTMLButtonElement, ComposableProps<PropsWithChildren>>(
51
- ({ children, ...props }, forwardedRef) => {
52
- const { className, ...rest } = useComposableProps(props);
53
- return (
54
- <button {...rest} className={className} ref={forwardedRef}>
55
- {children}
56
- </button>
57
- );
58
- },
59
- );
60
-
61
- // Test 1: Single asChild.
62
- const TestSingle = (props: ThemedClassName<{ role?: string }>) => {
63
- const { className, ...rest } = useComposableProps(props);
37
+ const Middle = slottable<HTMLDivElement>(({ children, asChild, ...props }, forwardedRef) => {
38
+ const Comp = asChild ? Slot : Primitive.div;
64
39
  return (
65
- <Outer asChild {...rest} className={className}>
66
- <Leaf>Single asChild</Leaf>
67
- </Outer>
40
+ <Comp
41
+ {...composableProps<HTMLDivElement>(props, { classNames: 'p-2 border border-red-500 rounded' })}
42
+ ref={forwardedRef}
43
+ >
44
+ {children}
45
+ </Comp>
68
46
  );
69
- };
47
+ });
70
48
 
71
- // Test 2: Nested asChild.
72
- const TestNested = (props: ThemedClassName<{ role?: string }>) => {
73
- const { className, ...rest } = useComposableProps(props);
49
+ const Leaf = composable<HTMLButtonElement>(({ children, ...props }, forwardedRef) => {
74
50
  return (
75
- <Outer asChild {...rest} className={className}>
76
- <Middle asChild>
77
- <Leaf>Nested asChild</Leaf>
78
- </Middle>
79
- </Outer>
51
+ <button
52
+ {...composableProps<HTMLButtonElement>(props, { classNames: 'p-2 border border-red-500 rounded' })}
53
+ ref={forwardedRef}
54
+ >
55
+ {children}
56
+ </button>
80
57
  );
81
- };
58
+ });
82
59
 
83
- // Test 3: Complex.
84
- const TestInner = (props: ThemedClassName<{ role?: string }>) => {
85
- const { className, ...rest } = useComposableProps(props);
86
- return (
87
- <Outer asChild {...rest} className={className}>
88
- <Middle asChild>
89
- <Leaf>
90
- <div role='none'>Leaf</div>
91
- </Leaf>
92
- </Middle>
93
- </Outer>
94
- );
95
- };
60
+ /** This isn't a valid child for a `slottable` component. */
61
+ const Simple = ({ children, classNames }: ThemedClassName<PropsWithChildren>) => (
62
+ <div role='none' className={mx(classNames)}>
63
+ {children}
64
+ </div>
65
+ );
96
66
 
97
67
  const meta = {
98
68
  title: 'ui/react-ui-core/exemplars/slot',
@@ -107,13 +77,41 @@ export default meta;
107
77
  type Story = StoryObj<typeof meta>;
108
78
 
109
79
  export const Single: Story = {
110
- render: () => <TestSingle role='listitem' classNames='border-red-500' />,
80
+ render: () => (
81
+ <Outer asChild role='article' classNames='border-green-500' priority={1}>
82
+ <Leaf>Single asChild (non-compliant — see console)</Leaf>
83
+ </Outer>
84
+ ),
111
85
  };
112
86
 
113
87
  export const Nested: Story = {
114
- render: () => <TestNested role='listitem' classNames='border-green-500' />,
88
+ render: () => (
89
+ <Outer asChild role='article' classNames='border-blue-500'>
90
+ <Middle asChild>
91
+ <Leaf>Nested asChild</Leaf>
92
+ </Middle>
93
+ </Outer>
94
+ ),
115
95
  };
116
96
 
117
97
  export const Inner: Story = {
118
- render: () => <TestInner role='listitem' classNames='border-blue-500' />,
98
+ render: () => (
99
+ <Outer asChild role='article' classNames='border-orange-500'>
100
+ <Middle asChild>
101
+ <Leaf>
102
+ <div role='none'>Leaf</div>
103
+ </Leaf>
104
+ </Middle>
105
+ </Outer>
106
+ ),
107
+ };
108
+
109
+ export const Error: Story = {
110
+ render: () => (
111
+ <Outer asChild role='none' classNames='p-2 border border-green-500 rounded'>
112
+ <Middle asChild>
113
+ <Simple>Simple</Simple>
114
+ </Middle>
115
+ </Outer>
116
+ ),
119
117
  };
@@ -43,7 +43,7 @@ const Column = forwardRef<HTMLDivElement, { items: string[] }>(({ items }, ref)
43
43
  const tabsterAttrs = useMergedTabsterAttributes_unstable(focusableGroupAttrs, arrowNavigationAttrs);
44
44
 
45
45
  return (
46
- <ScrollArea.Root tabIndex={0} orientation='vertical' classNames={mx('w-[25rem]', border)}>
46
+ <ScrollArea.Root orientation='vertical' classNames={mx('w-[25rem]', border)}>
47
47
  <ScrollArea.Viewport {...tabsterAttrs} classNames='p-4 gap-4' ref={ref}>
48
48
  {items.map((item) => (
49
49
  <Item key={item} value={item} />
@@ -6,11 +6,11 @@ import { type Meta } from '@storybook/react-vite';
6
6
  import { useVirtualizer } from '@tanstack/react-virtual';
7
7
  import React, { useEffect, useMemo, useRef, useState } from 'react';
8
8
 
9
- import { faker } from '@dxos/random';
9
+ import { random } from '@dxos/random';
10
10
  import { Panel, ScrollArea, Toolbar } from '@dxos/react-ui';
11
11
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
12
12
 
13
- faker.seed(999);
13
+ random.seed(999);
14
14
 
15
15
  type TestItem = {
16
16
  name: string;
@@ -37,7 +37,7 @@ export const Default = {
37
37
  const items = useMemo<TestItem[]>(
38
38
  () =>
39
39
  Array.from({ length: NUM_ITEMS }, () => ({
40
- name: faker.lorem.paragraph(),
40
+ name: random.lorem.paragraph(),
41
41
  })),
42
42
  [],
43
43
  );
@@ -63,7 +63,7 @@ export const Default = {
63
63
  <ScrollToolbar items={items} index={index} setIndex={setIndex} />
64
64
  </Panel.Toolbar>
65
65
  <Panel.Content asChild>
66
- <ScrollArea.Root orientation='vertical' margin>
66
+ <ScrollArea.Root orientation='vertical' centered>
67
67
  <ScrollArea.Viewport classNames='p-2' ref={setViewport}>
68
68
  <div
69
69
  role='none'
@@ -6,6 +6,7 @@ export * from './useDensityContext';
6
6
  export * from './useElevationContext';
7
7
  export * from './useIconHref';
8
8
  export * from './useSafeArea';
9
+ export * from './useSafeCollisionPadding';
9
10
  export * from './useTranslationsContext';
10
11
  export * from './useThemeContext';
11
12
  export * from './useVisualViewport';
@@ -8,7 +8,7 @@ import { type Density } from '@dxos/ui-types';
8
8
 
9
9
  import { DensityContext } from '../components';
10
10
 
11
- export const useDensityContext = (propsDensity?: Density) => {
11
+ export const useDensityContext = (densityProp?: Density): Density | undefined => {
12
12
  const { density } = useContext(DensityContext);
13
- return propsDensity ?? density;
13
+ return densityProp ?? density;
14
14
  };
@@ -20,15 +20,14 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
20
20
  </Button>
21
21
  </div>
22
22
  <div className='flex justify-center'>
23
- <IconButton {...args} label='Test' icon='ph--atom--regular' size={7} density='coarse' />
23
+ <IconButton {...args} label='Test' icon='ph--circle--regular' density='coarse' />
24
24
  </div>
25
25
  <div className='flex justify-center'>
26
26
  <IconButton
27
27
  {...args}
28
28
  label='Test'
29
- icon='ph--atom--regular'
29
+ icon='ph--circle--regular'
30
30
  iconOnly
31
- size={7}
32
31
  density='coarse'
33
32
  classNames='px-1.5'
34
33
  />
@@ -43,13 +42,13 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
43
42
  </Button>
44
43
  </div>
45
44
  <div className='flex justify-center'>
46
- <IconButton {...args} label='Test' icon='ph--atom--regular' density='fine' classNames='px-2' />
45
+ <IconButton {...args} label='Test' icon='ph--circle--regular' density='fine' classNames='px-2' />
47
46
  </div>
48
47
  <div className='flex justify-center'>
49
48
  <IconButton
50
49
  {...args}
51
50
  label='Test'
52
- icon='ph--atom--regular'
51
+ icon='ph--circle--regular'
53
52
  iconOnly
54
53
  density='fine'
55
54
  classNames='py-1 px-1.5'
@@ -68,9 +67,8 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
68
67
  <IconButton
69
68
  {...args}
70
69
  label='Test'
71
- icon='ph--atom--regular'
70
+ icon='ph--circle--regular'
72
71
  density='fine'
73
- size={4}
74
72
  classNames={'!h-[24px] !text-[14px] p-1 min-h-0 gap-0.5'}
75
73
  />
76
74
  </div>
@@ -78,10 +76,9 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
78
76
  <IconButton
79
77
  {...args}
80
78
  label='Test'
81
- icon='ph--atom--regular'
79
+ icon='ph--circle--regular'
82
80
  iconOnly
83
81
  density='fine'
84
- size={4}
85
82
  classNames={'!h-[24px] !text-[14px] p-1 min-h-0'}
86
83
  />
87
84
  </div>
@@ -0,0 +1,148 @@
1
+ # Column architecture reference
2
+
3
+ ## Background
4
+
5
+ `Column` establishes a 3-column CSS grid with left/right gutter columns and a center content
6
+ channel. Two CSS custom properties drive the system:
7
+
8
+ - `--gutter` — the gutter track width (e.g. `var(--dx-gutter-md)`); consumed by `ScrollArea.Viewport` for padding.
9
+ - `--dx-col` — the grid-column placement token; set by `Column.Root` and consumed by `withColumn` utilities.
10
+
11
+ ## Column primitives
12
+
13
+ ### Column.Root
14
+
15
+ ```css
16
+ /* column.ts — columnRoot */
17
+ dx-column grid
18
+ /* inline style */
19
+ --gutter: <gutterSize>
20
+ --dx-col: 2 / span 1
21
+ grid-template-columns: <gutter> minmax(0,1fr) <gutter>
22
+ ```
23
+
24
+ Sets the 3-column grid and both CSS variables. All `withColumn` utilities are no-ops outside this context.
25
+
26
+ ### Column.Center
27
+
28
+ ```css
29
+ /* column.ts — columnCenter */
30
+ [grid-column:var(--dx-col,auto)] min-h-0
31
+ ```
32
+
33
+ Places a single element in col 2 (the center track). Does not use subgrid — placement is explicit
34
+ on this element only, so arbitrary compound components (including `display: contents` wrappers) can
35
+ be nested safely.
36
+
37
+ ### Column.Bleed
38
+
39
+ ```css
40
+ /* column.ts — columnBleed */
41
+ col-span-full grid grid-cols-subgrid min-h-0
42
+ ```
43
+
44
+ Spans all 3 columns and propagates the subgrid. Use for `ScrollArea`, full-width dividers, and
45
+ any content that should ignore the gutters.
46
+
47
+ ### Column.Row
48
+
49
+ ```css
50
+ /* column.ts — columnRow */
51
+ col-span-3 grid grid-cols-subgrid
52
+ ```
53
+
54
+ Three-slot icon row. Children map to: `[col-1: icon/slot] [col-2: content] [col-3: icon/action]`.
55
+ Must be a direct child of `Column.Root`.
56
+
57
+ ## withColumn theme utilities
58
+
59
+ Exported from `@dxos/ui-theme`. Components import and call these in their theme functions to
60
+ participate in the Column grid without importing Column React components.
61
+
62
+ ```ts
63
+ withColumn.center();
64
+ // → '[grid-column:var(--dx-col,auto)]'
65
+
66
+ withColumn.propagate();
67
+ // → '[.dx-column_&]:col-span-full [.dx-column_&]:grid [.dx-column_&]:grid-cols-subgrid'
68
+
69
+ withColumn.consumed();
70
+ // → '[--dx-col:auto]'
71
+ ```
72
+
73
+ | Utility | Purpose | Where used |
74
+ | :------------ | :-------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- |
75
+ | `center()` | Place element in col 2 via `--dx-col`. No-op outside Column or inside ScrollArea. | Dialog.Header, Dialog.ActionBar, Form.Content, Form.Actions, SearchList.Input |
76
+ | `propagate()` | Extend Column subgrid to children. No-op outside Column. | Dialog.Body, SearchList.Content |
77
+ | `consumed()` | Reset `--dx-col` after `--gutter` is consumed. | ScrollArea.Viewport |
78
+
79
+ ## CSS custom property cascade
80
+
81
+ ```text
82
+ Column.Root
83
+ sets --gutter = var(--dx-gutter-<size>)
84
+ sets --dx-col = 2 / span 1
85
+
86
+ ├─ Column.Center → grid-column: var(--dx-col) ← consumes --dx-col
87
+ ├─ Column.Bleed → col-span-full, subgrid
88
+ ├─ Column.Row → col-span-3, subgrid
89
+
90
+ └─ withColumn.center() → grid-column: var(--dx-col) ← consumes --dx-col
91
+ withColumn.propagate() → col-span-full, grid, subgrid (inside .dx-column only)
92
+
93
+ └─ ScrollArea.Root → col-span-full (inside .dx-column only)
94
+ ScrollArea.Viewport
95
+ applies pl/pr using --gutter
96
+ withColumn.consumed() → sets --dx-col: auto
97
+
98
+ └─ (nested components no longer auto-position)
99
+ ```
100
+
101
+ ## Component integration
102
+
103
+ ### Dialog
104
+
105
+ | Sub-component | withColumn applied | Effect |
106
+ | :----------------- | :---------------------------- | :---------------------------- |
107
+ | `Dialog.Content` | `Column.Root` (gutter `'sm'`) | Establishes the 3-col grid. |
108
+ | `Dialog.Header` | `withColumn.center()` | Placed in col 2. |
109
+ | `Dialog.Body` | `withColumn.propagate()` | Children inherit the subgrid. |
110
+ | `Dialog.ActionBar` | `withColumn.center()` | Placed in col 2. |
111
+
112
+ ### Form
113
+
114
+ | Sub-component | withColumn applied | Effect |
115
+ | :------------- | :-------------------- | :---------------------------------- |
116
+ | `Form.Content` | `withColumn.center()` | Placed in col 2 when inside Column. |
117
+ | `Form.Actions` | `withColumn.center()` | Placed in col 2 when inside Column. |
118
+
119
+ ### SearchList
120
+
121
+ | Sub-component | withColumn applied | Effect |
122
+ | :------------------------- | :----------------------- | :---------------------------------------------- |
123
+ | `SearchList.Content` | `withColumn.propagate()` | Extends subgrid to children when inside Column. |
124
+ | `SearchList.Input` wrapper | `withColumn.center()` | Input row placed in col 2. |
125
+
126
+ ### Card
127
+
128
+ `Card.Row` uses its own inline subgrid CSS (`col-span-3 grid grid-cols-subgrid`) and does not
129
+ participate in an outer Column grid. `Card.Root` establishes a separate 3-column grid for its
130
+ own icon-slot layout.
131
+
132
+ ## Subgrid chain integrity
133
+
134
+ Every intermediate container between `Column.Root` and a `ScrollArea.Root` must propagate the
135
+ subgrid, otherwise `ScrollArea.Root`'s `[.dx-column_&]:col-span-full` selector will not match
136
+ and the scrollbar will not extend to the gutter.
137
+
138
+ Required chain:
139
+
140
+ ```
141
+ Column.Root (.dx-column)
142
+ → withColumn.propagate() container (col-span-full, grid, grid-cols-subgrid)
143
+ → ScrollArea.Root (.dx-container, [.dx-column_&]:col-span-full)
144
+ → ScrollArea.Viewport (applies --gutter padding, resets --dx-col)
145
+ ```
146
+
147
+ If any intermediate element wraps the ScrollArea without propagating, use `Column.Bleed` or
148
+ apply `withColumn.propagate()` to that wrapper.
@@ -7,18 +7,16 @@ import React from 'react';
7
7
 
8
8
  import { Input, ScrollArea } from '../../components';
9
9
  import { withLayout, withTheme } from '../../testing';
10
- import { Flex } from '../Flex';
11
-
12
10
  import { Column } from './Column';
13
11
 
14
12
  const List = () => {
15
13
  return (
16
- <ScrollArea.Root margin role='list'>
14
+ <ScrollArea.Root centered>
17
15
  <ScrollArea.Viewport>
18
16
  {Array.from({ length: 100 }).map((_, i) => (
19
- <div key={i} role='listitem' className='p-1 hover:bg-hover-surface'>
20
- Item {i}
21
- </div>
17
+ <Input.Root key={i}>
18
+ <Input.TextInput value={`Item ${i}`} readOnly />
19
+ </Input.Root>
22
20
  ))}
23
21
  </ScrollArea.Viewport>
24
22
  </ScrollArea.Root>
@@ -27,31 +25,47 @@ const List = () => {
27
25
 
28
26
  const DefaultStory = () => {
29
27
  return (
30
- <Column.Root className='h-full overflow-hidden' gutter='md'>
31
- <Column.Segment asChild>
28
+ <Column.Root classNames='overflow-hidden' gutter='md'>
29
+ <Column.Center>
32
30
  <h1 className='p-1 bg-blue-500 text-black'>Header</h1>
33
- </Column.Segment>
31
+ </Column.Center>
34
32
 
35
- <Column.Segment asChild>
36
- <div className='py-2'>
33
+ <Column.Row>
34
+ <div className='p-1 bg-blue-500'>A</div>
35
+ <div className='p-1 bg-red-500'>B</div>
36
+ <div className='p-1 bg-blue-500'>C</div>
37
+ </Column.Row>
38
+
39
+ <Column.Center asChild>
40
+ <div>
37
41
  <Input.Root>
38
42
  <Input.TextInput placeholder='Search' />
39
43
  </Input.Root>
40
44
  </div>
41
- </Column.Segment>
45
+ </Column.Center>
42
46
 
43
- <List />
47
+ <ScrollArea.Root orientation='vertical' padding>
48
+ <ScrollArea.Viewport>
49
+ <div className='flex flex-col gap-2'>
50
+ {Array.from({ length: 100 }).map((_, i) => (
51
+ <Input.Root key={i}>
52
+ <Input.TextInput value={`Item ${i}`} readOnly />
53
+ </Input.Root>
54
+ ))}
55
+ </div>
56
+ </ScrollArea.Viewport>
57
+ </ScrollArea.Root>
44
58
 
45
- <Column.Segment asChild>
46
- <Flex column>
59
+ <Column.Center asChild>
60
+ <div className='flex flex-col'>
47
61
  <h1 className='p-1 bg-red-500 text-black'>Section with overflow</h1>
48
62
  <pre className='p-1 text-xs text-subdued overflow-auto'>{new Error().stack}</pre>
49
- </Flex>
50
- </Column.Segment>
63
+ </div>
64
+ </Column.Center>
51
65
 
52
- <Column.Segment asChild>
66
+ <Column.Center>
53
67
  <div className='p-1 bg-green-500 text-black'>Footer</div>
54
- </Column.Segment>
68
+ </Column.Center>
55
69
  </Column.Root>
56
70
  );
57
71
  };
@@ -70,3 +84,98 @@ export default meta;
70
84
  type Story = StoryObj<typeof meta>;
71
85
 
72
86
  export const Default: Story = {};
87
+
88
+ const InputList = ({ items = 50 }: { items?: number }) => (
89
+ <div className='flex flex-col gap-2'>
90
+ {Array.from({ length: items }).map((_, index) => (
91
+ <Input.Root key={index}>
92
+ <Input.TextInput value={`Item ${index + 1}`} readOnly />
93
+ </Input.Root>
94
+ ))}
95
+ </div>
96
+ );
97
+
98
+ export const WithScrollArea = {
99
+ decorators: [withLayout({ layout: 'column' })],
100
+ render: () => (
101
+ <Column.Root classNames='overflow-hidden' gutter='md'>
102
+ <Column.Center>
103
+ <h2>Header</h2>
104
+ </Column.Center>
105
+ <ScrollArea.Root padding centered orientation='vertical'>
106
+ <ScrollArea.Viewport>
107
+ <InputList items={30} />
108
+ </ScrollArea.Viewport>
109
+ </ScrollArea.Root>
110
+ <Column.Center>
111
+ <h2>Footer</h2>
112
+ </Column.Center>
113
+ </Column.Root>
114
+ ),
115
+ };
116
+
117
+ /**
118
+ * Column.Center places a single element in the center column of the parent grid.
119
+ * Preferred for centered content — safe to nest
120
+ * compound components (Form.Root, Editor.Root, etc.) that render `display: contents`.
121
+ */
122
+ export const WithCenter: Story = {
123
+ decorators: [withLayout({ classNames: 'w-[25rem]' })],
124
+ render: () => (
125
+ <Column.Root gutter='md'>
126
+ <Column.Center>
127
+ <h2>Header (Column.Center)</h2>
128
+ </Column.Center>
129
+ <Column.Center classNames='flex flex-col'>
130
+ <p>This text is inside Column.Center. It sits in the central column between the gutters.</p>
131
+ <Input.Root>
132
+ <Input.Label>Name</Input.Label>
133
+ <Input.TextInput placeholder='Enter name' />
134
+ </Input.Root>
135
+ </Column.Center>
136
+ <Column.Center>
137
+ <h2>Footer (Column.Center)</h2>
138
+ </Column.Center>
139
+ </Column.Root>
140
+ ),
141
+ };
142
+
143
+ /**
144
+ * ScrollArea auto-bleeds inside Column.Root (via [.dx-column_&]:col-span-full).
145
+ * No Column.Bleed wrapper needed.
146
+ */
147
+ export const WithScrollAreaAutoBleed: Story = {
148
+ decorators: [withLayout({ layout: 'column', classNames: 'w-[25rem]' })],
149
+ render: () => (
150
+ <Column.Root classNames='overflow-hidden' gutter='md'>
151
+ <Column.Center>
152
+ <h2>Header (Column.Center)</h2>
153
+ </Column.Center>
154
+ <ScrollArea.Root orientation='vertical' padding thin>
155
+ <ScrollArea.Viewport>
156
+ <InputList items={30} />
157
+ </ScrollArea.Viewport>
158
+ </ScrollArea.Root>
159
+ <Column.Center>
160
+ <h2>Footer (Column.Center)</h2>
161
+ </Column.Center>
162
+ </Column.Root>
163
+ ),
164
+ };
165
+
166
+ export const Experimental = {
167
+ render: () => {
168
+ return (
169
+ <div className='grid grid-cols-[2rem_1fr_2rem]'>
170
+ <div className='col-span-full grid grid-cols-subgrid'>
171
+ <div className='bg-red-surface'>A</div>
172
+ <div className='bg-green-surface'>B</div>
173
+ <div className='bg-blue-surface'>C</div>
174
+ </div>
175
+ <div className='col-span-full grid grid-cols-subgrid col-start-2'>
176
+ <div className='bg-green-surface'>B</div>
177
+ </div>
178
+ </div>
179
+ );
180
+ },
181
+ };