@dxos/react-ui 0.7.5-main.9d2a38b → 0.7.5-main.ff8607b

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 (34) hide show
  1. package/dist/lib/browser/index.mjs +75 -76
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +76 -76
  5. package/dist/lib/node/index.cjs.map +3 -3
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +75 -76
  8. package/dist/lib/node-esm/index.mjs.map +3 -3
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/Avatars/Avatar.d.ts +5 -9
  11. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  12. package/dist/types/src/components/Avatars/Avatar.stories.d.ts +1 -2
  13. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/Buttons/IconButton.d.ts +2 -0
  15. package/dist/types/src/components/Buttons/IconButton.d.ts.map +1 -1
  16. package/dist/types/src/components/Lists/ListDropIndicator.d.ts +3 -1
  17. package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +1 -1
  18. package/dist/types/src/components/Main/Main.d.ts +35 -22
  19. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  20. package/dist/types/src/components/Main/Main.stories.d.ts +1 -1
  21. package/dist/types/src/components/Menus/DropdownMenu.d.ts +2 -6
  22. package/dist/types/src/components/Menus/DropdownMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  24. package/dist/types/src/components/Tag/Tag.stories.d.ts +12 -5
  25. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  26. package/package.json +42 -42
  27. package/src/components/Avatars/Avatar.tsx +3 -6
  28. package/src/components/Buttons/IconButton.tsx +4 -3
  29. package/src/components/Input/Input.tsx +1 -1
  30. package/src/components/Lists/ListDropIndicator.tsx +15 -7
  31. package/src/components/Main/Main.stories.tsx +1 -1
  32. package/src/components/Main/Main.tsx +78 -72
  33. package/src/components/Tag/Tag.stories.tsx +20 -31
  34. package/src/components/Tag/Tag.tsx +15 -6
@@ -35,12 +35,14 @@ const COMPLEMENTARY_SIDEBAR_NAME = 'ComplementarySidebar';
35
35
  const MAIN_NAME = 'Main';
36
36
  const GENERIC_CONSUMER_NAME = 'GenericConsumer';
37
37
 
38
+ type SidebarState = 'expanded' | 'collapsed' | 'closed';
39
+
38
40
  type MainContextValue = {
39
41
  resizing: boolean;
40
- navigationSidebarOpen: boolean;
41
- setNavigationSidebarOpen: Dispatch<SetStateAction<boolean | undefined>>;
42
- complementarySidebarOpen: boolean;
43
- setComplementarySidebarOpen: Dispatch<SetStateAction<boolean | undefined>>;
42
+ navigationSidebarState: SidebarState;
43
+ setNavigationSidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
44
+ complementarySidebarState: SidebarState;
45
+ setComplementarySidebarState: Dispatch<SetStateAction<SidebarState | undefined>>;
44
46
  };
45
47
 
46
48
  const landmarkAttr = 'data-main-landmark';
@@ -73,73 +75,77 @@ const useLandmarkMover = (propsOnKeyDown: ComponentPropsWithoutRef<'div'>['onKey
73
75
 
74
76
  const [MainProvider, useMainContext] = createContext<MainContextValue>(MAIN_NAME, {
75
77
  resizing: false,
76
- navigationSidebarOpen: false,
77
- setNavigationSidebarOpen: (nextOpen) => {
78
+ navigationSidebarState: 'closed',
79
+ setNavigationSidebarState: (nextState) => {
78
80
  // TODO(burdon): Standardize with other context missing errors using raise.
79
81
  log.warn('Attempt to set sidebar state without initializing `MainRoot`');
80
82
  },
81
- complementarySidebarOpen: false,
82
- setComplementarySidebarOpen: (nextOpen) => {
83
+ complementarySidebarState: 'closed',
84
+ setComplementarySidebarState: (nextState) => {
83
85
  // TODO(burdon): Standardize with other context missing errors using raise.
84
86
  log.warn('Attempt to set sidebar state without initializing `MainRoot`');
85
87
  },
86
88
  });
87
89
 
88
90
  const useSidebars = (consumerName = GENERIC_CONSUMER_NAME) => {
89
- const { setNavigationSidebarOpen, navigationSidebarOpen, setComplementarySidebarOpen, complementarySidebarOpen } =
91
+ const { setNavigationSidebarState, navigationSidebarState, setComplementarySidebarState, complementarySidebarState } =
90
92
  useMainContext(consumerName);
91
93
  return {
92
- navigationSidebarOpen,
93
- setNavigationSidebarOpen,
94
+ navigationSidebarState,
95
+ setNavigationSidebarState,
94
96
  toggleNavigationSidebar: useCallback(
95
- () => setNavigationSidebarOpen(!navigationSidebarOpen),
96
- [navigationSidebarOpen, setNavigationSidebarOpen],
97
+ () => setNavigationSidebarState(navigationSidebarState === 'expanded' ? 'closed' : 'expanded'),
98
+ [navigationSidebarState, setNavigationSidebarState],
97
99
  ),
98
- openNavigationSidebar: useCallback(() => setNavigationSidebarOpen(true), [setNavigationSidebarOpen]),
99
- closeNavigationSidebar: useCallback(() => setNavigationSidebarOpen(false), [setNavigationSidebarOpen]),
100
- complementarySidebarOpen,
101
- setComplementarySidebarOpen,
100
+ openNavigationSidebar: useCallback(() => setNavigationSidebarState('expanded'), []),
101
+ collapseNavigationSidebar: useCallback(() => setNavigationSidebarState('collapsed'), []),
102
+ closeNavigationSidebar: useCallback(() => setNavigationSidebarState('closed'), []),
103
+ complementarySidebarState,
104
+ setComplementarySidebarState,
102
105
  toggleComplementarySidebar: useCallback(
103
- () => setComplementarySidebarOpen(!complementarySidebarOpen),
104
- [complementarySidebarOpen, setComplementarySidebarOpen],
106
+ () => setComplementarySidebarState(complementarySidebarState === 'expanded' ? 'closed' : 'expanded'),
107
+ [complementarySidebarState, setComplementarySidebarState],
105
108
  ),
106
- openComplementarySidebar: useCallback(() => setComplementarySidebarOpen(true), [setComplementarySidebarOpen]),
107
- closeComplementarySidebar: useCallback(() => setComplementarySidebarOpen(false), [setComplementarySidebarOpen]),
109
+ openComplementarySidebar: useCallback(() => setComplementarySidebarState('expanded'), []),
110
+ collapseComplementarySidebar: useCallback(() => setComplementarySidebarState('collapsed'), []),
111
+ closeComplementarySidebar: useCallback(() => setComplementarySidebarState('closed'), []),
108
112
  };
109
113
  };
110
114
 
111
115
  type MainRootProps = PropsWithChildren<{
112
- navigationSidebarOpen?: boolean;
113
- defaultNavigationSidebarOpen?: boolean;
114
- onNavigationSidebarOpenChange?: (nextOpen: boolean) => void;
115
- complementarySidebarOpen?: boolean;
116
- defaultComplementarySidebarOpen?: boolean;
117
- onComplementarySidebarOpenChange?: (nextOpen: boolean) => void;
116
+ navigationSidebarState?: SidebarState;
117
+ defaultNavigationSidebarState?: SidebarState;
118
+ onNavigationSidebarStateChange?: (nextState: SidebarState) => void;
119
+ complementarySidebarState?: SidebarState;
120
+ defaultComplementarySidebarState?: SidebarState;
121
+ onComplementarySidebarStateChange?: (nextState: SidebarState) => void;
118
122
  }>;
119
123
 
120
124
  const resizeDebounce = 3000;
121
125
 
122
126
  const MainRoot = ({
123
- navigationSidebarOpen: propsNavigationSidebarOpen,
124
- defaultNavigationSidebarOpen,
125
- onNavigationSidebarOpenChange,
126
- complementarySidebarOpen: propsComplementarySidebarOpen,
127
- defaultComplementarySidebarOpen,
128
- onComplementarySidebarOpenChange,
127
+ navigationSidebarState: propsNavigationSidebarState,
128
+ defaultNavigationSidebarState,
129
+ onNavigationSidebarStateChange,
130
+ complementarySidebarState: propsComplementarySidebarState,
131
+ defaultComplementarySidebarState,
132
+ onComplementarySidebarStateChange,
129
133
  children,
130
134
  ...props
131
135
  }: MainRootProps) => {
132
136
  const [isLg] = useMediaQuery('lg', { ssr: false });
133
- const [navigationSidebarOpen = isLg, setNavigationSidebarOpen] = useControllableState<boolean>({
134
- prop: propsNavigationSidebarOpen,
135
- defaultProp: defaultNavigationSidebarOpen,
136
- onChange: onNavigationSidebarOpenChange,
137
- });
138
- const [complementarySidebarOpen = false, setComplementarySidebarOpen] = useControllableState<boolean>({
139
- prop: propsComplementarySidebarOpen,
140
- defaultProp: defaultComplementarySidebarOpen,
141
- onChange: onComplementarySidebarOpenChange,
142
- });
137
+ const [navigationSidebarState = isLg ? 'expanded' : 'collapsed', setNavigationSidebarState] =
138
+ useControllableState<SidebarState>({
139
+ prop: propsNavigationSidebarState,
140
+ defaultProp: defaultNavigationSidebarState,
141
+ onChange: onNavigationSidebarStateChange,
142
+ });
143
+ const [complementarySidebarState = isLg ? 'expanded' : 'collapsed', setComplementarySidebarState] =
144
+ useControllableState<SidebarState>({
145
+ prop: propsComplementarySidebarState,
146
+ defaultProp: defaultComplementarySidebarState,
147
+ onChange: onComplementarySidebarStateChange,
148
+ });
143
149
 
144
150
  const [resizing, setResizing] = useState(false);
145
151
  const resizeInterval = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -164,10 +170,10 @@ const MainRoot = ({
164
170
  <MainProvider
165
171
  {...props}
166
172
  {...{
167
- navigationSidebarOpen,
168
- setNavigationSidebarOpen,
169
- complementarySidebarOpen,
170
- setComplementarySidebarOpen,
173
+ navigationSidebarState,
174
+ setNavigationSidebarState,
175
+ complementarySidebarState,
176
+ setComplementarySidebarState,
171
177
  }}
172
178
  resizing={resizing}
173
179
  >
@@ -184,15 +190,15 @@ const handleOpenAutoFocus = (event: Event) => {
184
190
 
185
191
  type MainSidebarProps = ThemedClassName<ComponentPropsWithRef<typeof DialogContent>> & {
186
192
  swipeToDismiss?: boolean;
187
- open: boolean;
193
+ state?: SidebarState;
188
194
  resizing?: boolean;
189
- setOpen: Dispatch<SetStateAction<boolean | undefined>>;
195
+ onStateChange?: (nextState: SidebarState) => void;
190
196
  side: 'inline-start' | 'inline-end';
191
197
  };
192
198
 
193
199
  const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
194
200
  (
195
- { classNames, children, swipeToDismiss, onOpenAutoFocus, open, resizing, setOpen, side, ...props },
201
+ { classNames, children, swipeToDismiss, onOpenAutoFocus, state, resizing, onStateChange, side, ...props },
196
202
  forwardedRef,
197
203
  ) => {
198
204
  const [isLg] = useMediaQuery('lg', { ssr: false });
@@ -200,7 +206,7 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
200
206
  const ref = useForwardedRef(forwardedRef);
201
207
  const noopRef = useRef(null);
202
208
  useSwipeToDismiss(swipeToDismiss ? ref : noopRef, {
203
- onDismiss: () => setOpen(false),
209
+ onDismiss: () => onStateChange?.('closed'),
204
210
  });
205
211
  const handleKeyDown = useCallback(
206
212
  (event: KeyboardEvent<HTMLDivElement>) => {
@@ -213,16 +219,16 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
213
219
  );
214
220
  const Root = isLg ? Primitive.div : DialogContent;
215
221
  return (
216
- <DialogRoot open={open} modal={false}>
222
+ <DialogRoot open={state !== 'closed'} modal={false}>
217
223
  <Root
218
224
  {...(!isLg && { forceMount: true, tabIndex: -1, onOpenAutoFocus: onOpenAutoFocus ?? handleOpenAutoFocus })}
219
225
  {...props}
220
226
  data-side={side === 'inline-end' ? 'ie' : 'is'}
221
- data-state={open ? 'open' : 'closed'}
227
+ data-state={state}
222
228
  data-resizing={resizing ? 'true' : 'false'}
223
229
  className={tx('main.sidebar', 'main__sidebar', {}, classNames)}
224
230
  onKeyDown={handleKeyDown}
225
- {...(!open && { inert: 'true' })}
231
+ {...(state === 'closed' && { inert: 'true' })}
226
232
  ref={ref}
227
233
  >
228
234
  {children}
@@ -232,17 +238,17 @@ const MainSidebar = forwardRef<HTMLDivElement, MainSidebarProps>(
232
238
  },
233
239
  );
234
240
 
235
- type MainNavigationSidebarProps = Omit<MainSidebarProps, 'open' | 'setOpen' | 'side'>;
241
+ type MainNavigationSidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
236
242
 
237
243
  const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarProps>((props, forwardedRef) => {
238
- const { navigationSidebarOpen, setNavigationSidebarOpen, resizing } = useMainContext(NAVIGATION_SIDEBAR_NAME);
244
+ const { navigationSidebarState, setNavigationSidebarState, resizing } = useMainContext(NAVIGATION_SIDEBAR_NAME);
239
245
  const mover = useLandmarkMover(props.onKeyDown, '0');
240
246
  return (
241
247
  <MainSidebar
242
248
  {...mover}
243
249
  {...props}
244
- open={navigationSidebarOpen}
245
- setOpen={setNavigationSidebarOpen}
250
+ state={navigationSidebarState}
251
+ onStateChange={setNavigationSidebarState}
246
252
  resizing={resizing}
247
253
  side='inline-start'
248
254
  ref={forwardedRef}
@@ -252,18 +258,18 @@ const MainNavigationSidebar = forwardRef<HTMLDivElement, MainNavigationSidebarPr
252
258
 
253
259
  MainNavigationSidebar.displayName = NAVIGATION_SIDEBAR_NAME;
254
260
 
255
- type MainComplementarySidebarProps = Omit<MainSidebarProps, 'open' | 'setOpen' | 'side'>;
261
+ type MainComplementarySidebarProps = Omit<MainSidebarProps, 'expanded' | 'side'>;
256
262
 
257
263
  const MainComplementarySidebar = forwardRef<HTMLDivElement, MainComplementarySidebarProps>((props, forwardedRef) => {
258
- const { complementarySidebarOpen, setComplementarySidebarOpen, resizing } =
264
+ const { complementarySidebarState, setComplementarySidebarState, resizing } =
259
265
  useMainContext(COMPLEMENTARY_SIDEBAR_NAME);
260
266
  const mover = useLandmarkMover(props.onKeyDown, '2');
261
267
  return (
262
268
  <MainSidebar
263
269
  {...mover}
264
270
  {...props}
265
- open={complementarySidebarOpen}
266
- setOpen={setComplementarySidebarOpen}
271
+ state={complementarySidebarState}
272
+ onStateChange={setComplementarySidebarState}
267
273
  resizing={resizing}
268
274
  side='inline-end'
269
275
  ref={forwardedRef}
@@ -281,7 +287,7 @@ type MainProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.div>> &
281
287
 
282
288
  const MainContent = forwardRef<HTMLDivElement, MainProps>(
283
289
  ({ asChild, classNames, bounce, handlesFocus, children, role, ...props }: MainProps, forwardedRef) => {
284
- const { navigationSidebarOpen, complementarySidebarOpen } = useMainContext(MAIN_NAME);
290
+ const { navigationSidebarState, complementarySidebarState } = useMainContext(MAIN_NAME);
285
291
  const { tx } = useThemeContext();
286
292
  const Root = asChild ? Slot : role ? 'div' : 'main';
287
293
 
@@ -292,8 +298,8 @@ const MainContent = forwardRef<HTMLDivElement, MainProps>(
292
298
  role={role}
293
299
  {...(handlesFocus && { ...mover })}
294
300
  {...props}
295
- data-sidebar-inline-start-state={navigationSidebarOpen ? 'open' : 'closed'}
296
- data-sidebar-inline-end-state={complementarySidebarOpen ? 'open' : 'closed'}
301
+ data-sidebar-inline-start-state={navigationSidebarState}
302
+ data-sidebar-inline-end-state={complementarySidebarState}
297
303
  className={tx('main.content', 'main', { bounce, handlesFocus }, classNames)}
298
304
  ref={forwardedRef}
299
305
  >
@@ -309,23 +315,23 @@ type MainOverlayProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primit
309
315
 
310
316
  const MainOverlay = forwardRef<HTMLDivElement, MainOverlayProps>(({ classNames, ...props }, forwardedRef) => {
311
317
  const [isLg] = useMediaQuery('lg', { ssr: false });
312
- const { navigationSidebarOpen, setNavigationSidebarOpen, complementarySidebarOpen, setComplementarySidebarOpen } =
318
+ const { navigationSidebarState, setNavigationSidebarState, complementarySidebarState, setComplementarySidebarState } =
313
319
  useMainContext(MAIN_NAME);
314
320
  const { tx } = useThemeContext();
315
321
  return (
316
322
  <div
317
323
  onClick={() => {
318
- setNavigationSidebarOpen(false);
319
- setComplementarySidebarOpen(false);
324
+ setNavigationSidebarState('collapsed');
325
+ setComplementarySidebarState('collapsed');
320
326
  }}
321
327
  {...props}
322
328
  className={tx(
323
329
  'main.overlay',
324
330
  'main__overlay',
325
- { isLg, inlineStartSidebarOpen: navigationSidebarOpen, inlineEndSidebarOpen: complementarySidebarOpen },
331
+ { isLg, inlineStartSidebarOpen: navigationSidebarState, inlineEndSidebarOpen: complementarySidebarState },
326
332
  classNames,
327
333
  )}
328
- data-state={navigationSidebarOpen || complementarySidebarOpen ? 'open' : 'closed'}
334
+ data-state={navigationSidebarState === 'expanded' || complementarySidebarState === 'expanded' ? 'open' : 'closed'}
329
335
  aria-hidden='true'
330
336
  ref={forwardedRef}
331
337
  />
@@ -340,6 +346,6 @@ export const Main = {
340
346
  ComplementarySidebar: MainComplementarySidebar,
341
347
  };
342
348
 
343
- export { useMainContext, useSidebars };
349
+ export { useMainContext, useSidebars, useLandmarkMover };
344
350
 
345
- export type { MainRootProps, MainProps, MainOverlayProps, MainNavigationSidebarProps };
351
+ export type { MainRootProps, MainProps, MainOverlayProps, MainNavigationSidebarProps, SidebarState };
@@ -1,46 +1,35 @@
1
1
  //
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
+ import React from 'react';
4
5
 
6
+ import { hueTokenThemes } from '@dxos/react-ui-theme';
5
7
  import '@dxos-theme';
8
+ import { type ChromaticPalette, type MessageValence } from '@dxos/react-ui-types';
6
9
 
7
10
  import { Tag } from './Tag';
8
11
  import { withTheme } from '../../testing';
9
12
 
13
+ const palettes = ['neutral', 'success', 'info', 'warning', 'error', ...Object.keys(hueTokenThemes)] as (
14
+ | ChromaticPalette
15
+ | MessageValence
16
+ )[];
17
+
10
18
  export default {
11
19
  title: 'ui/react-ui-core/Tag',
12
20
  component: Tag,
13
21
  decorators: [withTheme],
14
22
  parameters: { chromatic: { disableSnapshot: false } },
15
- argTypes: {
16
- palette: {
17
- control: 'select',
18
- options: [
19
- 'neutral',
20
- 'success',
21
- 'info',
22
- 'warning',
23
- 'error',
24
- 'red',
25
- 'orange',
26
- 'amber',
27
- 'yellow',
28
- 'lime',
29
- 'green',
30
- 'emerald',
31
- 'teal',
32
- 'cyan',
33
- 'sky',
34
- 'blue',
35
- 'indigo',
36
- 'violet',
37
- 'purple',
38
- 'fuchsia',
39
- 'pink',
40
- 'rose',
41
- ],
42
- },
43
- },
44
- } as any;
23
+ } as const;
45
24
 
46
- export const Default = { args: { children: 'Hello', palette: 'success' } };
25
+ export const Default = {
26
+ render: () => (
27
+ <div role='grid' className='grid grid-cols-5 gap-2 max-is-screen-md'>
28
+ {palettes.map((palette) => (
29
+ <Tag key={palette} palette={palette}>
30
+ {palette}
31
+ </Tag>
32
+ ))}
33
+ </div>
34
+ ),
35
+ };
@@ -1,5 +1,5 @@
1
1
  //
2
- // Copyright 2022 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
5
  import { Primitive } from '@radix-ui/react-primitive';
@@ -16,8 +16,17 @@ export type TagProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.sp
16
16
  asChild?: boolean;
17
17
  };
18
18
 
19
- export const Tag = forwardRef<HTMLSpanElement, TagProps>(({ asChild, palette, classNames, ...props }, forwardedRef) => {
20
- const { tx } = useThemeContext();
21
- const Root = asChild ? Slot : Primitive.span;
22
- return <Root {...props} className={tx('tag.root', 'tag', { palette }, classNames)} ref={forwardedRef} />;
23
- });
19
+ export const Tag = forwardRef<HTMLSpanElement, TagProps>(
20
+ ({ asChild, palette = 'neutral', classNames, ...props }, forwardedRef) => {
21
+ const { tx } = useThemeContext();
22
+ const Root = asChild ? Slot : Primitive.span;
23
+ return (
24
+ <Root
25
+ {...props}
26
+ className={tx('tag.root', 'dx-tag', { palette }, classNames)}
27
+ data-hue={palette}
28
+ ref={forwardedRef}
29
+ />
30
+ );
31
+ },
32
+ );