@dxos/react-ui 0.8.2-main.12df754 → 0.8.2-main.30e4dbb

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 (65) hide show
  1. package/dist/lib/browser/index.mjs +1607 -1075
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +1942 -1408
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +1607 -1075
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/Buttons/Button.stories.d.ts +10 -44
  11. package/dist/types/src/components/Buttons/Button.stories.d.ts.map +1 -1
  12. package/dist/types/src/components/Buttons/IconButton.d.ts +4 -5
  13. package/dist/types/src/components/Buttons/IconButton.d.ts.map +1 -1
  14. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  15. package/dist/types/src/components/Clipboard/CopyButton.d.ts +2 -1
  16. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  17. package/dist/types/src/components/Clipboard/index.d.ts +2 -2
  18. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  19. package/dist/types/src/components/Dialogs/Dialog.d.ts +6 -2
  20. package/dist/types/src/components/Dialogs/Dialog.d.ts.map +1 -1
  21. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  22. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  23. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +1 -1
  25. package/dist/types/src/components/Lists/TreeDropIndicator.d.ts.map +1 -1
  26. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  27. package/dist/types/src/components/Main/useSwipeToDismiss.d.ts.map +1 -1
  28. package/dist/types/src/components/Popover/Popover.d.ts +2 -1
  29. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  30. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  31. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  33. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -1
  34. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  35. package/dist/types/src/components/Tooltip/Tooltip.d.ts +94 -20
  36. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  37. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +40 -16
  38. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/index.d.ts +1 -1
  40. package/dist/types/src/components/index.d.ts.map +1 -1
  41. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  42. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  43. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  44. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -1
  45. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  46. package/dist/types/src/playground/Controls.stories.d.ts +1 -1
  47. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  48. package/dist/types/src/playground/Custom.stories.d.ts +8 -0
  49. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -0
  50. package/dist/types/src/testing/decorators/withVariants.d.ts.map +1 -1
  51. package/dist/types/tsconfig.tsbuildinfo +1 -1
  52. package/package.json +14 -13
  53. package/src/components/Avatars/Avatar.tsx +1 -1
  54. package/src/components/Buttons/Button.stories.tsx +19 -14
  55. package/src/components/Buttons/IconButton.stories.tsx +2 -2
  56. package/src/components/Buttons/IconButton.tsx +8 -33
  57. package/src/components/Clipboard/CopyButton.tsx +22 -24
  58. package/src/components/Dialogs/Dialog.tsx +12 -7
  59. package/src/components/Popover/Popover.tsx +3 -0
  60. package/src/components/ScrollArea/ScrollArea.tsx +3 -0
  61. package/src/components/Tooltip/Tooltip.stories.tsx +41 -16
  62. package/src/components/Tooltip/Tooltip.tsx +748 -58
  63. package/src/components/index.ts +1 -1
  64. package/src/playground/Controls.stories.tsx +2 -2
  65. package/src/playground/Custom.stories.tsx +137 -0
@@ -2,60 +2,35 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { forwardRef, type ReactNode, type MutableRefObject, useState } from 'react';
5
+ import React, { forwardRef, type MutableRefObject } from 'react';
6
6
 
7
7
  import { Button, type ButtonProps } from './Button';
8
8
  import { useThemeContext } from '../../hooks';
9
9
  import { type ThemedClassName } from '../../util';
10
10
  import { Icon, type IconProps } from '../Icon';
11
- import { Tooltip, type TooltipContentProps } from '../Tooltip';
11
+ import { Tooltip, type TooltipSide } from '../Tooltip';
12
12
 
13
13
  type IconButtonProps = Omit<ButtonProps, 'children'> &
14
14
  Pick<IconProps, 'icon' | 'size'> & {
15
- label: NonNullable<ReactNode>;
15
+ label: string;
16
16
  iconOnly?: boolean;
17
17
  noTooltip?: boolean;
18
18
  caretDown?: boolean;
19
- // TODO(burdon): Create slots abstraction?
20
19
  iconClassNames?: ThemedClassName<any>['classNames'];
21
20
  tooltipPortal?: boolean;
22
- tooltipZIndex?: string;
23
- tooltipSide?: TooltipContentProps['side'];
21
+ tooltipSide?: TooltipSide;
24
22
  suppressNextTooltip?: MutableRefObject<boolean>;
25
23
  };
26
24
 
27
25
  const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
28
- (
29
- { noTooltip, tooltipPortal = true, tooltipZIndex: zIndex, tooltipSide, suppressNextTooltip, ...props },
30
- forwardedRef,
31
- ) => {
32
- const [triggerTooltipOpen, setTriggerTooltipOpen] = useState(false);
26
+ ({ noTooltip, tooltipPortal = true, tooltipSide, suppressNextTooltip, ...props }, forwardedRef) => {
33
27
  if (noTooltip) {
34
28
  return <LabelledIconButton {...props} ref={forwardedRef} />;
35
29
  }
36
- const content = (
37
- <Tooltip.Content {...(zIndex && { style: { zIndex } })} side={tooltipSide}>
38
- {props.label}
39
- <Tooltip.Arrow />
40
- </Tooltip.Content>
41
- );
42
30
  return (
43
- <Tooltip.Root
44
- open={triggerTooltipOpen}
45
- onOpenChange={(nextOpen) => {
46
- if (suppressNextTooltip?.current) {
47
- setTriggerTooltipOpen(false);
48
- suppressNextTooltip.current = false;
49
- } else {
50
- setTriggerTooltipOpen(nextOpen);
51
- }
52
- }}
53
- >
54
- <Tooltip.Trigger asChild>
55
- <LabelledIconButton {...props} ref={forwardedRef} />
56
- </Tooltip.Trigger>
57
- {tooltipPortal ? <Tooltip.Portal>{content}</Tooltip.Portal> : content}
58
- </Tooltip.Root>
31
+ <Tooltip.Trigger asChild content={props.label} side={tooltipSide} suppressNextTooltip={suppressNextTooltip}>
32
+ <LabelledIconButton {...props} ref={forwardedRef} />
33
+ </Tooltip.Trigger>
59
34
  );
60
35
  },
61
36
  );
@@ -3,15 +3,15 @@
3
3
  //
4
4
 
5
5
  import { type IconProps } from '@phosphor-icons/react';
6
- import React, { useState } from 'react';
6
+ import React from 'react';
7
7
 
8
8
  import { mx } from '@dxos/react-ui-theme';
9
9
 
10
10
  import { useClipboard } from './ClipboardProvider';
11
- import { Button, type ButtonProps } from '../Buttons';
11
+ import { Button, type ButtonProps, IconButton } from '../Buttons';
12
12
  import { Icon } from '../Icon';
13
13
  import { useTranslation } from '../ThemeProvider';
14
- import { Tooltip } from '../Tooltip';
14
+ import { type TooltipScopedProps, useTooltipContext } from '../Tooltip';
15
15
 
16
16
  export type CopyButtonProps = ButtonProps & {
17
17
  value: string;
@@ -48,31 +48,29 @@ type CopyButtonIconOnlyProps = CopyButtonProps & {
48
48
  label?: string;
49
49
  };
50
50
 
51
- export const CopyButtonIconOnly = ({ value, classNames, iconProps, variant, ...props }: CopyButtonIconOnlyProps) => {
51
+ export const CopyButtonIconOnly = ({
52
+ __scopeTooltip,
53
+ value,
54
+ classNames,
55
+ iconProps,
56
+ variant,
57
+ ...props
58
+ }: TooltipScopedProps<CopyButtonIconOnlyProps>) => {
52
59
  const { t } = useTranslation('os');
53
60
  const { textValue, setTextValue } = useClipboard();
54
61
  const isCopied = textValue === value;
55
62
  const label = isCopied ? t('copy success label') : props.label ?? t('copy label');
56
- const [open, setOpen] = useState(false);
63
+ const { onOpen } = useTooltipContext('CopyButton', __scopeTooltip);
57
64
  return (
58
- <Tooltip.Root delayDuration={1500} open={open} onOpenChange={setOpen}>
59
- <Tooltip.Portal>
60
- <Tooltip.Content side='bottom' sideOffset={12}>
61
- <span>{label}</span>
62
- <Tooltip.Arrow />
63
- </Tooltip.Content>
64
- </Tooltip.Portal>
65
- <Tooltip.Trigger
66
- aria-label={label}
67
- {...props}
68
- onClick={() => setTextValue(value).then(() => setOpen(true))}
69
- data-testid='copy-invitation'
70
- asChild
71
- >
72
- <Button variant={variant} classNames={['inline-flex flex-col justify-center', classNames]}>
73
- <Icon icon='ph--copy--regular' size={5 as any} {...iconProps} />
74
- </Button>
75
- </Tooltip.Trigger>
76
- </Tooltip.Root>
65
+ <IconButton
66
+ iconOnly
67
+ label={label!}
68
+ icon='ph--copy--regular'
69
+ size={5}
70
+ variant={variant}
71
+ classNames={['inline-flex flex-col justify-center', classNames]}
72
+ onClick={() => setTextValue(value).then(onOpen)}
73
+ data-testid='copy-invitation'
74
+ />
77
75
  );
78
76
  };
@@ -78,14 +78,18 @@ type DialogCloseProps = DialogClosePrimitiveProps;
78
78
 
79
79
  const DialogClose: FunctionComponent<DialogCloseProps> = DialogClosePrimitive;
80
80
 
81
- type OverlayLayoutContextValue = { inOverlayLayout?: boolean };
81
+ type OverlayLayoutContextValue = { descriptionId?: string; inOverlayLayout?: boolean };
82
82
  const DIALOG_OVERLAY_NAME = 'DialogOverlay';
83
83
  const DIALOG_CONTENT_NAME = 'DialogContent';
84
- const [OverlayLayoutProvider, useOverlayLayoutContext] = createContext<OverlayLayoutContextValue>(DIALOG_OVERLAY_NAME, {
85
- inOverlayLayout: false,
86
- });
84
+ const [OverlayLayoutProvider, useOverlayLayoutContext] = createContext<OverlayLayoutContextValue>(
85
+ DIALOG_OVERLAY_NAME,
86
+ {},
87
+ );
87
88
 
88
- type DialogOverlayProps = ThemedClassName<DialogOverlayPrimitiveProps> & { blockAlign?: 'center' | 'start' | 'end' };
89
+ type DialogOverlayProps = ThemedClassName<
90
+ DialogOverlayPrimitiveProps &
91
+ Pick<OverlayLayoutContextValue, 'descriptionId'> & { blockAlign?: 'center' | 'start' | 'end' }
92
+ >;
89
93
 
90
94
  const DialogOverlay: ForwardRefExoticComponent<DialogOverlayProps> = forwardRef<HTMLDivElement, DialogOverlayProps>(
91
95
  ({ classNames, children, blockAlign, ...props }, forwardedRef) => {
@@ -111,11 +115,12 @@ type DialogContentProps = ThemedClassName<DialogContentPrimitiveProps> & { inOve
111
115
  const DialogContent: ForwardRefExoticComponent<DialogContentProps> = forwardRef<HTMLDivElement, DialogContentProps>(
112
116
  ({ classNames, children, inOverlayLayout: propsInOverlayLayout, ...props }, forwardedRef) => {
113
117
  const { tx } = useThemeContext();
114
- const { inOverlayLayout } = useOverlayLayoutContext(DIALOG_CONTENT_NAME);
118
+ const { inOverlayLayout, descriptionId } = useOverlayLayoutContext(DIALOG_CONTENT_NAME);
115
119
 
116
120
  return (
117
121
  <DialogContentPrimitive
118
- aria-describedby={undefined}
122
+ // NOTE: Radix warning unless set.
123
+ aria-describedby={descriptionId ?? 'unknown'}
119
124
  {...props}
120
125
  className={tx(
121
126
  'dialog.content',
@@ -571,6 +571,8 @@ const PopoverViewport = forwardRef<HTMLDivElement, PopoverViewportProps>(
571
571
 
572
572
  const getState = (open: boolean) => (open ? 'open' : 'closed');
573
573
 
574
+ type PopoverContentInteractOutsideEvent = Parameters<NonNullable<PopoverContentProps['onInteractOutside']>>[0];
575
+
574
576
  export const Popover = {
575
577
  Root: PopoverRoot,
576
578
  Anchor: PopoverAnchor,
@@ -595,4 +597,5 @@ export type {
595
597
  PopoverCloseProps,
596
598
  PopoverArrowProps,
597
599
  PopoverViewportProps,
600
+ PopoverContentInteractOutsideEvent,
598
601
  };
@@ -23,6 +23,9 @@ type ScrollAreaVariant = 'coarse' | 'fine';
23
23
 
24
24
  type ScrollAreaRootProps = ThemedClassName<ScrollAreaPrimitiveRootProps>;
25
25
 
26
+ /**
27
+ * @deprecated
28
+ */
26
29
  const ScrollAreaRoot = forwardRef<HTMLDivElement, ScrollAreaRootProps>(({ classNames, ...props }, forwardedRef) => {
27
30
  const { tx } = useThemeContext();
28
31
  return (
@@ -3,29 +3,28 @@
3
3
  //
4
4
 
5
5
  import '@dxos-theme';
6
-
7
6
  import React from 'react';
8
7
 
8
+ import { faker } from '@dxos/random';
9
+
9
10
  import { Tooltip } from './Tooltip';
10
11
  import { withTheme } from '../../testing';
11
12
  import { Button } from '../Buttons';
12
13
 
13
14
  type StoryTooltipProps = {
14
- content: string;
15
+ tooltips: { label: string; content: string }[];
15
16
  defaultOpen?: boolean;
16
17
  };
17
18
 
18
- const StoryTooltip = ({ content, defaultOpen }: StoryTooltipProps) => (
19
- <Tooltip.Provider>
20
- <Tooltip.Root defaultOpen={defaultOpen}>
21
- <Tooltip.Trigger asChild>
22
- <Button>Trigger tooltip</Button>
23
- </Tooltip.Trigger>
24
- <Tooltip.Content side='right'>
25
- <Tooltip.Arrow />
26
- {content}
27
- </Tooltip.Content>
28
- </Tooltip.Root>
19
+ const StoryTooltip = ({ tooltips, defaultOpen }: StoryTooltipProps) => (
20
+ <Tooltip.Provider defaultOpen={defaultOpen}>
21
+ <div role='none' className='is-32'>
22
+ {tooltips.map(({ label, content }, i) => (
23
+ <Tooltip.Trigger asChild key={i} content={content} side='right'>
24
+ <Button classNames='block is-full'>{label}</Button>
25
+ </Tooltip.Trigger>
26
+ ))}
27
+ </div>
29
28
  </Tooltip.Provider>
30
29
  );
31
30
 
@@ -39,19 +38,45 @@ export default {
39
38
 
40
39
  export const Default = {
41
40
  args: {
42
- content: 'This is the tooltip content',
41
+ tooltips: [
42
+ {
43
+ label: 'Tooltip trigger',
44
+ content: 'This is the tooltip content',
45
+ },
46
+ ],
43
47
  },
44
48
  parameters: {
45
49
  chromatic: { delay: 500 },
46
50
  },
47
51
  };
48
52
 
49
- export const Testing = {
53
+ export const DefaultOpen = {
50
54
  args: {
51
55
  defaultOption: true,
52
- content: 'This is the tooltip content',
56
+ tooltips: [
57
+ {
58
+ label: 'Tooltip trigger',
59
+ content: 'This is the tooltip content',
60
+ },
61
+ ],
53
62
  },
54
63
  parameters: {
55
64
  chromatic: { delay: 500 },
56
65
  },
57
66
  };
67
+
68
+ export const StressTest = {
69
+ args: {
70
+ defaultOption: true,
71
+ tooltips: faker.helpers.multiple(
72
+ () => ({
73
+ label: faker.lorem.words(2),
74
+ content: faker.lorem.words(5),
75
+ }),
76
+ { count: 32 },
77
+ ),
78
+ },
79
+ parameters: {
80
+ chromatic: { disableSnapshot: true },
81
+ },
82
+ };