@dxos/react-ui 0.8.4-main.406dc2a → 0.8.4-main.40e3dcdf1b

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 (407) hide show
  1. package/dist/lib/browser/chunk-2FKSMWNY.mjs +774 -0
  2. package/dist/lib/browser/chunk-2FKSMWNY.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +3916 -66
  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 +76 -64
  7. package/dist/lib/browser/testing/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/chunk-ZNBLTSHI.mjs +776 -0
  9. package/dist/lib/node-esm/chunk-ZNBLTSHI.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +3916 -66
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +76 -64
  14. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  15. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  16. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  18. package/dist/types/src/components/{Buttons → Button}/Button.d.ts +1 -1
  19. package/dist/types/src/components/Button/Button.d.ts.map +1 -0
  20. package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -0
  21. package/dist/types/src/components/{Buttons → Button}/IconButton.d.ts +2 -2
  22. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -0
  23. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -0
  24. package/dist/types/src/components/Button/Toggle.d.ts.map +1 -0
  25. package/dist/types/src/components/Button/Toggle.stories.d.ts +16 -0
  26. package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -0
  27. package/dist/types/src/components/{Buttons → Button}/ToggleGroup.d.ts +4 -4
  28. package/dist/types/src/components/Button/ToggleGroup.d.ts.map +1 -0
  29. package/dist/types/src/components/{Buttons → Button}/ToggleGroup.stories.d.ts +4 -4
  30. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -0
  31. package/dist/types/src/components/Button/index.d.ts.map +1 -0
  32. package/dist/types/src/components/Card/Card.d.ts +107 -0
  33. package/dist/types/src/components/Card/Card.d.ts.map +1 -0
  34. package/dist/types/src/components/Card/Card.stories.d.ts +21 -0
  35. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -0
  36. package/dist/types/src/components/Card/index.d.ts +2 -0
  37. package/dist/types/src/components/Card/index.d.ts.map +1 -0
  38. package/dist/types/src/components/Clipboard/CopyButton.d.ts +1 -1
  39. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  40. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts +1 -1
  41. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  42. package/dist/types/src/components/{Dialogs → Dialog}/AlertDialog.d.ts +12 -3
  43. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -0
  44. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -0
  45. package/dist/types/src/components/Dialog/Dialog.d.ts +47 -0
  46. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -0
  47. package/dist/types/src/components/{Dialogs → Dialog}/Dialog.stories.d.ts +9 -10
  48. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -0
  49. package/dist/types/src/components/Dialog/index.d.ts.map +1 -0
  50. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts +1 -1
  51. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  52. package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts +11 -0
  53. package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts.map +1 -0
  54. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts +7 -0
  55. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -0
  56. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +8 -0
  57. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -0
  58. package/dist/types/src/components/ErrorFallback/ThrowError.d.ts +9 -0
  59. package/dist/types/src/components/ErrorFallback/ThrowError.d.ts.map +1 -0
  60. package/dist/types/src/components/ErrorFallback/index.d.ts +5 -0
  61. package/dist/types/src/components/ErrorFallback/index.d.ts.map +1 -0
  62. package/dist/types/src/components/Icon/Icon.d.ts +1 -1
  63. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  64. package/dist/types/src/components/Icon/Icon.stories.d.ts +17 -0
  65. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -0
  66. package/dist/types/src/components/Image/Image.d.ts +14 -0
  67. package/dist/types/src/components/Image/Image.d.ts.map +1 -0
  68. package/dist/types/src/components/Image/Image.stories.d.ts +33 -0
  69. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -0
  70. package/dist/types/src/components/Image/index.d.ts +2 -0
  71. package/dist/types/src/components/Image/index.d.ts.map +1 -0
  72. package/dist/types/src/components/Input/Input.d.ts +5 -5
  73. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  74. package/dist/types/src/components/Input/Input.stories.d.ts +8 -8
  75. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/{Lists → List}/List.d.ts +1 -1
  77. package/dist/types/src/components/List/List.d.ts.map +1 -0
  78. package/dist/types/src/components/List/List.stories.d.ts.map +1 -0
  79. package/dist/types/src/components/List/ListDropIndicator.d.ts.map +1 -0
  80. package/dist/types/src/components/List/Tree.d.ts.map +1 -0
  81. package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -0
  82. package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +1 -0
  83. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -0
  84. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -0
  85. package/dist/types/src/components/List/index.d.ts.map +1 -0
  86. package/dist/types/src/components/Main/Main.d.ts +17 -18
  87. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  88. package/dist/types/src/components/Main/Main.stories.d.ts +0 -3
  89. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  90. package/dist/types/src/components/{Menus → Menu}/ContextMenu.d.ts +6 -6
  91. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -0
  92. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -0
  93. package/dist/types/src/components/{Menus → Menu}/DropdownMenu.d.ts +3 -4
  94. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -0
  95. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -0
  96. package/dist/types/src/components/Menu/index.d.ts.map +1 -0
  97. package/dist/types/src/components/Message/Message.d.ts +1 -1
  98. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  99. package/dist/types/src/components/Message/Message.stories.d.ts +3 -4
  100. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  101. package/dist/types/src/components/Popover/Popover.d.ts +2 -1
  102. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  103. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +23 -26
  104. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  105. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +44 -8
  106. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  107. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +39 -0
  108. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -0
  109. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +24 -0
  110. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/ScrollContainer/index.d.ts +2 -0
  112. package/dist/types/src/components/ScrollContainer/index.d.ts.map +1 -0
  113. package/dist/types/src/components/Select/Select.d.ts +10 -10
  114. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  115. package/dist/types/src/components/Separator/Separator.d.ts +1 -1
  116. package/dist/types/src/components/Skeleton/Skeleton.d.ts +12 -0
  117. package/dist/types/src/components/Skeleton/Skeleton.d.ts.map +1 -0
  118. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts +17 -0
  119. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -0
  120. package/dist/types/src/components/Skeleton/index.d.ts +2 -0
  121. package/dist/types/src/components/Skeleton/index.d.ts.map +1 -0
  122. package/dist/types/src/components/Splitter/Splitter.d.ts +32 -0
  123. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -0
  124. package/dist/types/src/components/Splitter/Splitter.stories.d.ts +7 -0
  125. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -0
  126. package/dist/types/src/components/Splitter/index.d.ts +2 -0
  127. package/dist/types/src/components/Splitter/index.d.ts.map +1 -0
  128. package/dist/types/src/components/Status/Status.stories.d.ts +4 -2
  129. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  130. package/dist/types/src/components/Tag/Tag.d.ts +1 -1
  131. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  132. package/dist/types/src/components/Tag/Tag.stories.d.ts +0 -5
  133. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  134. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +2 -2
  135. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  136. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts +12 -0
  137. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -0
  138. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -8
  139. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  140. package/dist/types/src/components/ThemeProvider/index.d.ts +2 -1
  141. package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
  142. package/dist/types/src/components/Toast/Toast.d.ts +4 -4
  143. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  144. package/dist/types/src/components/Toolbar/Toolbar.d.ts +40 -12
  145. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  146. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  147. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  148. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  149. package/dist/types/src/components/index.d.ts +13 -8
  150. package/dist/types/src/components/index.d.ts.map +1 -1
  151. package/dist/types/src/exemplars/generics.stories.d.ts +18 -0
  152. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -0
  153. package/dist/types/src/exemplars/slot.stories.d.ts +14 -0
  154. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -0
  155. package/dist/types/src/exemplars/tabster.stories.d.ts +8 -0
  156. package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -0
  157. package/dist/types/src/exemplars/virtualizer.stories.d.ts +11 -0
  158. package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -0
  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 +1 -1
  162. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  163. package/dist/types/src/index.d.ts +2 -1
  164. package/dist/types/src/index.d.ts.map +1 -1
  165. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  166. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
  167. package/dist/types/src/primitives/Column/Column.d.ts +26 -0
  168. package/dist/types/src/primitives/Column/Column.d.ts.map +1 -0
  169. package/dist/types/src/primitives/Column/Column.stories.d.ts +6 -0
  170. package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -0
  171. package/dist/types/src/primitives/Column/index.d.ts +2 -0
  172. package/dist/types/src/primitives/Column/index.d.ts.map +1 -0
  173. package/dist/types/src/primitives/Container/Container.d.ts +8 -0
  174. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -0
  175. package/dist/types/src/primitives/Container/Container.stories.d.ts +6 -0
  176. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -0
  177. package/dist/types/src/primitives/Container/index.d.ts +2 -0
  178. package/dist/types/src/primitives/Container/index.d.ts.map +1 -0
  179. package/dist/types/src/primitives/Flex/Flex.d.ts +13 -0
  180. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -0
  181. package/dist/types/src/primitives/Flex/Flex.stories.d.ts +8 -0
  182. package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -0
  183. package/dist/types/src/primitives/Flex/index.d.ts +2 -0
  184. package/dist/types/src/primitives/Flex/index.d.ts.map +1 -0
  185. package/dist/types/src/primitives/Grid/Grid.d.ts +15 -0
  186. package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -0
  187. package/dist/types/src/primitives/Grid/Grid.stories.d.ts +8 -0
  188. package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -0
  189. package/dist/types/src/primitives/Grid/index.d.ts +2 -0
  190. package/dist/types/src/primitives/Grid/index.d.ts.map +1 -0
  191. package/dist/types/src/primitives/Panel/Panel.d.ts +26 -0
  192. package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -0
  193. package/dist/types/src/primitives/Panel/Panel.stories.d.ts +6 -0
  194. package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -0
  195. package/dist/types/src/primitives/Panel/index.d.ts +2 -0
  196. package/dist/types/src/primitives/Panel/index.d.ts.map +1 -0
  197. package/dist/types/src/primitives/index.d.ts +6 -0
  198. package/dist/types/src/primitives/index.d.ts.map +1 -0
  199. package/dist/types/src/testing/Loading.d.ts +9 -0
  200. package/dist/types/src/testing/Loading.d.ts.map +1 -0
  201. package/dist/types/src/testing/decorators/index.d.ts +1 -1
  202. package/dist/types/src/testing/decorators/index.d.ts.map +1 -1
  203. package/dist/types/src/testing/decorators/withLayout.d.ts +3 -3
  204. package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
  205. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts +12 -0
  206. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -0
  207. package/dist/types/src/testing/decorators/withTheme.d.ts +3 -2
  208. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  209. package/dist/types/src/testing/index.d.ts +1 -0
  210. package/dist/types/src/testing/index.d.ts.map +1 -1
  211. package/dist/types/src/translations.d.ts +11 -0
  212. package/dist/types/src/translations.d.ts.map +1 -0
  213. package/dist/types/src/util/index.d.ts +1 -2
  214. package/dist/types/src/util/index.d.ts.map +1 -1
  215. package/dist/types/tsconfig.tsbuildinfo +1 -1
  216. package/package.json +41 -29
  217. package/src/components/Avatars/Avatar.stories.tsx +5 -6
  218. package/src/components/Avatars/Avatar.tsx +6 -13
  219. package/src/components/Avatars/AvatarGroup.stories.tsx +2 -2
  220. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +4 -4
  221. package/src/components/Breadcrumb/Breadcrumb.tsx +11 -37
  222. package/src/components/{Buttons → Button}/Button.stories.tsx +4 -4
  223. package/src/components/{Buttons → Button}/Button.tsx +7 -13
  224. package/src/components/{Buttons → Button}/IconButton.stories.tsx +4 -4
  225. package/src/components/{Buttons → Button}/IconButton.tsx +20 -14
  226. package/src/components/{Buttons → Button}/Toggle.stories.tsx +7 -6
  227. package/src/components/{Buttons → Button}/ToggleGroup.stories.tsx +2 -2
  228. package/src/components/Card/Card.stories.tsx +151 -0
  229. package/src/components/Card/Card.tsx +347 -0
  230. package/src/components/Card/index.ts +5 -0
  231. package/src/components/Clipboard/CopyButton.tsx +7 -7
  232. package/src/components/DensityProvider/DensityProvider.tsx +1 -1
  233. package/src/components/Dialog/AlertDialog.stories.tsx +69 -0
  234. package/src/components/{Dialogs → Dialog}/AlertDialog.tsx +116 -16
  235. package/src/components/Dialog/Dialog.stories.tsx +122 -0
  236. package/src/components/{Dialogs → Dialog}/Dialog.tsx +179 -49
  237. package/src/components/ElevationProvider/ElevationProvider.tsx +1 -1
  238. package/src/components/ErrorFallback/ErrorFallback.stories.tsx +50 -0
  239. package/src/components/ErrorFallback/ErrorFallback.tsx +70 -0
  240. package/src/components/ErrorFallback/ErrorStack.tsx +80 -0
  241. package/src/components/ErrorFallback/ThrowError.tsx +37 -0
  242. package/src/components/ErrorFallback/index.ts +9 -0
  243. package/src/components/Icon/Icon.stories.tsx +113 -0
  244. package/src/components/Icon/Icon.tsx +3 -3
  245. package/src/components/Image/Image.stories.tsx +86 -0
  246. package/src/components/Image/Image.tsx +223 -0
  247. package/src/components/Image/index.ts +5 -0
  248. package/src/components/Input/Input.stories.tsx +21 -40
  249. package/src/components/Input/Input.tsx +32 -68
  250. package/src/components/Link/Link.stories.tsx +2 -2
  251. package/src/components/Link/Link.tsx +2 -2
  252. package/src/components/{Lists → List}/List.stories.tsx +30 -33
  253. package/src/components/{Lists → List}/List.tsx +12 -17
  254. package/src/components/{Lists → List}/ListDropIndicator.tsx +7 -7
  255. package/src/components/{Lists → List}/Tree.stories.tsx +4 -4
  256. package/src/components/{Lists → List}/TreeDropIndicator.tsx +6 -6
  257. package/src/components/{Lists → List}/Treegrid.stories.tsx +3 -3
  258. package/src/components/{Lists → List}/Treegrid.tsx +10 -15
  259. package/src/components/Main/Main.stories.tsx +41 -23
  260. package/src/components/Main/Main.tsx +149 -92
  261. package/src/components/{Menus → Menu}/ContextMenu.stories.tsx +2 -2
  262. package/src/components/{Menus → Menu}/ContextMenu.tsx +9 -33
  263. package/src/components/{Menus → Menu}/DropdownMenu.stories.tsx +3 -3
  264. package/src/components/{Menus → Menu}/DropdownMenu.tsx +89 -68
  265. package/src/components/Message/Message.stories.tsx +26 -11
  266. package/src/components/Message/Message.tsx +46 -33
  267. package/src/components/Popover/Popover.stories.tsx +5 -5
  268. package/src/components/Popover/Popover.tsx +75 -53
  269. package/src/components/ScrollArea/ScrollArea.stories.tsx +166 -40
  270. package/src/components/ScrollArea/ScrollArea.tsx +84 -82
  271. package/src/components/ScrollArea/index.ts +1 -1
  272. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +89 -0
  273. package/src/components/ScrollContainer/ScrollContainer.tsx +238 -0
  274. package/src/components/ScrollContainer/index.ts +5 -0
  275. package/src/components/Select/Select.stories.tsx +3 -3
  276. package/src/components/Select/Select.tsx +11 -27
  277. package/src/components/Separator/Separator.tsx +1 -1
  278. package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
  279. package/src/components/Skeleton/Skeleton.tsx +26 -0
  280. package/src/components/Skeleton/index.ts +5 -0
  281. package/src/components/Splitter/Splitter.stories.tsx +83 -0
  282. package/src/components/Splitter/Splitter.tsx +126 -0
  283. package/src/components/Splitter/index.ts +5 -0
  284. package/src/components/Status/Status.stories.tsx +21 -17
  285. package/src/components/Status/Status.tsx +2 -2
  286. package/src/components/Tag/Tag.stories.tsx +6 -11
  287. package/src/components/Tag/Tag.tsx +3 -8
  288. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +32 -0
  289. package/src/components/ThemeProvider/ThemeProvider.tsx +5 -6
  290. package/src/components/ThemeProvider/TranslationsProvider.tsx +1 -16
  291. package/src/components/ThemeProvider/index.ts +3 -3
  292. package/src/components/Toast/Toast.stories.tsx +3 -3
  293. package/src/components/Toast/Toast.tsx +10 -14
  294. package/src/components/Toolbar/Toolbar.stories.tsx +4 -6
  295. package/src/components/Toolbar/Toolbar.tsx +193 -15
  296. package/src/components/Tooltip/Tooltip.stories.tsx +16 -14
  297. package/src/components/Tooltip/Tooltip.tsx +25 -22
  298. package/src/components/index.ts +14 -9
  299. package/src/exemplars/generics.stories.tsx +49 -0
  300. package/src/exemplars/slot.stories.tsx +107 -0
  301. package/src/exemplars/tabster.stories.tsx +127 -0
  302. package/src/exemplars/virtualizer.stories.tsx +137 -0
  303. package/src/hooks/useDensityContext.ts +1 -1
  304. package/src/hooks/useElevationContext.ts +1 -1
  305. package/src/index.ts +2 -1
  306. package/src/playground/Controls.stories.tsx +3 -10
  307. package/src/playground/Custom.stories.tsx +8 -10
  308. package/src/playground/Typography.stories.tsx +3 -3
  309. package/src/primitives/Column/Column.stories.tsx +78 -0
  310. package/src/primitives/Column/Column.tsx +134 -0
  311. package/src/primitives/Column/index.ts +5 -0
  312. package/src/primitives/Container/Container.stories.tsx +30 -0
  313. package/src/primitives/Container/Container.tsx +22 -0
  314. package/src/primitives/Container/index.ts +5 -0
  315. package/src/primitives/Flex/Flex.stories.tsx +58 -0
  316. package/src/primitives/Flex/Flex.tsx +29 -0
  317. package/src/primitives/Flex/index.ts +5 -0
  318. package/src/primitives/Grid/Grid.stories.tsx +57 -0
  319. package/src/primitives/Grid/Grid.tsx +35 -0
  320. package/src/primitives/Grid/index.ts +5 -0
  321. package/src/primitives/Panel/Panel.stories.tsx +67 -0
  322. package/src/primitives/Panel/Panel.tsx +119 -0
  323. package/src/primitives/Panel/index.ts +5 -0
  324. package/src/primitives/index.ts +9 -0
  325. package/src/testing/Loading.tsx +26 -0
  326. package/src/testing/decorators/index.ts +1 -1
  327. package/src/testing/decorators/withLayout.tsx +39 -18
  328. package/src/testing/decorators/withLayoutVariants.tsx +48 -0
  329. package/src/testing/decorators/withTheme.tsx +21 -18
  330. package/src/testing/index.ts +2 -0
  331. package/src/translations.ts +19 -0
  332. package/src/util/index.ts +2 -2
  333. package/dist/lib/browser/chunk-KX5JDELJ.mjs +0 -4521
  334. package/dist/lib/browser/chunk-KX5JDELJ.mjs.map +0 -7
  335. package/dist/lib/node-esm/chunk-3HDQYL5S.mjs +0 -4523
  336. package/dist/lib/node-esm/chunk-3HDQYL5S.mjs.map +0 -7
  337. package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts +0 -15
  338. package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts.map +0 -1
  339. package/dist/types/src/components/AnchoredOverflow/index.d.ts +0 -2
  340. package/dist/types/src/components/AnchoredOverflow/index.d.ts.map +0 -1
  341. package/dist/types/src/components/Buttons/Button.d.ts.map +0 -1
  342. package/dist/types/src/components/Buttons/Button.stories.d.ts.map +0 -1
  343. package/dist/types/src/components/Buttons/IconButton.d.ts.map +0 -1
  344. package/dist/types/src/components/Buttons/IconButton.stories.d.ts.map +0 -1
  345. package/dist/types/src/components/Buttons/Toggle.d.ts.map +0 -1
  346. package/dist/types/src/components/Buttons/Toggle.stories.d.ts +0 -13
  347. package/dist/types/src/components/Buttons/Toggle.stories.d.ts.map +0 -1
  348. package/dist/types/src/components/Buttons/ToggleGroup.d.ts.map +0 -1
  349. package/dist/types/src/components/Buttons/ToggleGroup.stories.d.ts.map +0 -1
  350. package/dist/types/src/components/Buttons/index.d.ts.map +0 -1
  351. package/dist/types/src/components/Dialogs/AlertDialog.d.ts.map +0 -1
  352. package/dist/types/src/components/Dialogs/AlertDialog.stories.d.ts.map +0 -1
  353. package/dist/types/src/components/Dialogs/Dialog.d.ts +0 -31
  354. package/dist/types/src/components/Dialogs/Dialog.d.ts.map +0 -1
  355. package/dist/types/src/components/Dialogs/Dialog.stories.d.ts.map +0 -1
  356. package/dist/types/src/components/Dialogs/index.d.ts.map +0 -1
  357. package/dist/types/src/components/Lists/List.d.ts.map +0 -1
  358. package/dist/types/src/components/Lists/List.stories.d.ts.map +0 -1
  359. package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +0 -1
  360. package/dist/types/src/components/Lists/Tree.d.ts.map +0 -1
  361. package/dist/types/src/components/Lists/Tree.stories.d.ts.map +0 -1
  362. package/dist/types/src/components/Lists/TreeDropIndicator.d.ts.map +0 -1
  363. package/dist/types/src/components/Lists/Treegrid.d.ts.map +0 -1
  364. package/dist/types/src/components/Lists/Treegrid.stories.d.ts.map +0 -1
  365. package/dist/types/src/components/Lists/index.d.ts.map +0 -1
  366. package/dist/types/src/components/Menus/ContextMenu.d.ts.map +0 -1
  367. package/dist/types/src/components/Menus/ContextMenu.stories.d.ts.map +0 -1
  368. package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +0 -1
  369. package/dist/types/src/components/Menus/DropdownMenu.stories.d.ts.map +0 -1
  370. package/dist/types/src/components/Menus/index.d.ts.map +0 -1
  371. package/dist/types/src/testing/decorators/withSurfaceVariantsLayout.d.ts +0 -12
  372. package/dist/types/src/testing/decorators/withSurfaceVariantsLayout.d.ts.map +0 -1
  373. package/dist/types/src/util/ThemedClassName.d.ts +0 -5
  374. package/dist/types/src/util/ThemedClassName.d.ts.map +0 -1
  375. package/dist/types/src/util/domino.d.ts +0 -18
  376. package/dist/types/src/util/domino.d.ts.map +0 -1
  377. package/src/components/AnchoredOverflow/AnchoredOverflow.tsx +0 -59
  378. package/src/components/AnchoredOverflow/index.ts +0 -5
  379. package/src/components/Dialogs/AlertDialog.stories.tsx +0 -69
  380. package/src/components/Dialogs/Dialog.stories.tsx +0 -67
  381. package/src/testing/decorators/withSurfaceVariantsLayout.tsx +0 -51
  382. package/src/util/ThemedClassName.ts +0 -7
  383. package/src/util/domino.ts +0 -53
  384. /package/dist/types/src/components/{Buttons → Button}/Button.stories.d.ts +0 -0
  385. /package/dist/types/src/components/{Buttons → Button}/IconButton.stories.d.ts +0 -0
  386. /package/dist/types/src/components/{Buttons → Button}/Toggle.d.ts +0 -0
  387. /package/dist/types/src/components/{Buttons → Button}/index.d.ts +0 -0
  388. /package/dist/types/src/components/{Dialogs → Dialog}/AlertDialog.stories.d.ts +0 -0
  389. /package/dist/types/src/components/{Dialogs → Dialog}/index.d.ts +0 -0
  390. /package/dist/types/src/components/{Lists → List}/List.stories.d.ts +0 -0
  391. /package/dist/types/src/components/{Lists → List}/ListDropIndicator.d.ts +0 -0
  392. /package/dist/types/src/components/{Lists → List}/Tree.d.ts +0 -0
  393. /package/dist/types/src/components/{Lists → List}/Tree.stories.d.ts +0 -0
  394. /package/dist/types/src/components/{Lists → List}/TreeDropIndicator.d.ts +0 -0
  395. /package/dist/types/src/components/{Lists → List}/Treegrid.d.ts +0 -0
  396. /package/dist/types/src/components/{Lists → List}/Treegrid.stories.d.ts +0 -0
  397. /package/dist/types/src/components/{Lists → List}/index.d.ts +0 -0
  398. /package/dist/types/src/components/{Menus → Menu}/ContextMenu.stories.d.ts +0 -0
  399. /package/dist/types/src/components/{Menus → Menu}/DropdownMenu.stories.d.ts +0 -0
  400. /package/dist/types/src/components/{Menus → Menu}/index.d.ts +0 -0
  401. /package/src/components/{Buttons → Button}/Toggle.tsx +0 -0
  402. /package/src/components/{Buttons → Button}/ToggleGroup.tsx +0 -0
  403. /package/src/components/{Buttons → Button}/index.ts +0 -0
  404. /package/src/components/{Dialogs → Dialog}/index.ts +0 -0
  405. /package/src/components/{Lists → List}/Tree.tsx +0 -0
  406. /package/src/components/{Lists → List}/index.ts +0 -0
  407. /package/src/components/{Menus → Menu}/index.ts +0 -0
@@ -1,111 +1,113 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
- import {
6
- Corner as ScrollAreaPrimitiveCorner,
7
- type ScrollAreaCornerProps as ScrollAreaPrimitiveCornerProps,
8
- Root as ScrollAreaPrimitiveRoot,
9
- type ScrollAreaProps as ScrollAreaPrimitiveRootProps,
10
- Scrollbar as ScrollAreaPrimitiveScrollbar,
11
- type ScrollAreaScrollbarProps as ScrollAreaPrimitiveScrollbarProps,
12
- Thumb as ScrollAreaPrimitiveThumb,
13
- type ScrollAreaThumbProps as ScrollAreaPrimitiveThumbProps,
14
- Viewport as ScrollAreaPrimitiveViewport,
15
- type ScrollAreaViewportProps as ScrollAreaPrimitiveViewportProps,
16
- } from '@radix-ui/react-scroll-area';
17
- import React, { forwardRef } from 'react';
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import { Primitive } from '@radix-ui/react-primitive';
7
+ import { Slot } from '@radix-ui/react-slot';
8
+ import React, { type HTMLAttributes, forwardRef } from 'react';
9
+
10
+ import { composableProps } from '@dxos/ui-theme';
11
+ import { type AllowedAxis, type SlottableProps, type ThemedClassName } from '@dxos/ui-types';
18
12
 
19
13
  import { useThemeContext } from '../../hooks';
20
- import { type ThemedClassName } from '../../util';
21
14
 
22
- type ScrollAreaVariant = 'coarse' | 'fine';
15
+ //
16
+ // Context
17
+ //
23
18
 
24
- type ScrollAreaRootProps = ThemedClassName<ScrollAreaPrimitiveRootProps>;
19
+ const SCROLLAREA_NAME = 'ScrollArea';
20
+
21
+ type ScrollAreaContextType = {
22
+ /** Orientation of scrollbars. */
23
+ orientation: AllowedAxis;
24
+ /** Hide scrollbars when not scrolling. */
25
+ autoHide: boolean;
26
+ /** Apply padding to opposite side of scrollbar. */
27
+ margin?: boolean;
28
+ /** Apply padding. */
29
+ padding: boolean;
30
+ /** Use thin scrollbars. */
31
+ thin: boolean;
32
+ /** Enable snap scrolling. */
33
+ snap: boolean;
34
+ };
35
+
36
+ const [ScrollAreaProvider, useScrollAreaContext] = createContext<ScrollAreaContextType>(SCROLLAREA_NAME);
37
+
38
+ //
39
+ // Root
40
+ //
41
+
42
+ const SCROLLAREA_ROOT_NAME = 'ScrollArea.Root';
43
+
44
+ type ScrollAreaRootProps = SlottableProps<HTMLDivElement, Partial<ScrollAreaContextType>>;
25
45
 
26
46
  /**
27
- * @deprecated
47
+ * ScrollArea provides native scrollbars with custom styling.
28
48
  */
29
- const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(({ classNames, ...props }, forwardedRef) => {
30
- const { tx } = useThemeContext();
31
- return (
32
- <ScrollAreaPrimitiveRoot
33
- {...props}
34
- className={tx('scrollArea.root', 'scroll-area', {}, classNames)}
35
- ref={forwardedRef}
36
- />
37
- );
38
- });
39
-
40
- type ScrollAreaViewportProps = ThemedClassName<ScrollAreaPrimitiveViewportProps>;
41
-
42
- const ScrollAreaViewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(
43
- ({ classNames, ...props }, forwardedRef) => {
49
+ const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(
50
+ (
51
+ {
52
+ children,
53
+ asChild,
54
+ orientation = 'vertical',
55
+ autoHide = true,
56
+ margin = false,
57
+ padding = false,
58
+ thin = false,
59
+ snap = false,
60
+ ...props
61
+ },
62
+ forwardedRef,
63
+ ) => {
64
+ const { className, ...rest } = composableProps(props);
65
+ const Comp = asChild ? Slot : Primitive.div;
44
66
  const { tx } = useThemeContext();
67
+ const options = { orientation, autoHide, margin, padding, thin, snap };
68
+
45
69
  return (
46
- <ScrollAreaPrimitiveViewport
47
- {...props}
48
- className={tx('scrollArea.viewport', 'scroll-area', {}, classNames)}
49
- ref={forwardedRef}
50
- />
70
+ <ScrollAreaProvider {...options}>
71
+ <Comp {...rest} className={tx('scrollArea.root', options, className)} ref={forwardedRef}>
72
+ {children}
73
+ </Comp>
74
+ </ScrollAreaProvider>
51
75
  );
52
76
  },
53
77
  );
54
78
 
55
- type ScrollAreaScrollbarProps = ThemedClassName<ScrollAreaPrimitiveScrollbarProps> & { variant?: ScrollAreaVariant };
79
+ ScrollAreaRoot.displayName = SCROLLAREA_ROOT_NAME;
80
+
81
+ //
82
+ // Viewport
83
+ //
84
+
85
+ const SCROLLAREA_VIEWPORT_NAME = 'ScrollArea.Viewport';
86
+
87
+ type ScrollAreaViewportProps = ThemedClassName<HTMLAttributes<HTMLDivElement>>;
56
88
 
57
- const ScrollAreaScrollbar = forwardRef<HTMLDivElement, ScrollAreaScrollbarProps>(
58
- ({ classNames, variant = 'fine', ...props }, forwardedRef) => {
89
+ const ScrollAreaViewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(
90
+ ({ classNames, children, ...props }, forwardedRef) => {
59
91
  const { tx } = useThemeContext();
92
+ const options = useScrollAreaContext(SCROLLAREA_VIEWPORT_NAME);
93
+
60
94
  return (
61
- <ScrollAreaPrimitiveScrollbar
62
- data-variant={variant}
63
- {...props}
64
- className={tx('scrollArea.scrollbar', 'scroll-area__scrollbar', {}, classNames)}
65
- ref={forwardedRef}
66
- />
95
+ <div {...props} className={tx('scrollArea.viewport', options, classNames)} ref={forwardedRef}>
96
+ {children}
97
+ </div>
67
98
  );
68
99
  },
69
100
  );
70
101
 
71
- type ScrollAreaThumbProps = ThemedClassName<ScrollAreaPrimitiveThumbProps>;
72
-
73
- const ScrollAreaThumb = forwardRef<HTMLDivElement, ScrollAreaThumbProps>(({ classNames, ...props }, forwardedRef) => {
74
- const { tx } = useThemeContext();
75
- return (
76
- <ScrollAreaPrimitiveThumb
77
- {...props}
78
- className={tx('scrollArea.thumb', 'scroll-area__thumb', {}, classNames)}
79
- ref={forwardedRef}
80
- />
81
- );
82
- });
83
-
84
- type ScrollAreaCornerProps = ThemedClassName<ScrollAreaPrimitiveCornerProps>;
85
-
86
- const ScrollAreaCorner = forwardRef<HTMLDivElement, ScrollAreaCornerProps>(({ classNames, ...props }, forwardedRef) => {
87
- const { tx } = useThemeContext();
88
- return (
89
- <ScrollAreaPrimitiveCorner
90
- {...props}
91
- className={tx('scrollArea.corner', 'scroll-area__corner', {}, classNames)}
92
- ref={forwardedRef}
93
- />
94
- );
95
- });
102
+ ScrollAreaViewport.displayName = SCROLLAREA_VIEWPORT_NAME;
103
+
104
+ //
105
+ // ScrollArea
106
+ //
96
107
 
97
108
  export const ScrollArea = {
98
109
  Root: ScrollAreaRoot,
99
110
  Viewport: ScrollAreaViewport,
100
- Scrollbar: ScrollAreaScrollbar,
101
- Thumb: ScrollAreaThumb,
102
- Corner: ScrollAreaCorner,
103
111
  };
104
112
 
105
- export type {
106
- ScrollAreaRootProps,
107
- ScrollAreaViewportProps,
108
- ScrollAreaScrollbarProps,
109
- ScrollAreaThumbProps,
110
- ScrollAreaCornerProps,
111
- };
113
+ export type { ScrollAreaRootProps, ScrollAreaViewportProps };
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
5
  export * from './ScrollArea';
@@ -0,0 +1,89 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useEffect, useRef, useState } from 'react';
7
+
8
+ import { faker } from '@dxos/random';
9
+
10
+ import { Panel } from '../../primitives';
11
+ import { withLayout, withTheme } from '../../testing';
12
+ import { Button } from '../Button';
13
+ import { Toolbar } from '../Toolbar';
14
+
15
+ import { ScrollContainer, type ScrollContainerRootProps, type ScrollController } from './ScrollContainer';
16
+
17
+ type StoryProps = ScrollContainerRootProps & { running?: boolean; initialLines?: number };
18
+
19
+ const DefaultStory = ({ initialLines = 0, running: runningProp, ...props }: StoryProps) => {
20
+ const [lines, setLines] = useState<string[]>([]);
21
+ const [running, setRunning] = useState(runningProp);
22
+ const scroller = useRef<ScrollController>(null);
23
+ useEffect(() => {
24
+ setLines(Array.from({ length: initialLines }, () => faker.lorem.paragraph()));
25
+ }, [initialLines]);
26
+ useEffect(() => {
27
+ if (!running) {
28
+ return;
29
+ }
30
+
31
+ const i = setInterval(() => {
32
+ setLines((lines) => [...lines, faker.lorem.paragraph()]);
33
+ }, 500);
34
+
35
+ return () => clearInterval(i);
36
+ }, [running]);
37
+
38
+ return (
39
+ <Panel.Root className='dx-article'>
40
+ <Panel.Toolbar asChild>
41
+ <Toolbar.Root>
42
+ <Button onClick={() => setRunning((running) => !running)}>{running ? 'Stop' : 'Start'}</Button>
43
+ <Button onClick={() => scroller.current?.scrollToBottom()}>Scroll to bottom</Button>
44
+ <Toolbar.Separator />
45
+ <div className='px-1'>{lines.length}</div>
46
+ </Toolbar.Root>
47
+ </Panel.Toolbar>
48
+ <Panel.Content asChild>
49
+ <ScrollContainer.Root {...props} ref={scroller}>
50
+ <ScrollContainer.Viewport>
51
+ {lines.map((line, index) => (
52
+ <div key={index} className='p-2 text-description'>
53
+ {line}
54
+ </div>
55
+ ))}
56
+ </ScrollContainer.Viewport>
57
+ <ScrollContainer.ScrollDownButton />
58
+ </ScrollContainer.Root>
59
+ </Panel.Content>
60
+ </Panel.Root>
61
+ );
62
+ };
63
+
64
+ const meta = {
65
+ title: 'ui/react-ui-core/components/ScrollContainer',
66
+ component: ScrollContainer.Root,
67
+ render: DefaultStory,
68
+ decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'w-[30rem]' })],
69
+ } satisfies Meta<typeof DefaultStory>;
70
+
71
+ export default meta;
72
+
73
+ type Story = StoryObj<typeof meta>;
74
+
75
+ export const Default: Story = {
76
+ args: {
77
+ pin: true,
78
+ fade: true,
79
+ running: true,
80
+ },
81
+ };
82
+
83
+ export const Large: Story = {
84
+ args: {
85
+ pin: true,
86
+ fade: true,
87
+ initialLines: 100,
88
+ },
89
+ };
@@ -0,0 +1,238 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import React, {
7
+ type HTMLAttributes,
8
+ type PropsWithChildren,
9
+ forwardRef,
10
+ useCallback,
11
+ useEffect,
12
+ useImperativeHandle,
13
+ useMemo,
14
+ useRef,
15
+ useState,
16
+ } from 'react';
17
+
18
+ import { addEventListener, combine } from '@dxos/async';
19
+ import { invariant } from '@dxos/invariant';
20
+ import { useForwardedRef } from '@dxos/react-hooks';
21
+ import { mx } from '@dxos/ui-theme';
22
+
23
+ import { type ThemedClassName } from '../../util';
24
+ import { IconButton } from '../Button';
25
+ import { ScrollArea } from '../ScrollArea';
26
+
27
+ const isBottom = (el: HTMLElement | null) => {
28
+ return !!(el && el.scrollHeight - el.scrollTop === el.clientHeight);
29
+ };
30
+
31
+ export interface ScrollController {
32
+ viewport: HTMLDivElement | null;
33
+ scrollToTop: (behavior?: ScrollBehavior) => void;
34
+ scrollToBottom: (behavior?: ScrollBehavior) => void;
35
+ }
36
+
37
+ type ScrollContainerContextValue = {
38
+ scrollToBottom: (behavior?: ScrollBehavior) => void;
39
+ controller?: ScrollController;
40
+ pinned?: boolean;
41
+ };
42
+
43
+ const [ScrollContainerProvider, useScrollContainerContext] =
44
+ createContext<ScrollContainerContextValue>('ScrollContainer');
45
+
46
+ //
47
+ // Root
48
+ //
49
+
50
+ type RootProps = ThemedClassName<
51
+ PropsWithChildren<{
52
+ pin?: boolean;
53
+ fade?: boolean;
54
+ behavior?: ScrollBehavior;
55
+ }>
56
+ >;
57
+
58
+ /**
59
+ * Scroll container that automatically scrolls to the bottom when new content is added.
60
+ */
61
+ const Root = forwardRef<ScrollController, RootProps>(
62
+ ({ children, classNames, pin, fade, behavior: behaviorProp = 'smooth' }, forwardedRef) => {
63
+ const scrollerRef = useRef<HTMLDivElement>(null);
64
+ const autoScrollRef = useRef(false);
65
+ const [overflow, setOverflow] = useState(false);
66
+ const [pinned, setPinned] = useState(pin);
67
+
68
+ const timeoutRef = useRef<NodeJS.Timeout>(undefined);
69
+ const scrollToBottom = useCallback((behavior: ScrollBehavior = behaviorProp) => {
70
+ if (scrollerRef.current) {
71
+ // Temporarily hide scrollbar to prevent flickering.
72
+ autoScrollRef.current = true;
73
+ scrollerRef.current.classList.add('scrollbar-none');
74
+ scrollerRef.current.scrollTo({
75
+ top: scrollerRef.current.scrollHeight,
76
+ behavior,
77
+ });
78
+
79
+ clearTimeout(timeoutRef.current);
80
+ if (behavior !== 'instant') {
81
+ timeoutRef.current = setTimeout(() => {
82
+ scrollerRef.current?.classList.remove('scrollbar-none');
83
+ autoScrollRef.current = false;
84
+ }, 500);
85
+ }
86
+
87
+ setPinned(true);
88
+ }
89
+ }, []);
90
+
91
+ const controller = useMemo(
92
+ () => ({
93
+ viewport: scrollerRef.current,
94
+ scrollToTop: () => {
95
+ invariant(scrollerRef.current);
96
+ scrollerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
97
+ setPinned(false);
98
+ },
99
+ scrollToBottom: () => {
100
+ scrollToBottom('smooth');
101
+ },
102
+ }),
103
+ [scrollToBottom, scrollerRef.current],
104
+ );
105
+
106
+ // Scroll controller imperative ref.
107
+ useImperativeHandle(forwardedRef, () => controller, [controller]);
108
+
109
+ // Listen for scroll events.
110
+ useEffect(() => {
111
+ if (!scrollerRef.current) {
112
+ return;
113
+ }
114
+
115
+ return combine(
116
+ // Check if user scrolls.
117
+ addEventListener(scrollerRef.current, 'wheel', () => {
118
+ setPinned(isBottom(scrollerRef.current));
119
+ }),
120
+ // Check if scrolls.
121
+ addEventListener(scrollerRef.current, 'scroll', () => {
122
+ setOverflow((scrollerRef.current?.scrollTop ?? 0) > 0);
123
+ }),
124
+ );
125
+ }, []);
126
+
127
+ return (
128
+ <ScrollContainerProvider pinned={pinned} controller={controller} scrollToBottom={scrollToBottom}>
129
+ <div className='relative grid dx-container overflow-hidden'>
130
+ {fade && (
131
+ <div
132
+ role='none'
133
+ data-visible={overflow}
134
+ className={mx(
135
+ // NOTE: Gradients may not be visible with dark reader extensions.
136
+ 'z-10 absolute top-0 inset-x-0 h-24 w-full',
137
+ 'opacity-0 duration-200 transition-opacity data-[visible="true"]:opacity-100',
138
+ 'bg-gradient-to-b from-(--surface-bg) to-transparent pointer-events-none',
139
+ )}
140
+ />
141
+ )}
142
+ <ScrollArea.Root classNames={mx('min-h-0', classNames)} thin>
143
+ <ScrollArea.Viewport ref={scrollerRef}>{children}</ScrollArea.Viewport>
144
+ </ScrollArea.Root>
145
+ </div>
146
+ </ScrollContainerProvider>
147
+ );
148
+ },
149
+ );
150
+
151
+ Root.displayName = 'ScrollContainer.Root';
152
+
153
+ //
154
+ // Viewport
155
+ //
156
+
157
+ const VIEWPORT_NAME = 'ScrollContainer.Viewport';
158
+
159
+ type ViewportProps = ThemedClassName<PropsWithChildren<Omit<HTMLAttributes<HTMLDivElement>, 'className'>>>;
160
+
161
+ const Viewport = forwardRef<HTMLDivElement, ViewportProps>(({ classNames, children, ...props }, forwardedRef) => {
162
+ const contentRef = useForwardedRef(forwardedRef);
163
+ const { pinned, scrollToBottom } = useScrollContainerContext(VIEWPORT_NAME);
164
+
165
+ useEffect(() => {
166
+ if (!pinned || !contentRef.current) {
167
+ return;
168
+ }
169
+
170
+ // Scroll instantly otherwise it might move while we're scrolling.
171
+ scrollToBottom();
172
+
173
+ // Setup resize observer to detect content changes.
174
+ const resizeObserver = new ResizeObserver(() => scrollToBottom());
175
+ resizeObserver.observe(contentRef.current);
176
+ return () => resizeObserver.disconnect();
177
+ }, [pinned, scrollToBottom]);
178
+
179
+ return (
180
+ <div className={mx('w-full', classNames)} {...props} ref={contentRef}>
181
+ {children}
182
+ </div>
183
+ );
184
+ });
185
+
186
+ Viewport.displayName = VIEWPORT_NAME;
187
+
188
+ //
189
+ // ScrollDownButton
190
+ //
191
+
192
+ const SCROLL_DOWN_BUTTON_NAME = 'ScrollContainer.ScrollDownButton';
193
+
194
+ type ScrollDownButtonProps = ThemedClassName;
195
+
196
+ const ScrollDownButton = ({ classNames }: ScrollDownButtonProps) => {
197
+ const { pinned, scrollToBottom } = useScrollContainerContext(SCROLL_DOWN_BUTTON_NAME);
198
+
199
+ return (
200
+ <div
201
+ role='none'
202
+ className={mx(
203
+ 'absolute bottom-2 right-4 opacity-100 transition-opacity duration-300',
204
+ pinned && 'opacity-0',
205
+ classNames,
206
+ )}
207
+ >
208
+ <IconButton
209
+ variant='primary'
210
+ icon='ph--arrow-down--regular'
211
+ iconOnly
212
+ size={4}
213
+ label='Scroll down'
214
+ onClick={() => scrollToBottom()}
215
+ />
216
+ </div>
217
+ );
218
+ };
219
+
220
+ ScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
221
+
222
+ //
223
+ // ScrollContainer
224
+ //
225
+
226
+ export { useScrollContainerContext };
227
+
228
+ export const ScrollContainer = {
229
+ Root,
230
+ Viewport,
231
+ ScrollDownButton,
232
+ };
233
+
234
+ export type {
235
+ RootProps as ScrollContainerRootProps,
236
+ ViewportProps as ScrollContainerViewportProps,
237
+ ScrollDownButtonProps as ScrollContainerScrollDownButtonProps,
238
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './ScrollContainer';
@@ -8,7 +8,7 @@ import React, { useState } from 'react';
8
8
  import { faker } from '@dxos/random';
9
9
 
10
10
  import { withTheme } from '../../testing';
11
- import { withSurfaceVariantsLayout } from '../../testing';
11
+ import { withLayoutVariants } from '../../testing';
12
12
 
13
13
  import { Select } from './Select';
14
14
 
@@ -42,9 +42,9 @@ const DefaultStory = ({ items = [] }: StoryProps) => {
42
42
  };
43
43
 
44
44
  const meta = {
45
- title: 'ui/react-ui-core/Select',
45
+ title: 'ui/react-ui-core/components/Select',
46
46
  render: DefaultStory,
47
- decorators: [withTheme, withSurfaceVariantsLayout()],
47
+ decorators: [withTheme(), withLayoutVariants()],
48
48
  } satisfies Meta<typeof DefaultStory>;
49
49
 
50
50
  export default meta;
@@ -8,7 +8,7 @@ import React, { forwardRef } from 'react';
8
8
  import { useElevationContext, useThemeContext } from '../../hooks';
9
9
  import { useSafeCollisionPadding } from '../../hooks/useSafeCollisionPadding';
10
10
  import { type ThemedClassName } from '../../util';
11
- import { Button, type ButtonProps } from '../Buttons';
11
+ import { Button, type ButtonProps } from '../Button';
12
12
  import { Icon } from '../Icon';
13
13
 
14
14
  type SelectRootProps = SelectPrimitive.SelectProps;
@@ -61,7 +61,7 @@ const SelectContent = forwardRef<HTMLDivElement, SelectContentProps>(
61
61
  {...props}
62
62
  data-arrow-keys='up down'
63
63
  collisionPadding={safeCollisionPadding}
64
- className={tx('select.content', 'select__content', { elevation }, classNames)}
64
+ className={tx('select.content', { elevation }, classNames)}
65
65
  position='popper'
66
66
  ref={forwardedRef}
67
67
  >
@@ -79,7 +79,7 @@ const SelectScrollUpButton = forwardRef<HTMLDivElement, SelectScrollUpButtonProp
79
79
  return (
80
80
  <SelectPrimitive.SelectScrollUpButton
81
81
  {...props}
82
- className={tx('select.scrollButton', 'select__scroll-button--up', {}, classNames)}
82
+ className={tx('select.scrollButton', {}, classNames)}
83
83
  ref={forwardedRef}
84
84
  >
85
85
  {children ?? <Icon size={3} icon='ph--caret-up--bold' />}
@@ -96,7 +96,7 @@ const SelectScrollDownButton = forwardRef<HTMLDivElement, SelectScrollDownButton
96
96
  return (
97
97
  <SelectPrimitive.SelectScrollDownButton
98
98
  {...props}
99
- className={tx('select.scrollButton', 'select__scroll-button--down', {}, classNames)}
99
+ className={tx('select.scrollButton', {}, classNames)}
100
100
  ref={forwardedRef}
101
101
  >
102
102
  {children ?? <Icon size={3} icon='ph--caret-down--bold' />}
@@ -108,14 +108,10 @@ const SelectScrollDownButton = forwardRef<HTMLDivElement, SelectScrollDownButton
108
108
  type SelectViewportProps = ThemedClassName<SelectPrimitive.SelectViewportProps>;
109
109
 
110
110
  const SelectViewport = forwardRef<HTMLDivElement, SelectViewportProps>(
111
- ({ classNames, asChild, children, ...props }, forwardedRef) => {
111
+ ({ classNames, children, ...props }, forwardedRef) => {
112
112
  const { tx } = useThemeContext();
113
113
  return (
114
- <SelectPrimitive.SelectViewport
115
- {...props}
116
- className={tx('select.viewport', 'select__viewport', {}, classNames)}
117
- ref={forwardedRef}
118
- >
114
+ <SelectPrimitive.SelectViewport {...props} className={tx('select.viewport', {}, classNames)} ref={forwardedRef}>
119
115
  {children}
120
116
  </SelectPrimitive.SelectViewport>
121
117
  );
@@ -126,7 +122,7 @@ type SelectItemProps = ThemedClassName<SelectPrimitive.SelectItemProps>;
126
122
 
127
123
  const SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(({ classNames, ...props }, forwardedRef) => {
128
124
  const { tx } = useThemeContext();
129
- return <SelectPrimitive.Item {...props} className={tx('select.item', 'option', {}, classNames)} ref={forwardedRef} />;
125
+ return <SelectPrimitive.Item {...props} className={tx('select.item', {}, classNames)} ref={forwardedRef} />;
130
126
  });
131
127
 
132
128
  type SelectItemTextProps = SelectPrimitive.SelectItemTextProps;
@@ -141,7 +137,7 @@ const SelectItemIndicator = forwardRef<HTMLDivElement, SelectItemIndicatorProps>
141
137
  return (
142
138
  <SelectPrimitive.ItemIndicator
143
139
  {...props}
144
- className={tx('select.itemIndicator', 'option__indicator', {}, classNames)}
140
+ className={tx('select.itemIndicator', {}, classNames)}
145
141
  ref={forwardedRef}
146
142
  >
147
143
  {children}
@@ -156,7 +152,7 @@ type SelectOptionProps = SelectItemProps;
156
152
  const SelectOption = forwardRef<HTMLDivElement, SelectItemProps>(({ children, classNames, ...props }, forwardedRef) => {
157
153
  const { tx } = useThemeContext();
158
154
  return (
159
- <SelectPrimitive.Item {...props} className={tx('select.item', 'option', {}, classNames)} ref={forwardedRef}>
155
+ <SelectPrimitive.Item {...props} className={tx('select.item', {}, classNames)} ref={forwardedRef}>
160
156
  <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
161
157
  <span className='grow w-1' />
162
158
  {/* <SelectPrimitive.ItemIndicator className={tx('select.itemIndicator', 'option__indicator', {})}> */}
@@ -178,26 +174,14 @@ type SelectSeparatorProps = ThemedClassName<SelectPrimitive.SelectSeparatorProps
178
174
 
179
175
  const SelectSeparator = forwardRef<HTMLDivElement, SelectSeparatorProps>(({ classNames, ...props }, forwardedRef) => {
180
176
  const { tx } = useThemeContext();
181
- return (
182
- <SelectPrimitive.Separator
183
- {...props}
184
- className={tx('select.separator', 'select__separator', {}, classNames)}
185
- ref={forwardedRef}
186
- />
187
- );
177
+ return <SelectPrimitive.Separator {...props} className={tx('select.separator', {}, classNames)} ref={forwardedRef} />;
188
178
  });
189
179
 
190
180
  type SelectArrowProps = ThemedClassName<SelectPrimitive.SelectArrowProps>;
191
181
 
192
182
  const SelectArrow = forwardRef<SVGSVGElement, SelectArrowProps>(({ classNames, ...props }, forwardedRef) => {
193
183
  const { tx } = useThemeContext();
194
- return (
195
- <SelectPrimitive.Arrow
196
- {...props}
197
- className={tx('select.arrow', 'select__arrow', {}, classNames)}
198
- ref={forwardedRef}
199
- />
200
- );
184
+ return <SelectPrimitive.Arrow {...props} className={tx('select.arrow', {}, classNames)} ref={forwardedRef} />;
201
185
  });
202
186
 
203
187
  export const Select = {
@@ -19,7 +19,7 @@ const Separator = forwardRef<HTMLDivElement, SeparatorProps>(
19
19
  <SeparatorPrimitive
20
20
  orientation={orientation}
21
21
  {...props}
22
- className={tx('separator.root', 'separator', { orientation, subdued }, classNames)}
22
+ className={tx('separator.root', { orientation, subdued }, classNames)}
23
23
  ref={forwardedRef}
24
24
  />
25
25
  );