@dxos/react-ui 0.8.4-main.40e3dcdf1b → 0.8.4-main.422d1c7879

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 (250) hide show
  1. package/dist/lib/browser/{chunk-2FKSMWNY.mjs → chunk-OCVRIJCH.mjs} +79 -5
  2. package/dist/lib/browser/chunk-OCVRIJCH.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +905 -700
  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 +30 -18
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-ZNBLTSHI.mjs → chunk-QUD5P3RU.mjs} +79 -5
  9. package/dist/lib/node-esm/chunk-QUD5P3RU.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +905 -700
  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 +30 -18
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/Avatars/Avatar.d.ts +1 -1
  16. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  17. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
  20. package/dist/types/src/components/Button/Button.d.ts +2 -2
  21. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  22. package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  24. package/dist/types/src/components/Button/IconButton.stories.d.ts +3 -0
  25. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/Button/Toggle.d.ts +2 -2
  27. package/dist/types/src/components/Button/Toggle.d.ts.map +1 -1
  28. package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Button/ToggleGroup.d.ts +6 -6
  30. package/dist/types/src/components/Button/ToggleGroup.d.ts.map +1 -1
  31. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/Card/Card.d.ts +69 -49
  33. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  34. package/dist/types/src/components/Card/Card.stories.d.ts +2 -2
  35. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  37. package/dist/types/src/components/Clipboard/index.d.ts +10 -1
  38. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  39. package/dist/types/src/components/Dialog/AlertDialog.d.ts +39 -28
  40. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  41. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/Dialog/Dialog.d.ts +44 -27
  43. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  44. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +3 -2
  45. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  46. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts +14 -3
  48. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
  49. package/dist/types/src/components/Focus/Focus.d.ts +36 -0
  50. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -0
  51. package/dist/types/src/components/Focus/Focus.stories.d.ts +9 -0
  52. package/dist/types/src/components/Focus/Focus.stories.d.ts.map +1 -0
  53. package/dist/types/src/components/Focus/index.d.ts +2 -0
  54. package/dist/types/src/components/Focus/index.d.ts.map +1 -0
  55. package/dist/types/src/components/Icon/Icon.d.ts +3 -0
  56. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  57. package/dist/types/src/components/Icon/Icon.stories.d.ts +11 -3
  58. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/Image/Image.d.ts +2 -1
  60. package/dist/types/src/components/Image/Image.d.ts.map +1 -1
  61. package/dist/types/src/components/Image/Image.stories.d.ts +2 -1
  62. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -1
  63. package/dist/types/src/components/Input/Input.d.ts +2 -2
  64. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  65. package/dist/types/src/components/Input/Input.stories.d.ts +3 -3
  66. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  67. package/dist/types/src/components/Link/Link.stories.d.ts.map +1 -1
  68. package/dist/types/src/components/List/List.d.ts +5 -3
  69. package/dist/types/src/components/List/List.d.ts.map +1 -1
  70. package/dist/types/src/components/List/List.stories.d.ts +3 -1
  71. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  72. package/dist/types/src/components/List/Tree.d.ts.map +1 -1
  73. package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -1
  74. package/dist/types/src/components/List/Treegrid.d.ts +5 -9
  75. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
  76. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -1
  77. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  78. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  79. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -1
  80. package/dist/types/src/components/Menu/DropdownMenu.d.ts +51 -50
  81. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  82. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts +14 -1
  83. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
  84. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  85. package/dist/types/src/components/Message/Message.stories.d.ts +2 -2
  86. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  87. package/dist/types/src/components/Popover/Popover.d.ts +31 -23
  88. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  89. package/dist/types/src/components/Popover/Popover.stories.d.ts.map +1 -1
  90. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +12 -9
  91. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  92. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +18 -5
  93. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  94. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +34 -13
  95. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  96. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +5 -6
  97. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  98. package/dist/types/src/components/Select/Select.stories.d.ts +2 -2
  99. package/dist/types/src/components/Select/Select.stories.d.ts.map +1 -1
  100. package/dist/types/src/components/Separator/Separator.d.ts +3 -3
  101. package/dist/types/src/components/Separator/Separator.d.ts.map +1 -1
  102. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/Splitter/Splitter.d.ts +19 -17
  104. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -1
  105. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -1
  106. package/dist/types/src/components/Status/Status.d.ts +3 -4
  107. package/dist/types/src/components/Status/Status.d.ts.map +1 -1
  108. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  109. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  110. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -1
  111. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  112. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts +1 -1
  113. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  114. package/dist/types/src/components/Toast/Toast.d.ts +15 -15
  115. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  116. package/dist/types/src/components/Toast/Toast.stories.d.ts.map +1 -1
  117. package/dist/types/src/components/Toolbar/Toolbar.d.ts +8 -16
  118. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  119. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  120. package/dist/types/src/components/Tooltip/Tooltip.d.ts +9 -9
  121. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  122. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +2 -2
  123. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  124. package/dist/types/src/components/index.d.ts +1 -0
  125. package/dist/types/src/components/index.d.ts.map +1 -1
  126. package/dist/types/src/exemplars/generics.stories.d.ts +6 -5
  127. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -1
  128. package/dist/types/src/exemplars/slot.stories.d.ts +1 -0
  129. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -1
  130. package/dist/types/src/hooks/index.d.ts +1 -0
  131. package/dist/types/src/hooks/index.d.ts.map +1 -1
  132. package/dist/types/src/hooks/useDensityContext.d.ts +1 -1
  133. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  134. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
  135. package/dist/types/src/primitives/Column/Column.d.ts +21 -14
  136. package/dist/types/src/primitives/Column/Column.d.ts.map +1 -1
  137. package/dist/types/src/primitives/Column/Column.stories.d.ts +19 -0
  138. package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -1
  139. package/dist/types/src/primitives/Container/Container.d.ts +4 -5
  140. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -1
  141. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -1
  142. package/dist/types/src/primitives/Flex/Flex.d.ts +5 -7
  143. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -1
  144. package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -1
  145. package/dist/types/src/primitives/Grid/Grid.d.ts +3 -8
  146. package/dist/types/src/primitives/Grid/Grid.d.ts.map +1 -1
  147. package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -1
  148. package/dist/types/src/primitives/Panel/Panel.d.ts +24 -15
  149. package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -1
  150. package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -1
  151. package/dist/types/src/testing/Loading.d.ts.map +1 -1
  152. package/dist/types/src/testing/decorators/withTheme.d.ts +1 -1
  153. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  154. package/dist/types/src/translations.d.ts +3 -3
  155. package/dist/types/src/util/usePx.d.ts.map +1 -1
  156. package/dist/types/tsconfig.tsbuildinfo +1 -1
  157. package/package.json +18 -24
  158. package/src/components/Avatars/Avatar.stories.tsx +2 -3
  159. package/src/components/Avatars/Avatar.tsx +1 -2
  160. package/src/components/Avatars/AvatarGroup.stories.tsx +0 -1
  161. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -2
  162. package/src/components/Button/Button.stories.tsx +0 -1
  163. package/src/components/Button/Button.tsx +5 -13
  164. package/src/components/Button/IconButton.stories.tsx +6 -4
  165. package/src/components/Button/IconButton.tsx +1 -3
  166. package/src/components/Button/Toggle.stories.tsx +0 -1
  167. package/src/components/Button/Toggle.tsx +4 -4
  168. package/src/components/Button/ToggleGroup.stories.tsx +0 -1
  169. package/src/components/Button/ToggleGroup.tsx +12 -16
  170. package/src/components/Card/Card.stories.tsx +12 -12
  171. package/src/components/Card/Card.tsx +266 -108
  172. package/src/components/Clipboard/CopyButton.tsx +3 -4
  173. package/src/components/Dialog/AlertDialog.stories.tsx +5 -6
  174. package/src/components/Dialog/AlertDialog.tsx +67 -126
  175. package/src/components/Dialog/Dialog.stories.tsx +64 -9
  176. package/src/components/Dialog/Dialog.tsx +84 -88
  177. package/src/components/ErrorFallback/ErrorFallback.stories.tsx +3 -8
  178. package/src/components/ErrorFallback/ErrorStack.tsx +36 -2
  179. package/src/components/Focus/AUDIT.md +43 -0
  180. package/src/components/Focus/Focus.stories.tsx +230 -0
  181. package/src/components/Focus/Focus.tsx +201 -0
  182. package/src/components/Focus/index.ts +5 -0
  183. package/src/components/Icon/Icon.stories.tsx +43 -13
  184. package/src/components/Icon/Icon.tsx +5 -1
  185. package/src/components/Image/Image.stories.tsx +3 -3
  186. package/src/components/Image/Image.tsx +16 -3
  187. package/src/components/Input/Input.stories.tsx +3 -4
  188. package/src/components/Input/Input.tsx +7 -7
  189. package/src/components/Link/Link.stories.tsx +0 -1
  190. package/src/components/List/List.stories.tsx +0 -1
  191. package/src/components/List/List.tsx +6 -5
  192. package/src/components/List/Tree.stories.tsx +1 -2
  193. package/src/components/List/Tree.tsx +0 -1
  194. package/src/components/List/Treegrid.stories.tsx +26 -27
  195. package/src/components/List/Treegrid.tsx +14 -14
  196. package/src/components/Main/Main.stories.tsx +0 -1
  197. package/src/components/Main/Main.tsx +1 -2
  198. package/src/components/Menu/ContextMenu.stories.tsx +0 -1
  199. package/src/components/Menu/DropdownMenu.stories.tsx +0 -1
  200. package/src/components/Menu/DropdownMenu.tsx +48 -42
  201. package/src/components/Message/Message.stories.tsx +6 -7
  202. package/src/components/Message/Message.tsx +1 -5
  203. package/src/components/Popover/Popover.stories.tsx +4 -5
  204. package/src/components/Popover/Popover.tsx +42 -42
  205. package/src/components/ScrollArea/ScrollArea.stories.tsx +93 -30
  206. package/src/components/ScrollArea/ScrollArea.tsx +39 -23
  207. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +20 -18
  208. package/src/components/ScrollContainer/ScrollContainer.tsx +200 -91
  209. package/src/components/Select/Select.stories.tsx +5 -6
  210. package/src/components/Separator/Separator.tsx +4 -7
  211. package/src/components/Skeleton/Skeleton.stories.tsx +0 -1
  212. package/src/components/Splitter/Splitter.stories.tsx +29 -29
  213. package/src/components/Splitter/Splitter.tsx +35 -34
  214. package/src/components/Status/Status.stories.tsx +0 -1
  215. package/src/components/Status/Status.tsx +8 -5
  216. package/src/components/Tag/Tag.stories.tsx +0 -1
  217. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +0 -1
  218. package/src/components/ThemeProvider/ThemeProvider.tsx +5 -4
  219. package/src/components/Toast/Toast.stories.tsx +0 -1
  220. package/src/components/Toast/Toast.tsx +16 -31
  221. package/src/components/Toolbar/Toolbar.stories.tsx +0 -1
  222. package/src/components/Toolbar/Toolbar.tsx +19 -34
  223. package/src/components/Tooltip/Tooltip.stories.tsx +6 -7
  224. package/src/components/Tooltip/Tooltip.tsx +15 -16
  225. package/src/components/index.ts +1 -0
  226. package/src/exemplars/generics.stories.tsx +7 -15
  227. package/src/exemplars/slot.stories.tsx +67 -57
  228. package/src/exemplars/tabster.stories.tsx +1 -1
  229. package/src/exemplars/virtualizer.stories.tsx +4 -4
  230. package/src/hooks/index.ts +1 -0
  231. package/src/hooks/useDensityContext.ts +2 -2
  232. package/src/playground/Custom.stories.tsx +6 -9
  233. package/src/primitives/Column/AUDIT.md +148 -0
  234. package/src/primitives/Column/Column.stories.tsx +122 -19
  235. package/src/primitives/Column/Column.tsx +73 -42
  236. package/src/primitives/Container/Container.stories.tsx +0 -1
  237. package/src/primitives/Container/Container.tsx +5 -8
  238. package/src/primitives/Flex/Flex.stories.tsx +0 -1
  239. package/src/primitives/Flex/Flex.tsx +10 -12
  240. package/src/primitives/Grid/Grid.stories.tsx +0 -1
  241. package/src/primitives/Grid/Grid.tsx +4 -9
  242. package/src/primitives/Panel/Panel.stories.tsx +9 -8
  243. package/src/primitives/Panel/Panel.tsx +64 -63
  244. package/src/testing/Loading.tsx +25 -4
  245. package/src/testing/decorators/withLayout.tsx +6 -6
  246. package/src/testing/decorators/withTheme.tsx +10 -7
  247. package/src/translations.ts +3 -3
  248. package/src/util/usePx.ts +1 -0
  249. package/dist/lib/browser/chunk-2FKSMWNY.mjs.map +0 -7
  250. package/dist/lib/node-esm/chunk-ZNBLTSHI.mjs.map +0 -7
@@ -2,16 +2,18 @@
2
2
  // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
- import React, { useMemo } from 'react';
5
+ import React, { PropsWithChildren, useMemo } from 'react';
6
6
 
7
- import { faker } from '@dxos/random';
7
+ import { random } from '@dxos/random';
8
8
  import { mx } from '@dxos/ui-theme';
9
+ import { ThemedClassName } from '@dxos/ui-types';
9
10
 
11
+ import { Column } from '../../primitives';
10
12
  import { withLayout, withTheme } from '../../testing';
11
-
13
+ import { Input } from '../Input';
12
14
  import { ScrollArea } from './ScrollArea';
13
15
 
14
- faker.seed(123);
16
+ random.seed(123);
15
17
 
16
18
  export default {
17
19
  title: 'ui/react-ui-core/components/ScrollArea',
@@ -22,22 +24,22 @@ export default {
22
24
  },
23
25
  };
24
26
 
25
- const Column = () => (
27
+ const List = ({ items = 50 }: { items?: number }) => (
26
28
  <div>
27
- {Array.from({ length: 50 }).map((_, index) => (
28
- <div key={index} className='px-1 text-sm cursor-pointer hover:bg-hover-surface'>
29
+ {Array.from({ length: items }).map((_, index) => (
30
+ <div key={index} className='px-1 cursor-pointer hover:bg-hover-surface'>
29
31
  Item {index + 1}
30
32
  </div>
31
33
  ))}
32
34
  </div>
33
35
  );
34
36
 
35
- const Row = () => (
37
+ const Row = ({ items = 50 }: { items?: number }) => (
36
38
  <div className='flex gap-2 w-max'>
37
- {Array.from({ length: 50 }).map((_, index) => (
39
+ {Array.from({ length: items }).map((_, index) => (
38
40
  <div
39
41
  key={index}
40
- className='shrink-0 h-20 w-20 cursor-pointer border border-separator rounded-md flex items-center justify-center text-sm hover:bg-hover-surface'
42
+ className='shrink-0 h-20 w-20 cursor-pointer border border-separator rounded-md flex items-center justify-center hover:bg-hover-surface'
41
43
  >
42
44
  {index + 1}
43
45
  </div>
@@ -45,58 +47,95 @@ const Row = () => (
45
47
  </div>
46
48
  );
47
49
 
50
+ const Container = ({ classNames, children }: ThemedClassName<PropsWithChildren>) => {
51
+ return (
52
+ <div role='none' className={mx('border border-separator rounded-md overflow-hidden', classNames)}>
53
+ {children}
54
+ </div>
55
+ );
56
+ };
57
+
48
58
  export const Vertical = {
49
59
  render: () => (
50
- <div className='h-72 w-48 p-2 border border-separator rounded-md'>
51
- <ScrollArea.Root orientation='vertical' padding>
60
+ <Container classNames='h-72 w-48'>
61
+ <ScrollArea.Root orientation='vertical'>
52
62
  <ScrollArea.Viewport>
53
- <Column />
63
+ <List />
54
64
  </ScrollArea.Viewport>
55
65
  </ScrollArea.Root>
56
- </div>
66
+ </Container>
57
67
  ),
58
68
  };
59
69
 
60
70
  export const VerticalThin = {
61
71
  render: () => (
62
- <div className='h-72 w-48 p-2 border border-separator rounded-md'>
63
- <ScrollArea.Root orientation='vertical' padding thin>
72
+ <Container classNames='h-72 w-48'>
73
+ <ScrollArea.Root orientation='vertical' thin>
64
74
  <ScrollArea.Viewport>
65
- <Column />
75
+ <List />
66
76
  </ScrollArea.Viewport>
67
77
  </ScrollArea.Root>
68
- </div>
78
+ </Container>
79
+ ),
80
+ };
81
+
82
+ export const VerticalPadded = {
83
+ render: () => (
84
+ <Container classNames='h-72 w-48'>
85
+ <ScrollArea.Root orientation='vertical' centered padding thin>
86
+ <ScrollArea.Viewport>
87
+ <List />
88
+ </ScrollArea.Viewport>
89
+ </ScrollArea.Root>
90
+ </Container>
91
+ ),
92
+ };
93
+
94
+ export const VerticalColumn = {
95
+ render: () => (
96
+ <Container classNames='h-72 w-48'>
97
+ <Column.Root gutter='sm' classNames='h-full overflow-hidden'>
98
+ <ScrollArea.Root orientation='vertical' padding thin>
99
+ <ScrollArea.Viewport classNames='py-2'>
100
+ <Input.Root>
101
+ <Input.TextInput classNames='p-1' />
102
+ </Input.Root>
103
+ <List />
104
+ </ScrollArea.Viewport>
105
+ </ScrollArea.Root>
106
+ </Column.Root>
107
+ </Container>
69
108
  ),
70
109
  };
71
110
 
72
111
  export const Horizontal = {
73
112
  render: () => (
74
- <div className='w-96 p-2 border border-separator rounded-md'>
75
- <ScrollArea.Root orientation='horizontal' padding>
113
+ <Container classNames='w-96'>
114
+ <ScrollArea.Root orientation='horizontal'>
76
115
  <ScrollArea.Viewport>
77
116
  <Row />
78
117
  </ScrollArea.Viewport>
79
118
  </ScrollArea.Root>
80
- </div>
119
+ </Container>
81
120
  ),
82
121
  };
83
122
 
84
123
  export const HorizontalThin = {
85
124
  render: () => (
86
- <div className='w-96 p-2 border border-separator rounded-md'>
87
- <ScrollArea.Root orientation='horizontal' padding thin>
125
+ <Container classNames='w-96'>
126
+ <ScrollArea.Root orientation='horizontal' thin>
88
127
  <ScrollArea.Viewport>
89
128
  <Row />
90
129
  </ScrollArea.Viewport>
91
130
  </ScrollArea.Root>
92
- </div>
131
+ </Container>
93
132
  ),
94
133
  };
95
134
 
96
135
  export const Both = {
97
136
  render: () => (
98
- <div className='h-96 w-96 p-2 border border-separator rounded-md'>
99
- <ScrollArea.Root orientation='all' padding>
137
+ <Container classNames='w-96 h-96'>
138
+ <ScrollArea.Root orientation='all'>
100
139
  <ScrollArea.Viewport>
101
140
  <div className='flex flex-col gap-2'>
102
141
  {Array.from({ length: 50 }).map((_, rowIndex) => (
@@ -114,7 +153,31 @@ export const Both = {
114
153
  </div>
115
154
  </ScrollArea.Viewport>
116
155
  </ScrollArea.Root>
117
- </div>
156
+ </Container>
157
+ ),
158
+ };
159
+
160
+ export const Fullscreen = {
161
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
162
+ render: () => (
163
+ <ScrollArea.Root orientation='all' thin>
164
+ <ScrollArea.Viewport>
165
+ <div className='flex flex-col gap-2'>
166
+ {Array.from({ length: 50 }).map((_, rowIndex) => (
167
+ <div key={rowIndex} className='flex gap-2'>
168
+ {Array.from({ length: 50 }).map((_, colIndex) => (
169
+ <div
170
+ key={colIndex}
171
+ className='shrink-0 h-20 w-20 flex items-center justify-center text-sm border border-separator font-mono'
172
+ >
173
+ [{colIndex}:{rowIndex}]
174
+ </div>
175
+ ))}
176
+ </div>
177
+ ))}
178
+ </div>
179
+ </ScrollArea.Viewport>
180
+ </ScrollArea.Root>
118
181
  ),
119
182
  };
120
183
 
@@ -125,13 +188,13 @@ export const NestedScrollAreas = {
125
188
  () =>
126
189
  Array.from({ length: 8 }).map((_, index) => ({
127
190
  id: String(index),
128
- count: faker.number.int({ min: 5, max: 20 }),
191
+ count: random.number.int({ min: 5, max: 20 }),
129
192
  })),
130
193
  [],
131
194
  );
132
195
 
133
196
  return (
134
- <ScrollArea.Root thin orientation='horizontal'>
197
+ <ScrollArea.Root orientation='horizontal' thin padding>
135
198
  <ScrollArea.Viewport classNames='gap-4'>
136
199
  {columns.map((column) => (
137
200
  <section
@@ -170,7 +233,7 @@ export const NativeScroll = {
170
233
  'group-hover:[&::-webkit-scrollbar-thumb]:bg-scrollbar-thumb',
171
234
  )}
172
235
  >
173
- <Column />
236
+ <List />
174
237
  </div>
175
238
  </div>
176
239
  ),
@@ -5,10 +5,10 @@
5
5
  import { createContext } from '@radix-ui/react-context';
6
6
  import { Primitive } from '@radix-ui/react-primitive';
7
7
  import { Slot } from '@radix-ui/react-slot';
8
- import React, { type HTMLAttributes, forwardRef } from 'react';
8
+ import React, { CSSProperties, useMemo } from 'react';
9
9
 
10
- import { composableProps } from '@dxos/ui-theme';
11
- import { type AllowedAxis, type SlottableProps, type ThemedClassName } from '@dxos/ui-types';
10
+ import { composableProps, scrollbar, slottable } from '@dxos/ui-theme';
11
+ import { type AllowedAxis, type SlottableProps } from '@dxos/ui-types';
12
12
 
13
13
  import { useThemeContext } from '../../hooks';
14
14
 
@@ -24,7 +24,7 @@ type ScrollAreaContextType = {
24
24
  /** Hide scrollbars when not scrolling. */
25
25
  autoHide: boolean;
26
26
  /** Apply padding to opposite side of scrollbar. */
27
- margin?: boolean;
27
+ centered?: boolean;
28
28
  /** Apply padding. */
29
29
  padding: boolean;
30
30
  /** Use thin scrollbars. */
@@ -41,19 +41,19 @@ const [ScrollAreaProvider, useScrollAreaContext] = createContext<ScrollAreaConte
41
41
 
42
42
  const SCROLLAREA_ROOT_NAME = 'ScrollArea.Root';
43
43
 
44
- type ScrollAreaRootProps = SlottableProps<HTMLDivElement, Partial<ScrollAreaContextType>>;
44
+ type ScrollAreaRootProps = Partial<ScrollAreaContextType>;
45
45
 
46
46
  /**
47
47
  * ScrollArea provides native scrollbars with custom styling.
48
48
  */
49
- const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(
49
+ const ScrollAreaRoot = slottable<HTMLDivElement, ScrollAreaRootProps>(
50
50
  (
51
51
  {
52
52
  children,
53
53
  asChild,
54
54
  orientation = 'vertical',
55
55
  autoHide = true,
56
- margin = false,
56
+ centered = false,
57
57
  padding = false,
58
58
  thin = false,
59
59
  snap = false,
@@ -61,10 +61,13 @@ const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(
61
61
  },
62
62
  forwardedRef,
63
63
  ) => {
64
+ const { tx } = useThemeContext();
64
65
  const { className, ...rest } = composableProps(props);
65
66
  const Comp = asChild ? Slot : Primitive.div;
66
- const { tx } = useThemeContext();
67
- const options = { orientation, autoHide, margin, padding, thin, snap };
67
+ const options = useMemo(
68
+ () => ({ orientation, autoHide, centered, padding, thin, snap }),
69
+ [orientation, autoHide, centered, padding, thin, snap],
70
+ );
68
71
 
69
72
  return (
70
73
  <ScrollAreaProvider {...options}>
@@ -84,20 +87,33 @@ ScrollAreaRoot.displayName = SCROLLAREA_ROOT_NAME;
84
87
 
85
88
  const SCROLLAREA_VIEWPORT_NAME = 'ScrollArea.Viewport';
86
89
 
87
- type ScrollAreaViewportProps = ThemedClassName<HTMLAttributes<HTMLDivElement>>;
88
-
89
- const ScrollAreaViewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(
90
- ({ classNames, children, ...props }, forwardedRef) => {
91
- const { tx } = useThemeContext();
92
- const options = useScrollAreaContext(SCROLLAREA_VIEWPORT_NAME);
93
-
94
- return (
95
- <div {...props} className={tx('scrollArea.viewport', options, classNames)} ref={forwardedRef}>
96
- {children}
97
- </div>
98
- );
99
- },
100
- );
90
+ type ScrollAreaViewportProps = SlottableProps;
91
+
92
+ const ScrollAreaViewport = slottable<HTMLDivElement>(({ children, asChild, ...props }, forwardedRef) => {
93
+ const { tx } = useThemeContext();
94
+ const options = useScrollAreaContext(SCROLLAREA_VIEWPORT_NAME);
95
+ const density = options.thin ? scrollbar.thin : scrollbar.coarse;
96
+ const { className, ...rest } = composableProps(props);
97
+ const { style, ...restWithoutStyle } = rest as { style?: CSSProperties; [key: string]: any };
98
+ const Comp = asChild ? Slot : Primitive.div;
99
+
100
+ return (
101
+ <Comp
102
+ {...restWithoutStyle}
103
+ style={
104
+ {
105
+ '--scroll-width': `${density.size}px`,
106
+ '--scroll-padding': `${density.padding}px`,
107
+ ...style,
108
+ } as CSSProperties
109
+ }
110
+ className={tx('scrollArea.viewport', options, className)}
111
+ ref={forwardedRef}
112
+ >
113
+ {children}
114
+ </Comp>
115
+ );
116
+ });
101
117
 
102
118
  ScrollAreaViewport.displayName = SCROLLAREA_VIEWPORT_NAME;
103
119
 
@@ -5,23 +5,22 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useEffect, useRef, useState } from 'react';
7
7
 
8
- import { faker } from '@dxos/random';
8
+ import { random } from '@dxos/random';
9
9
 
10
10
  import { Panel } from '../../primitives';
11
11
  import { withLayout, withTheme } from '../../testing';
12
12
  import { Button } from '../Button';
13
13
  import { Toolbar } from '../Toolbar';
14
-
15
14
  import { ScrollContainer, type ScrollContainerRootProps, type ScrollController } from './ScrollContainer';
16
15
 
17
- type StoryProps = ScrollContainerRootProps & { running?: boolean; initialLines?: number };
16
+ type DefaultStoryProps = ScrollContainerRootProps & { running?: boolean; initialLines?: number };
18
17
 
19
- const DefaultStory = ({ initialLines = 0, running: runningProp, ...props }: StoryProps) => {
18
+ const DefaultStory = ({ initialLines = 0, running: runningProp, ...props }: DefaultStoryProps) => {
20
19
  const [lines, setLines] = useState<string[]>([]);
21
20
  const [running, setRunning] = useState(runningProp);
22
21
  const scroller = useRef<ScrollController>(null);
23
22
  useEffect(() => {
24
- setLines(Array.from({ length: initialLines }, () => faker.lorem.paragraph()));
23
+ setLines(Array.from({ length: initialLines }, () => random.lorem.paragraph()));
25
24
  }, [initialLines]);
26
25
  useEffect(() => {
27
26
  if (!running) {
@@ -29,14 +28,14 @@ const DefaultStory = ({ initialLines = 0, running: runningProp, ...props }: Stor
29
28
  }
30
29
 
31
30
  const i = setInterval(() => {
32
- setLines((lines) => [...lines, faker.lorem.paragraph()]);
31
+ setLines((lines) => [...lines, random.lorem.paragraph()]);
33
32
  }, 500);
34
33
 
35
34
  return () => clearInterval(i);
36
35
  }, [running]);
37
36
 
38
37
  return (
39
- <Panel.Root className='dx-article'>
38
+ <Panel.Root className='dx-document'>
40
39
  <Panel.Toolbar asChild>
41
40
  <Toolbar.Root>
42
41
  <Button onClick={() => setRunning((running) => !running)}>{running ? 'Stop' : 'Start'}</Button>
@@ -45,16 +44,19 @@ const DefaultStory = ({ initialLines = 0, running: runningProp, ...props }: Stor
45
44
  <div className='px-1'>{lines.length}</div>
46
45
  </Toolbar.Root>
47
46
  </Panel.Toolbar>
48
- <Panel.Content asChild>
47
+ <Panel.Content>
49
48
  <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 />
49
+ <ScrollContainer.Content>
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.Fade />
59
+ </ScrollContainer.Content>
58
60
  </ScrollContainer.Root>
59
61
  </Panel.Content>
60
62
  </Panel.Root>
@@ -75,7 +77,7 @@ type Story = StoryObj<typeof meta>;
75
77
  export const Default: Story = {
76
78
  args: {
77
79
  pin: true,
78
- fade: true,
80
+
79
81
  running: true,
80
82
  },
81
83
  };
@@ -83,7 +85,7 @@ export const Default: Story = {
83
85
  export const Large: Story = {
84
86
  args: {
85
87
  pin: true,
86
- fade: true,
88
+
87
89
  initialLines: 100,
88
90
  },
89
91
  };