@dxos/react-ui 0.8.4-main.21d9917 → 0.8.4-main.2244d791bb

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 (183) hide show
  1. package/dist/lib/browser/{chunk-CEKVHJ27.mjs → chunk-6DTBPJE4.mjs} +4 -4
  2. package/dist/lib/browser/chunk-6DTBPJE4.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +456 -309
  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 +5 -4
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-2NHEX4AD.mjs → chunk-JKHQSGNU.mjs} +4 -4
  9. package/dist/lib/node-esm/chunk-JKHQSGNU.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +456 -309
  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 +5 -4
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts +7 -0
  16. package/dist/types/src/components/AnchoredOverflow/AnchoredOverflow.d.ts.map +1 -1
  17. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  18. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  19. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  20. package/dist/types/src/components/Dialog/AlertDialog.d.ts +4 -2
  21. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  22. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Dialog/Dialog.d.ts +7 -1
  24. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  25. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +1 -5
  26. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  28. package/dist/types/src/components/Input/Input.stories.d.ts +1 -1
  29. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  30. package/dist/types/src/components/List/List.d.ts.map +1 -1
  31. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
  32. package/dist/types/src/components/Main/Main.d.ts +8 -9
  33. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  34. package/dist/types/src/components/Main/Main.stories.d.ts +0 -3
  35. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
  37. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  38. package/dist/types/src/components/Message/Message.stories.d.ts +2 -3
  39. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  40. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +23 -26
  41. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  42. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +43 -9
  43. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  45. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +6 -1
  46. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  48. package/dist/types/src/components/Skeleton/Skeleton.d.ts +12 -0
  49. package/dist/types/src/components/Skeleton/Skeleton.d.ts.map +1 -0
  50. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts +17 -0
  51. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -0
  52. package/dist/types/src/components/Skeleton/index.d.ts +2 -0
  53. package/dist/types/src/components/Skeleton/index.d.ts.map +1 -0
  54. package/dist/types/src/components/Splitter/Splitter.d.ts +26 -0
  55. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -0
  56. package/dist/types/src/components/Splitter/Splitter.stories.d.ts +7 -0
  57. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -0
  58. package/dist/types/src/components/Splitter/index.d.ts +2 -0
  59. package/dist/types/src/components/Splitter/index.d.ts.map +1 -0
  60. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  61. package/dist/types/src/components/Tag/Tag.stories.d.ts +1 -5
  62. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  63. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts +1 -0
  64. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  65. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  66. package/dist/types/src/components/Toolbar/Toolbar.d.ts +7 -6
  67. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  68. package/dist/types/src/components/index.d.ts +2 -0
  69. package/dist/types/src/components/index.d.ts.map +1 -1
  70. package/dist/types/src/exemplars/generics.stories.d.ts +17 -0
  71. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -0
  72. package/dist/types/src/exemplars/slot.stories.d.ts +14 -0
  73. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -0
  74. package/dist/types/src/exemplars/tabster.stories.d.ts +8 -0
  75. package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -0
  76. package/dist/types/src/exemplars/virtualizer.stories.d.ts +11 -0
  77. package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -0
  78. package/dist/types/src/index.d.ts +1 -0
  79. package/dist/types/src/index.d.ts.map +1 -1
  80. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  81. package/dist/types/src/primitives/Container/Container.d.ts +23 -0
  82. package/dist/types/src/primitives/Container/Container.d.ts.map +1 -0
  83. package/dist/types/src/primitives/Container/Container.stories.d.ts +11 -0
  84. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -0
  85. package/dist/types/src/primitives/Container/Layout.d.ts +18 -0
  86. package/dist/types/src/primitives/Container/Layout.d.ts.map +1 -0
  87. package/dist/types/src/primitives/Container/Layout.stories.d.ts +10 -0
  88. package/dist/types/src/primitives/Container/Layout.stories.d.ts.map +1 -0
  89. package/dist/types/src/primitives/Container/index.d.ts +3 -0
  90. package/dist/types/src/primitives/Container/index.d.ts.map +1 -0
  91. package/dist/types/src/primitives/Flex/Flex.d.ts +8 -0
  92. package/dist/types/src/primitives/Flex/Flex.d.ts.map +1 -0
  93. package/dist/types/src/primitives/Flex/index.d.ts +2 -0
  94. package/dist/types/src/primitives/Flex/index.d.ts.map +1 -0
  95. package/dist/types/src/primitives/index.d.ts +3 -0
  96. package/dist/types/src/primitives/index.d.ts.map +1 -0
  97. package/dist/types/src/testing/decorators/withTheme.d.ts +3 -2
  98. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  99. package/dist/types/tsconfig.tsbuildinfo +1 -1
  100. package/package.json +23 -22
  101. package/src/components/AnchoredOverflow/AnchoredOverflow.tsx +10 -12
  102. package/src/components/Avatars/Avatar.stories.tsx +2 -2
  103. package/src/components/Avatars/Avatar.tsx +2 -9
  104. package/src/components/Avatars/AvatarGroup.stories.tsx +2 -2
  105. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +2 -2
  106. package/src/components/Breadcrumb/Breadcrumb.tsx +5 -31
  107. package/src/components/Button/Button.stories.tsx +3 -3
  108. package/src/components/Button/Button.tsx +1 -7
  109. package/src/components/Button/IconButton.stories.tsx +2 -2
  110. package/src/components/Button/IconButton.tsx +1 -1
  111. package/src/components/Button/Toggle.stories.tsx +2 -2
  112. package/src/components/Button/ToggleGroup.stories.tsx +2 -2
  113. package/src/components/Dialog/AlertDialog.stories.tsx +6 -7
  114. package/src/components/Dialog/AlertDialog.tsx +78 -9
  115. package/src/components/Dialog/Dialog.stories.tsx +11 -11
  116. package/src/components/Dialog/Dialog.tsx +44 -19
  117. package/src/components/Icon/Icon.stories.tsx +2 -2
  118. package/src/components/Icon/Icon.tsx +1 -1
  119. package/src/components/Input/Input.stories.tsx +11 -10
  120. package/src/components/Input/Input.tsx +10 -25
  121. package/src/components/Link/Link.stories.tsx +2 -2
  122. package/src/components/Link/Link.tsx +1 -1
  123. package/src/components/List/List.stories.tsx +2 -2
  124. package/src/components/List/List.tsx +7 -13
  125. package/src/components/List/Tree.stories.tsx +2 -2
  126. package/src/components/List/Treegrid.stories.tsx +2 -2
  127. package/src/components/List/Treegrid.tsx +4 -9
  128. package/src/components/Main/Main.stories.tsx +41 -23
  129. package/src/components/Main/Main.tsx +128 -71
  130. package/src/components/Menu/ContextMenu.stories.tsx +2 -2
  131. package/src/components/Menu/ContextMenu.tsx +7 -31
  132. package/src/components/Menu/DropdownMenu.stories.tsx +2 -2
  133. package/src/components/Menu/DropdownMenu.tsx +8 -8
  134. package/src/components/Message/Message.stories.tsx +23 -8
  135. package/src/components/Message/Message.tsx +8 -21
  136. package/src/components/Popover/Popover.stories.tsx +2 -2
  137. package/src/components/Popover/Popover.tsx +3 -3
  138. package/src/components/ScrollArea/ScrollArea.stories.tsx +152 -76
  139. package/src/components/ScrollArea/ScrollArea.tsx +68 -116
  140. package/src/components/ScrollArea/index.ts +1 -1
  141. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +24 -9
  142. package/src/components/ScrollContainer/ScrollContainer.tsx +14 -9
  143. package/src/components/Select/Select.stories.tsx +2 -2
  144. package/src/components/Select/Select.tsx +9 -25
  145. package/src/components/Separator/Separator.tsx +1 -1
  146. package/src/components/Skeleton/Skeleton.stories.tsx +52 -0
  147. package/src/components/Skeleton/Skeleton.tsx +26 -0
  148. package/src/components/Skeleton/index.ts +5 -0
  149. package/src/components/Splitter/Splitter.stories.tsx +73 -0
  150. package/src/components/Splitter/Splitter.tsx +123 -0
  151. package/src/components/Splitter/index.ts +5 -0
  152. package/src/components/Status/Status.stories.tsx +2 -2
  153. package/src/components/Status/Status.tsx +2 -2
  154. package/src/components/Tag/Tag.stories.tsx +3 -7
  155. package/src/components/Tag/Tag.tsx +1 -6
  156. package/src/components/ThemeProvider/ThemeProvider.tsx +2 -1
  157. package/src/components/Toast/Toast.stories.tsx +2 -2
  158. package/src/components/Toast/Toast.tsx +6 -10
  159. package/src/components/Toolbar/Toolbar.stories.tsx +2 -2
  160. package/src/components/Toolbar/Toolbar.tsx +13 -9
  161. package/src/components/Tooltip/Tooltip.stories.tsx +2 -2
  162. package/src/components/Tooltip/Tooltip.tsx +2 -2
  163. package/src/components/index.ts +2 -0
  164. package/src/exemplars/generics.stories.tsx +44 -0
  165. package/src/exemplars/slot.stories.tsx +108 -0
  166. package/src/exemplars/tabster.stories.tsx +127 -0
  167. package/src/exemplars/virtualizer.stories.tsx +133 -0
  168. package/src/index.ts +1 -0
  169. package/src/playground/Controls.stories.tsx +3 -4
  170. package/src/playground/Custom.stories.tsx +2 -2
  171. package/src/playground/Typography.stories.tsx +2 -2
  172. package/src/primitives/Container/Container.stories.tsx +67 -0
  173. package/src/primitives/Container/Container.tsx +79 -0
  174. package/src/primitives/Container/Layout.stories.tsx +57 -0
  175. package/src/primitives/Container/Layout.tsx +61 -0
  176. package/src/primitives/Container/index.ts +6 -0
  177. package/src/primitives/Flex/Flex.tsx +26 -0
  178. package/src/primitives/Flex/index.ts +5 -0
  179. package/src/primitives/index.ts +6 -0
  180. package/src/testing/decorators/withLayoutVariants.tsx +1 -1
  181. package/src/testing/decorators/withTheme.tsx +19 -17
  182. package/dist/lib/browser/chunk-CEKVHJ27.mjs.map +0 -7
  183. package/dist/lib/node-esm/chunk-2NHEX4AD.mjs.map +0 -7
@@ -22,8 +22,10 @@ import React, {
22
22
  useState,
23
23
  } from 'react';
24
24
 
25
+ import { addEventListener } from '@dxos/async';
25
26
  import { log } from '@dxos/log';
26
27
  import { useForwardedRef, useMediaQuery } from '@dxos/react-hooks';
28
+ import { type MainStyleProps } from '@dxos/ui-theme';
27
29
 
28
30
  import { useThemeContext } from '../../hooks';
29
31
  import { type ThemedClassName } from '../../util';
@@ -33,9 +35,17 @@ import { useSwipeToDismiss } from './useSwipeToDismiss';
33
35
 
34
36
  const MAIN_NAME = 'Main';
35
37
  const MAIN_ROOT_NAME = 'MainRoot';
38
+ const MAIN_OVERLAY_NAME = 'MainOverlay';
36
39
  const NAVIGATION_SIDEBAR_NAME = 'NavigationSidebar';
37
40
  const COMPLEMENTARY_SIDEBAR_NAME = 'ComplementarySidebar';
38
- const GENERIC_CONSUMER_NAME = 'GenericConsumer';
41
+
42
+ const handleOpenAutoFocus = (event: Event) => {
43
+ !document.body.hasAttribute('data-is-keyboard') && event.preventDefault();
44
+ };
45
+
46
+ //
47
+ // Landmark
48
+ //
39
49
 
40
50
  const landmarkAttr = 'data-main-landmark';
41
51
 
@@ -67,40 +77,54 @@ const useLandmarkMover = (propsOnKeyDown: ComponentPropsWithoutRef<'div'>['onKey
67
77
  const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited', ignoreDefaultKeydown: { Tab: true } });
68
78
 
69
79
  return {
70
- onKeyDown: handleKeyDown,
71
80
  [landmarkAttr]: landmark,
72
81
  tabIndex: 0,
82
+ onKeyDown: handleKeyDown,
73
83
  ...focusableGroupAttrs,
74
84
  };
75
85
  };
76
86
 
87
+ //
88
+ // Context
89
+ //
90
+
91
+ // TODO(burdon): Define collapsed state.
77
92
  type SidebarState = 'expanded' | 'collapsed' | 'closed';
78
93
 
79
94
  type MainContextValue = {
80
95
  resizing: boolean;
96
+
97
+ // Navigation
81
98
  navigationSidebarState: SidebarState;
82
99
  setNavigationSidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
100
+
101
+ // Complementary
83
102
  complementarySidebarState: SidebarState;
84
103
  setComplementarySidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
85
104
  };
86
105
 
87
106
  const [MainProvider, useMainContext] = createContext<MainContextValue>(MAIN_NAME, {
88
107
  resizing: false,
108
+
89
109
  navigationSidebarState: 'closed',
90
110
  setNavigationSidebarState: (_nextState) => {
91
- // TODO(burdon): Standardize with other context missing errors using raise.
92
- log.warn('Attempt to set sidebar state without initializing `MainRoot`');
111
+ log.warn('Not initialized');
93
112
  },
113
+
94
114
  complementarySidebarState: 'closed',
95
115
  setComplementarySidebarState: (_nextState) => {
96
- // TODO(burdon): Standardize with other context missing errors using raise.
97
- log.warn('Attempt to set sidebar state without initializing `MainRoot`');
116
+ log.warn('Not initialized');
98
117
  },
99
118
  });
100
119
 
101
- const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
102
- const { setNavigationSidebarState, navigationSidebarState, setComplementarySidebarState, complementarySidebarState } =
103
- useMainContext(consumerName);
120
+ const useSidebars = (consumerName: string) => {
121
+ const {
122
+ navigationSidebarState,
123
+ setNavigationSidebarState,
124
+
125
+ complementarySidebarState,
126
+ setComplementarySidebarState,
127
+ } = useMainContext(consumerName);
104
128
 
105
129
  return {
106
130
  navigationSidebarState,
@@ -112,6 +136,7 @@ const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
112
136
  openNavigationSidebar: useCallback(() => setNavigationSidebarState('expanded'), []),
113
137
  collapseNavigationSidebar: useCallback(() => setNavigationSidebarState('collapsed'), []),
114
138
  closeNavigationSidebar: useCallback(() => setNavigationSidebarState('closed'), []),
139
+
115
140
  complementarySidebarState,
116
141
  setComplementarySidebarState,
117
142
  toggleComplementarySidebar: useCallback(
@@ -124,24 +149,29 @@ const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
124
149
  };
125
150
  };
126
151
 
152
+ //
153
+ // Root
154
+ //
155
+
127
156
  type MainRootProps = PropsWithChildren<{
128
157
  navigationSidebarState?: SidebarState;
129
158
  defaultNavigationSidebarState?: SidebarState;
130
159
  onNavigationSidebarStateChange?: (nextState: SidebarState) => void;
160
+
131
161
  complementarySidebarState?: SidebarState;
132
162
  defaultComplementarySidebarState?: SidebarState;
133
163
  onComplementarySidebarStateChange?: (nextState: SidebarState) => void;
134
164
  }>;
135
165
 
136
- const resizeDebounce = 3000;
137
-
138
166
  const MainRoot = ({
139
167
  navigationSidebarState: propsNavigationSidebarState,
140
- defaultNavigationSidebarState,
168
+ defaultNavigationSidebarState = 'closed',
141
169
  onNavigationSidebarStateChange,
170
+
142
171
  complementarySidebarState: propsComplementarySidebarState,
143
- defaultComplementarySidebarState,
172
+ defaultComplementarySidebarState = 'closed',
144
173
  onComplementarySidebarStateChange,
174
+
145
175
  children,
146
176
  ...props
147
177
  }: MainRootProps) => {
@@ -161,22 +191,21 @@ const MainRoot = ({
161
191
 
162
192
  const [resizing, setResizing] = useState(false);
163
193
  const resizeInterval = useRef<ReturnType<typeof setTimeout> | null>(null);
194
+ useEffect(
195
+ () =>
196
+ addEventListener(window, 'resize', () => {
197
+ setResizing(true);
198
+ if (resizeInterval.current) {
199
+ clearTimeout(resizeInterval.current);
200
+ }
164
201
 
165
- const handleResize = useCallback(() => {
166
- setResizing(true);
167
- if (resizeInterval.current) {
168
- clearTimeout(resizeInterval.current);
169
- }
170
- resizeInterval.current = setTimeout(() => {
171
- setResizing(false);
172
- resizeInterval.current = null;
173
- }, resizeDebounce);
174
- }, []);
175
-
176
- useEffect(() => {
177
- window.addEventListener('resize', handleResize);
178
- return () => window.removeEventListener('resize', handleResize);
179
- }, [handleResize]);
202
+ resizeInterval.current = setTimeout(() => {
203
+ setResizing(false);
204
+ resizeInterval.current = null;
205
+ }, 3_000);
206
+ }),
207
+ [],
208
+ );
180
209
 
181
210
  return (
182
211
  <MainProvider
@@ -196,9 +225,45 @@ const MainRoot = ({
196
225
 
197
226
  MainRoot.displayName = MAIN_ROOT_NAME;
198
227
 
199
- const handleOpenAutoFocus = (event: Event) => {
200
- !document.body.hasAttribute('data-is-keyboard') && event.preventDefault();
201
- };
228
+ //
229
+ // Overlay
230
+ //
231
+
232
+ type MainOverlayProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.div>, 'children' | 'onClick'>>;
233
+
234
+ const MainOverlay = forwardRef<HTMLDivElement, MainOverlayProps>(({ classNames, ...props }, forwardedRef) => {
235
+ const [isLg] = useMediaQuery('lg');
236
+ const { navigationSidebarState, setNavigationSidebarState, complementarySidebarState, setComplementarySidebarState } =
237
+ useMainContext(MAIN_OVERLAY_NAME);
238
+ const { tx } = useThemeContext();
239
+ return (
240
+ <div
241
+ {...props}
242
+ onClick={() => {
243
+ setNavigationSidebarState('collapsed');
244
+ setComplementarySidebarState('collapsed');
245
+ }}
246
+ className={tx(
247
+ 'main.overlay',
248
+ {
249
+ isLg,
250
+ inlineStartSidebarOpen: navigationSidebarState,
251
+ inlineEndSidebarOpen: complementarySidebarState,
252
+ },
253
+ classNames,
254
+ )}
255
+ data-state={navigationSidebarState === 'expanded' || complementarySidebarState === 'expanded' ? 'open' : 'closed'}
256
+ aria-hidden='true'
257
+ ref={forwardedRef}
258
+ />
259
+ );
260
+ });
261
+
262
+ MainOverlay.displayName = MAIN_OVERLAY_NAME;
263
+
264
+ //
265
+ // Sidebar
266
+ //
202
267
 
203
268
  type MainSidebarProps = ThemedClassName<ComponentPropsWithRef<typeof DialogContent>> & {
204
269
  swipeToDismiss?: boolean;
@@ -219,9 +284,11 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
219
284
  const { t } = useTranslation();
220
285
  const ref = useForwardedRef(forwardedRef);
221
286
  const noopRef = useRef(null);
287
+
222
288
  useSwipeToDismiss(swipeToDismiss ? ref : noopRef, {
223
289
  onDismiss: () => onStateChange?.('closed'),
224
290
  });
291
+
225
292
  // NOTE(thure): This is a workaround for something further down the tree grabbing focus on Escape. Adding this
226
293
  // intervention to `Tabs.Root` or `Tabs.Tabpenel` instances is somehow ineffectual.
227
294
  const handleKeyDown = useCallback(
@@ -236,6 +303,7 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
236
303
  },
237
304
  [props.onKeyDown],
238
305
  );
306
+
239
307
  const Root = isLg ? Primitive.div : DialogContent;
240
308
 
241
309
  return (
@@ -243,13 +311,13 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
243
311
  {!isLg && <DialogTitle className='sr-only'>{toLocalizedString(label, t)}</DialogTitle>}
244
312
  <Root
245
313
  {...(!isLg && { forceMount: true, tabIndex: -1, onOpenAutoFocus: onOpenAutoFocus ?? handleOpenAutoFocus })}
314
+ {...(state === 'closed' && { inert: true })}
246
315
  {...props}
247
316
  data-side={side === 'inline-end' ? 'ie' : 'is'}
248
317
  data-state={state}
249
318
  data-resizing={resizing ? 'true' : 'false'}
250
- className={tx('main.sidebar', 'main__sidebar', {}, classNames)}
319
+ className={tx('main.sidebar', {}, classNames)}
251
320
  onKeyDownCapture={handleKeyDown}
252
- {...(state === 'closed' && { inert: true })}
253
321
  ref={ref}
254
322
  >
255
323
  {children}
@@ -259,6 +327,10 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
259
327
  },
260
328
  );
261
329
 
330
+ //
331
+ // Navigation Sidebar
332
+ //
333
+
262
334
  type MainNavigationSidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
263
335
 
264
336
  const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarProps>((props, forwardedRef) => {
@@ -280,6 +352,10 @@ const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarPr
280
352
 
281
353
  MainNavigationSidebar.displayName = NAVIGATION_SIDEBAR_NAME;
282
354
 
355
+ //
356
+ // Complementary Sidebar
357
+ //
358
+
283
359
  type MainComplementarySidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
284
360
 
285
361
  const MainComplementarySidebar = forwardRef<HTMLDivElement, MainComplementarySidebarProps>((props, forwardedRef) => {
@@ -300,20 +376,24 @@ const MainComplementarySidebar = forwardRef<HTMLDivElement, MainComplementarySid
300
376
  );
301
377
  });
302
378
 
303
- MainNavigationSidebar.displayName = NAVIGATION_SIDEBAR_NAME;
379
+ MainComplementarySidebar.displayName = COMPLEMENTARY_SIDEBAR_NAME;
304
380
 
305
- type MainProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.div>> & {
306
- asChild?: boolean;
307
- bounce?: boolean;
308
- handlesFocus?: boolean;
309
- };
381
+ //
382
+ // Content
383
+ //
384
+
385
+ type MainContentProps = ThemedClassName<
386
+ ComponentPropsWithRef<typeof Primitive.div> &
387
+ MainStyleProps & {
388
+ asChild?: boolean;
389
+ }
390
+ >;
310
391
 
311
- const MainContent = forwardRef<HTMLDivElement, MainProps>(
312
- ({ asChild, classNames, bounce, handlesFocus, children, role, ...props }: MainProps, forwardedRef) => {
392
+ const MainContent = forwardRef<HTMLDivElement, MainContentProps>(
393
+ ({ asChild, classNames, bounce, handlesFocus, children, role, ...props }: MainContentProps, forwardedRef) => {
313
394
  const { navigationSidebarState, complementarySidebarState } = useMainContext(MAIN_NAME);
314
395
  const { tx } = useThemeContext();
315
396
  const Root = asChild ? Slot : role ? 'div' : 'main';
316
-
317
397
  const mover = useLandmarkMover(props.onKeyDown, '1');
318
398
 
319
399
  return (
@@ -324,7 +404,7 @@ const MainContent = forwardRef<HTMLDivElement, MainProps>(
324
404
  data-sidebar-inline-start-state={navigationSidebarState}
325
405
  data-sidebar-inline-end-state={complementarySidebarState}
326
406
  data-handles-focus={handlesFocus}
327
- className={tx('main.content', 'main', { bounce, handlesFocus }, classNames)}
407
+ className={tx('main.content', { bounce, handlesFocus }, classNames)}
328
408
  ref={forwardedRef}
329
409
  >
330
410
  {children}
@@ -335,41 +415,18 @@ const MainContent = forwardRef<HTMLDivElement, MainProps>(
335
415
 
336
416
  MainContent.displayName = MAIN_NAME;
337
417
 
338
- type MainOverlayProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.div>, 'children'>>;
339
-
340
- const MainOverlay = forwardRef<HTMLDivElement, MainOverlayProps>(({ classNames, ...props }, forwardedRef) => {
341
- const [isLg] = useMediaQuery('lg');
342
- const { navigationSidebarState, setNavigationSidebarState, complementarySidebarState, setComplementarySidebarState } =
343
- useMainContext(MAIN_NAME);
344
- const { tx } = useThemeContext();
345
- return (
346
- <div
347
- onClick={() => {
348
- setNavigationSidebarState('collapsed');
349
- setComplementarySidebarState('collapsed');
350
- }}
351
- {...props}
352
- className={tx(
353
- 'main.overlay',
354
- 'main__overlay',
355
- { isLg, inlineStartSidebarOpen: navigationSidebarState, inlineEndSidebarOpen: complementarySidebarState },
356
- classNames,
357
- )}
358
- data-state={navigationSidebarState === 'expanded' || complementarySidebarState === 'expanded' ? 'open' : 'closed'}
359
- aria-hidden='true'
360
- ref={forwardedRef}
361
- />
362
- );
363
- });
418
+ //
419
+ // Main
420
+ //
364
421
 
365
422
  export const Main = {
366
423
  Root: MainRoot,
367
- Content: MainContent,
368
424
  Overlay: MainOverlay,
425
+ Content: MainContent,
369
426
  NavigationSidebar: MainNavigationSidebar,
370
427
  ComplementarySidebar: MainComplementarySidebar,
371
428
  };
372
429
 
373
430
  export { useMainContext, useSidebars, useLandmarkMover };
374
431
 
375
- export type { MainRootProps, MainProps, MainOverlayProps, MainNavigationSidebarProps, SidebarState };
432
+ export type { MainRootProps, MainOverlayProps, MainContentProps, MainNavigationSidebarProps, SidebarState };
@@ -92,10 +92,10 @@ const DefaultStory = () => {
92
92
  };
93
93
 
94
94
  const meta = {
95
- title: 'ui/react-ui-core/ContextMenu',
95
+ title: 'ui/react-ui-core/components/ContextMenu',
96
96
  component: ContextMenu.Root as any,
97
97
  render: DefaultStory,
98
- decorators: [withTheme],
98
+ decorators: [withTheme()],
99
99
  } satisfies Meta<typeof DefaultStory>;
100
100
 
101
101
  export default meta;
@@ -36,7 +36,7 @@ const ContextMenuContent = forwardRef<HTMLDivElement, ContextMenuContentProps>(
36
36
  {...props}
37
37
  data-arrow-keys='up down'
38
38
  collisionPadding={safeCollisionPadding}
39
- className={tx('menu.content', 'menu', { elevation }, classNames)}
39
+ className={tx('menu.content', { elevation }, classNames)}
40
40
  ref={forwardedRef}
41
41
  >
42
42
  {children}
@@ -54,7 +54,7 @@ const ContextMenuViewport = forwardRef<HTMLDivElement, ContextMenuViewportProps>
54
54
  const { tx } = useThemeContext();
55
55
  const Root = asChild ? Slot : Primitive.div;
56
56
  return (
57
- <Root {...props} className={tx('menu.viewport', 'menu__viewport', {}, classNames)} ref={forwardedRef}>
57
+ <Root {...props} className={tx('menu.viewport', {}, classNames)} ref={forwardedRef}>
58
58
  {children}
59
59
  </Root>
60
60
  );
@@ -65,13 +65,7 @@ type ContextMenuArrowProps = ThemedClassName<ContextMenuPrimitive.ContextMenuArr
65
65
 
66
66
  const ContextMenuArrow = forwardRef<SVGSVGElement, ContextMenuArrowProps>(({ classNames, ...props }, forwardedRef) => {
67
67
  const { tx } = useThemeContext();
68
- return (
69
- <ContextMenuPrimitive.Arrow
70
- {...props}
71
- className={tx('menu.arrow', 'menu__arrow', {}, classNames)}
72
- ref={forwardedRef}
73
- />
74
- );
68
+ return <ContextMenuPrimitive.Arrow {...props} className={tx('menu.arrow', {}, classNames)} ref={forwardedRef} />;
75
69
  });
76
70
 
77
71
  type ContextMenuGroupProps = ContextMenuPrimitive.ContextMenuGroupProps;
@@ -87,13 +81,7 @@ type ContextMenuItemProps = ThemedClassName<ContextMenuPrimitive.ContextMenuItem
87
81
  const ContextMenuItem = forwardRef<HTMLDivElement, ContextMenuItemProps>(
88
82
  ({ classNames, ...props }: ContextMenuItemProps, forwardedRef) => {
89
83
  const { tx } = useThemeContext();
90
- return (
91
- <ContextMenuPrimitive.Item
92
- {...props}
93
- className={tx('menu.item', 'menu__item', {}, classNames)}
94
- ref={forwardedRef}
95
- />
96
- );
84
+ return <ContextMenuPrimitive.Item {...props} className={tx('menu.item', {}, classNames)} ref={forwardedRef} />;
97
85
  },
98
86
  );
99
87
 
@@ -103,11 +91,7 @@ const ContextMenuCheckboxItem = forwardRef<HTMLDivElement, ContextMenuCheckboxIt
103
91
  ({ classNames, ...props }: ContextMenuItemProps, forwardedRef) => {
104
92
  const { tx } = useThemeContext();
105
93
  return (
106
- <ContextMenuPrimitive.CheckboxItem
107
- {...props}
108
- className={tx('menu.item', 'menu__item--checkbox', {}, classNames)}
109
- ref={forwardedRef}
110
- />
94
+ <ContextMenuPrimitive.CheckboxItem {...props} className={tx('menu.item', {}, classNames)} ref={forwardedRef} />
111
95
  );
112
96
  },
113
97
  );
@@ -118,11 +102,7 @@ const ContextMenuSeparator = forwardRef<HTMLDivElement, ContextMenuSeparatorProp
118
102
  ({ classNames, ...props }, forwardedRef) => {
119
103
  const { tx } = useThemeContext();
120
104
  return (
121
- <ContextMenuPrimitive.Separator
122
- {...props}
123
- className={tx('menu.separator', 'menu__item', {}, classNames)}
124
- ref={forwardedRef}
125
- />
105
+ <ContextMenuPrimitive.Separator {...props} className={tx('menu.separator', {}, classNames)} ref={forwardedRef} />
126
106
  );
127
107
  },
128
108
  );
@@ -133,11 +113,7 @@ const ContextMenuGroupLabel = forwardRef<HTMLDivElement, ContextMenuGroupLabelPr
133
113
  ({ classNames, ...props }, forwardedRef) => {
134
114
  const { tx } = useThemeContext();
135
115
  return (
136
- <ContextMenuPrimitive.Label
137
- {...props}
138
- className={tx('menu.groupLabel', 'menu__group__label', {}, classNames)}
139
- ref={forwardedRef}
140
- />
116
+ <ContextMenuPrimitive.Label {...props} className={tx('menu.groupLabel', {}, classNames)} ref={forwardedRef} />
141
117
  );
142
118
  },
143
119
  );
@@ -92,10 +92,10 @@ const DefaultStory = () => {
92
92
  };
93
93
 
94
94
  const meta = {
95
- title: 'ui/react-ui-core/DropdownMenu',
95
+ title: 'ui/react-ui-core/components/DropdownMenu',
96
96
  component: DropdownMenu.Root,
97
97
  render: DefaultStory,
98
- decorators: [withTheme],
98
+ decorators: [withTheme()],
99
99
  } satisfies Meta<typeof DefaultStory>;
100
100
 
101
101
  export default meta;
@@ -216,7 +216,7 @@ const DropdownMenuViewport = forwardRef<HTMLDivElement, DropdownMenuViewportProp
216
216
  const { tx } = useThemeContext();
217
217
  const Root = asChild ? Slot : Primitive.div;
218
218
  return (
219
- <Root {...props} className={tx('menu.viewport', 'menu__viewport', {}, classNames)} ref={forwardedRef}>
219
+ <Root {...props} className={tx('menu.viewport', {}, classNames)} ref={forwardedRef}>
220
220
  {children}
221
221
  </Root>
222
222
  );
@@ -283,7 +283,7 @@ const DropdownMenuContent = forwardRef<DropdownMenuContentElement, DropdownMenuC
283
283
  }
284
284
  })}
285
285
  data-arrow-keys='up down'
286
- className={tx('menu.content', 'menu', { elevation }, classNames)}
286
+ className={tx('menu.content', { elevation }, classNames)}
287
287
  style={{
288
288
  ...props.style,
289
289
  // re-namespace exposed content custom properties
@@ -341,7 +341,7 @@ const DropdownMenuGroupLabel = forwardRef<DropdownMenuLabelElement, DropdownMenu
341
341
  <MenuPrimitive.Label
342
342
  {...menuScope}
343
343
  {...labelProps}
344
- className={tx('menu.groupLabel', 'menu__group__label', {}, classNames)}
344
+ className={tx('menu.groupLabel', {}, classNames)}
345
345
  ref={forwardedRef}
346
346
  />
347
347
  );
@@ -369,7 +369,7 @@ const DropdownMenuItem = forwardRef<DropdownMenuItemElement, DropdownMenuItemPro
369
369
  <MenuPrimitive.Item
370
370
  {...menuScope}
371
371
  {...itemProps}
372
- className={tx('menu.item', 'menu__item', {}, classNames)}
372
+ className={tx('menu.item', {}, classNames)}
373
373
  ref={forwardedRef}
374
374
  />
375
375
  );
@@ -397,7 +397,7 @@ const DropdownMenuCheckboxItem = forwardRef<DropdownMenuCheckboxItemElement, Dro
397
397
  <MenuPrimitive.CheckboxItem
398
398
  {...menuScope}
399
399
  {...checkboxItemProps}
400
- className={tx('menu.item', 'menu__item--checkbox', {}, classNames)}
400
+ className={tx('menu.item', {}, classNames)}
401
401
  ref={forwardedRef}
402
402
  />
403
403
  );
@@ -445,7 +445,7 @@ const DropdownMenuRadioItem = forwardRef<DropdownMenuRadioItemElement, DropdownM
445
445
  <MenuPrimitive.Item
446
446
  {...menuScope}
447
447
  {...itemProps}
448
- className={tx('menu.item', 'menu__item', {}, classNames)}
448
+ className={tx('menu.item', {}, classNames)}
449
449
  ref={forwardedRef}
450
450
  />
451
451
  );
@@ -493,7 +493,7 @@ const DropdownMenuSeparator = forwardRef<DropdownMenuSeparatorElement, DropdownM
493
493
  <MenuPrimitive.Separator
494
494
  {...menuScope}
495
495
  {...separatorProps}
496
- className={tx('menu.separator', 'menu__item', {}, classNames)}
496
+ className={tx('menu.separator', {}, classNames)}
497
497
  ref={forwardedRef}
498
498
  />
499
499
  );
@@ -521,7 +521,7 @@ const DropdownMenuArrow = forwardRef<DropdownMenuArrowElement, DropdownMenuArrow
521
521
  <MenuPrimitive.Arrow
522
522
  {...menuScope}
523
523
  {...arrowProps}
524
- className={tx('menu.arrow', 'menu__arrow', {}, classNames)}
524
+ className={tx('menu.arrow', {}, classNames)}
525
525
  ref={forwardedRef}
526
526
  />
527
527
  );
@@ -5,12 +5,15 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React from 'react';
7
7
 
8
+ import { faker } from '@dxos/random';
8
9
  import { type MessageValence } from '@dxos/ui-types';
9
10
 
10
11
  import { withTheme } from '../../testing';
11
12
 
12
13
  import { Callout } from './Message';
13
14
 
15
+ faker.seed(123);
16
+
14
17
  type StoryProps = {
15
18
  valence: MessageValence;
16
19
  title: string;
@@ -18,18 +21,22 @@ type StoryProps = {
18
21
  };
19
22
 
20
23
  const DefaultStory = ({ valence, title, body }: StoryProps) => (
21
- <Callout.Root valence={valence}>
22
- {title && <Callout.Title>{title}</Callout.Title>}
23
- {body && <Callout.Content>{body}</Callout.Content>}
24
- </Callout.Root>
24
+ <div className='is-[30rem]'>
25
+ <Callout.Root valence={valence}>
26
+ {title && <Callout.Title>{title}</Callout.Title>}
27
+ {body && <Callout.Content>{body}</Callout.Content>}
28
+ </Callout.Root>
29
+ </div>
25
30
  );
26
31
 
27
32
  const meta = {
28
- title: 'ui/react-ui-core/Callout',
33
+ title: 'ui/react-ui-core/components/Message',
29
34
  component: Callout.Root as any,
30
35
  render: DefaultStory,
31
- decorators: [withTheme],
32
- parameters: { chromatic: { disableSnapshot: false } },
36
+ decorators: [withTheme()],
37
+ parameters: {
38
+ layout: 'centered',
39
+ },
33
40
  argTypes: {
34
41
  valence: {
35
42
  control: 'select',
@@ -46,6 +53,14 @@ export const Default: Story = {
46
53
  args: {
47
54
  valence: 'neutral',
48
55
  title: 'Alert title',
49
- body: 'Alert content',
56
+ body: faker.lorem.paragraphs(1),
57
+ },
58
+ };
59
+
60
+ export const Error: Story = {
61
+ args: {
62
+ valence: 'error',
63
+ title: 'Error title',
64
+ body: faker.lorem.paragraphs(1),
50
65
  },
51
66
  };
@@ -65,7 +65,7 @@ const MessageRoot = forwardRef<HTMLDivElement, MessageRootProps>(
65
65
  <Root
66
66
  role={valence === 'neutral' ? 'paragraph' : 'alert'}
67
67
  {...props}
68
- className={tx('message.root', 'message', { valence, elevation }, classNames)}
68
+ className={tx('message.root', { valence, elevation }, classNames)}
69
69
  aria-labelledby={titleId}
70
70
  aria-describedby={descriptionId}
71
71
  ref={forwardedRef}
@@ -95,22 +95,14 @@ const MessageTitle = forwardRef<HTMLHeadingElement, MessageTitleProps>(
95
95
  const { tx } = useThemeContext();
96
96
  const { titleId, valence } = useMessageContext(MESSAGE_TITLE_NAME);
97
97
  const Root = asChild ? Slot : Primitive.h2;
98
-
99
98
  return (
100
- <Root
101
- {...props}
102
- className={tx('message.title', 'message__title', {}, classNames)}
103
- id={titleId}
104
- ref={forwardedRef}
105
- >
106
- {!icon && valence === 'neutral' ? null : (
107
- <Icon
108
- size={5}
109
- icon={icon ?? messageIcons[valence]}
110
- classNames={tx('message.icon', 'message__icon', { valence })}
111
- />
99
+ <Root {...props} className={tx('message.header', {}, classNames)} id={titleId} ref={forwardedRef}>
100
+ {!icon && valence === 'neutral' ? (
101
+ <div />
102
+ ) : (
103
+ <Icon size={5} icon={icon ?? messageIcons[valence]} classNames={tx('message.icon', { valence })} />
112
104
  )}
113
- <span>{children}</span>
105
+ <span className={tx('message.title', {}, classNames)}>{children}</span>
114
106
  </Root>
115
107
  );
116
108
  },
@@ -134,12 +126,7 @@ const MessageContent = forwardRef<HTMLParagraphElement, MessageContentProps>(
134
126
  const { descriptionId } = useMessageContext(MESSAGE_CONTENT_NAME);
135
127
  const Root = asChild ? Slot : Primitive.p;
136
128
  return (
137
- <Root
138
- {...props}
139
- className={tx('message.content', 'message__content', {}, classNames)}
140
- id={descriptionId}
141
- ref={forwardedRef}
142
- >
129
+ <Root {...props} className={tx('message.content', {}, classNames)} id={descriptionId} ref={forwardedRef}>
143
130
  {children}
144
131
  </Root>
145
132
  );
@@ -29,10 +29,10 @@ const DefaultStory = ({ openTrigger, children }: PropsWithChildren<{ openTrigger
29
29
  };
30
30
 
31
31
  const meta = {
32
- title: 'ui/react-ui-core/Popover',
32
+ title: 'ui/react-ui-core/components/Popover',
33
33
  component: Popover.Root,
34
34
  render: DefaultStory,
35
- decorators: [withTheme],
35
+ decorators: [withTheme()],
36
36
  } satisfies Meta<typeof DefaultStory>;
37
37
 
38
38
  export default meta;