@dxos/react-ui 0.8.1 → 0.8.2-main.10c050d

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 (135) hide show
  1. package/dist/lib/browser/chunk-5Y5JI6KC.mjs +4355 -0
  2. package/dist/lib/browser/chunk-5Y5JI6KC.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +75 -2986
  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 +85 -0
  7. package/dist/lib/browser/testing/index.mjs.map +7 -0
  8. package/dist/lib/node/chunk-KMS7RFL7.cjs +4340 -0
  9. package/dist/lib/node/chunk-KMS7RFL7.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +71 -2946
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +114 -0
  14. package/dist/lib/node/testing/index.cjs.map +7 -0
  15. package/dist/lib/node-esm/chunk-ANVE7WX5.mjs +4357 -0
  16. package/dist/lib/node-esm/chunk-ANVE7WX5.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +74 -2986
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +86 -0
  21. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  22. package/dist/types/src/components/Avatars/Avatar.d.ts +4 -4
  23. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  24. package/dist/types/src/components/Avatars/Avatar.stories.d.ts +3 -3
  25. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts +0 -1
  27. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Buttons/Button.stories.d.ts +10 -44
  29. package/dist/types/src/components/Buttons/Button.stories.d.ts.map +1 -1
  30. package/dist/types/src/components/Buttons/IconButton.d.ts +4 -6
  31. package/dist/types/src/components/Buttons/IconButton.d.ts.map +1 -1
  32. package/dist/types/src/components/Buttons/IconButton.stories.d.ts +7 -6
  33. package/dist/types/src/components/Buttons/IconButton.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/Buttons/Toggle.stories.d.ts.map +1 -1
  35. package/dist/types/src/components/Buttons/ToggleGroup.stories.d.ts +1 -4
  36. package/dist/types/src/components/Buttons/ToggleGroup.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  38. package/dist/types/src/components/Clipboard/CopyButton.d.ts +2 -1
  39. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  40. package/dist/types/src/components/Clipboard/index.d.ts +2 -2
  41. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  42. package/dist/types/src/components/Dialogs/AlertDialog.stories.d.ts +2 -2
  43. package/dist/types/src/components/Dialogs/AlertDialog.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/Dialogs/Dialog.d.ts +2 -2
  45. package/dist/types/src/components/Dialogs/Dialog.d.ts.map +1 -1
  46. package/dist/types/src/components/Dialogs/Dialog.stories.d.ts +2 -2
  47. package/dist/types/src/components/Dialogs/Dialog.stories.d.ts.map +1 -1
  48. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  49. package/dist/types/src/components/Input/Input.d.ts +1 -1
  50. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  51. package/dist/types/src/components/Input/Input.stories.d.ts +33 -159
  52. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  53. package/dist/types/src/components/Lists/ListDropIndicator.d.ts.map +1 -1
  54. package/dist/types/src/components/Lists/Tree.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/Lists/TreeDropIndicator.d.ts.map +1 -1
  56. package/dist/types/src/components/Lists/Treegrid.stories.d.ts +1 -1
  57. package/dist/types/src/components/Lists/Treegrid.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  59. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  60. package/dist/types/src/components/Main/useSwipeToDismiss.d.ts.map +1 -1
  61. package/dist/types/src/components/Message/Message.stories.d.ts +8 -2
  62. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  63. package/dist/types/src/components/Popover/Popover.d.ts +15 -6
  64. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  65. package/dist/types/src/components/Popover/Popover.stories.d.ts +5 -1
  66. package/dist/types/src/components/Popover/Popover.stories.d.ts.map +1 -1
  67. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  68. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  69. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  70. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  71. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +1 -1
  72. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  73. package/dist/types/src/components/Toast/Toast.stories.d.ts +2 -2
  74. package/dist/types/src/components/Toast/Toast.stories.d.ts.map +1 -1
  75. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/Tooltip/Tooltip.d.ts +92 -20
  77. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  78. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +40 -17
  79. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  80. package/dist/types/src/components/index.d.ts +1 -1
  81. package/dist/types/src/components/index.d.ts.map +1 -1
  82. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  83. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  84. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  85. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -1
  86. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  87. package/dist/types/src/playground/Controls.stories.d.ts +1 -1
  88. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  89. package/dist/types/src/playground/Custom.stories.d.ts +8 -0
  90. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -0
  91. package/dist/types/src/testing/decorators/index.d.ts +1 -1
  92. package/dist/types/src/testing/decorators/index.d.ts.map +1 -1
  93. package/dist/types/src/testing/decorators/{withVariants.d.ts → withSurfaceVariantsLayout.d.ts} +2 -3
  94. package/dist/types/src/testing/decorators/withSurfaceVariantsLayout.d.ts.map +1 -0
  95. package/dist/types/tsconfig.tsbuildinfo +1 -1
  96. package/package.json +25 -15
  97. package/src/components/Avatars/Avatar.stories.tsx +27 -27
  98. package/src/components/Avatars/Avatar.tsx +24 -21
  99. package/src/components/Avatars/AvatarGroup.stories.tsx +4 -5
  100. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +2 -2
  101. package/src/components/Buttons/Button.stories.tsx +20 -15
  102. package/src/components/Buttons/IconButton.stories.tsx +9 -10
  103. package/src/components/Buttons/IconButton.tsx +9 -38
  104. package/src/components/Buttons/Toggle.stories.tsx +2 -2
  105. package/src/components/Buttons/ToggleGroup.stories.tsx +3 -7
  106. package/src/components/Clipboard/CopyButton.tsx +22 -24
  107. package/src/components/Dialogs/AlertDialog.stories.tsx +4 -11
  108. package/src/components/Dialogs/Dialog.stories.tsx +3 -3
  109. package/src/components/Dialogs/Dialog.tsx +8 -4
  110. package/src/components/Input/Input.stories.tsx +69 -58
  111. package/src/components/Input/Input.tsx +1 -0
  112. package/src/components/Lists/Tree.stories.tsx +2 -2
  113. package/src/components/Lists/Treegrid.stories.tsx +12 -12
  114. package/src/components/Main/Main.stories.tsx +2 -2
  115. package/src/components/Main/Main.tsx +1 -0
  116. package/src/components/Menus/ContextMenu.stories.tsx +2 -2
  117. package/src/components/Menus/DropdownMenu.stories.tsx +2 -2
  118. package/src/components/Message/Message.stories.tsx +10 -4
  119. package/src/components/Popover/Popover.stories.tsx +2 -2
  120. package/src/components/Popover/Popover.tsx +8 -4
  121. package/src/components/ScrollArea/ScrollArea.stories.tsx +4 -4
  122. package/src/components/ScrollArea/ScrollArea.tsx +3 -0
  123. package/src/components/Select/Select.stories.tsx +2 -2
  124. package/src/components/Toast/Toast.stories.tsx +15 -10
  125. package/src/components/Toolbar/Toolbar.stories.tsx +2 -2
  126. package/src/components/Tooltip/Tooltip.stories.tsx +43 -18
  127. package/src/components/Tooltip/Tooltip.tsx +733 -58
  128. package/src/components/index.ts +1 -1
  129. package/src/playground/Controls.stories.tsx +4 -4
  130. package/src/playground/Custom.stories.tsx +137 -0
  131. package/src/playground/Typography.stories.tsx +2 -2
  132. package/src/testing/decorators/index.ts +1 -1
  133. package/src/testing/decorators/withSurfaceVariantsLayout.tsx +53 -0
  134. package/dist/types/src/testing/decorators/withVariants.d.ts.map +0 -1
  135. package/src/testing/decorators/withVariants.tsx +0 -45
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui",
3
- "version": "0.8.1",
3
+ "version": "0.8.2-main.10c050d",
4
4
  "description": "Low-level React components for DXOS, applying a theme to a core group of primitives",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -13,11 +13,20 @@
13
13
  "types": "./dist/types/src/index.d.ts",
14
14
  "browser": "./dist/lib/browser/index.mjs",
15
15
  "node": "./dist/lib/node-esm/index.mjs"
16
+ },
17
+ "./testing": {
18
+ "types": "./dist/types/src/testing/index.d.ts",
19
+ "browser": "./dist/lib/browser/testing/index.mjs",
20
+ "node": "./dist/lib/node-esm/testing/index.mjs"
16
21
  }
17
22
  },
18
23
  "types": "dist/types/src/index.d.ts",
19
24
  "typesVersions": {
20
- "*": {}
25
+ "*": {
26
+ "testing": [
27
+ "./dist/types/src/testing/index.d.ts"
28
+ ]
29
+ }
21
30
  },
22
31
  "files": [
23
32
  "dist",
@@ -26,7 +35,7 @@
26
35
  "dependencies": {
27
36
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
28
37
  "@fluentui/react-tabster": "^9.24.2",
29
- "@lit/react": "^1.0.5",
38
+ "@preact-signals/safe-react": "^0.9.0",
30
39
  "@radix-ui/primitive": "1.1.1",
31
40
  "@radix-ui/react-alert-dialog": "1.1.6",
32
41
  "@radix-ui/react-avatar": "1.1.3",
@@ -56,20 +65,21 @@
56
65
  "@radix-ui/react-toolbar": "1.1.2",
57
66
  "@radix-ui/react-tooltip": "1.1.8",
58
67
  "@radix-ui/react-use-controllable-state": "1.1.0",
68
+ "@radix-ui/react-visually-hidden": "1.1.2",
59
69
  "aria-hidden": "^1.2.4",
60
70
  "date-fns": "^3.3.1",
61
71
  "i18next": "^21.10.0",
62
72
  "keyborg": "^2.5.0",
63
73
  "react-i18next": "^11.18.6",
64
74
  "react-remove-scroll": "^2.6.0",
65
- "@dxos/debug": "0.8.1",
66
- "@dxos/lit-ui": "0.8.1",
67
- "@dxos/log": "0.8.1",
68
- "@dxos/react-hooks": "0.8.1",
69
- "@dxos/react-input": "0.8.1",
70
- "@dxos/react-ui-types": "0.8.1",
71
- "@dxos/react-list": "0.8.1",
72
- "@dxos/util": "0.8.1"
75
+ "@dxos/debug": "0.8.2-main.10c050d",
76
+ "@dxos/lit-ui": "0.8.2-main.10c050d",
77
+ "@dxos/log": "0.8.2-main.10c050d",
78
+ "@dxos/react-hooks": "0.8.2-main.10c050d",
79
+ "@dxos/react-input": "0.8.2-main.10c050d",
80
+ "@dxos/react-list": "0.8.2-main.10c050d",
81
+ "@dxos/react-ui-types": "0.8.2-main.10c050d",
82
+ "@dxos/util": "0.8.2-main.10c050d"
73
83
  },
74
84
  "devDependencies": {
75
85
  "@dnd-kit/core": "^6.0.5",
@@ -81,15 +91,15 @@
81
91
  "react": "~18.2.0",
82
92
  "react-dom": "~18.2.0",
83
93
  "vite": "5.4.7",
84
- "@dxos/random": "0.8.1",
85
- "@dxos/react-ui-theme": "0.8.1",
86
- "@dxos/util": "0.8.1"
94
+ "@dxos/random": "0.8.2-main.10c050d",
95
+ "@dxos/react-ui-theme": "0.8.2-main.10c050d",
96
+ "@dxos/util": "0.8.2-main.10c050d"
87
97
  },
88
98
  "peerDependencies": {
89
99
  "@phosphor-icons/react": "^2.1.5",
90
100
  "react": "~18.2.0",
91
101
  "react-dom": "~18.2.0",
92
- "@dxos/react-ui-theme": "0.8.1"
102
+ "@dxos/react-ui-theme": "0.8.2-main.10c050d"
93
103
  },
94
104
  "publishConfig": {
95
105
  "access": "public"
@@ -12,7 +12,7 @@ import { hexToFallback } from '@dxos/util';
12
12
  import { Avatar, type AvatarVariant, type AvatarStatus, type AvatarAnimation } from './Avatar';
13
13
  import { withTheme } from '../../testing';
14
14
 
15
- type StorybookAvatarProps = {
15
+ type StoryProps = {
16
16
  id?: string;
17
17
  imgSrc?: string;
18
18
  fallbackText?: string;
@@ -25,7 +25,7 @@ type StorybookAvatarProps = {
25
25
  hue?: HuePalette;
26
26
  };
27
27
 
28
- const StorybookAvatar = (props: PropsWithChildren<StorybookAvatarProps>) => {
28
+ const DefaultStory = (props: PropsWithChildren<StoryProps>) => {
29
29
  const {
30
30
  id = '20970b563fc49b5bb194a6ffdff376031a3a11f9481360c071c3fed87874106b',
31
31
  status,
@@ -58,7 +58,7 @@ const StorybookAvatar = (props: PropsWithChildren<StorybookAvatarProps>) => {
58
58
  export default {
59
59
  title: 'ui/react-ui-core/Avatar',
60
60
  component: Avatar,
61
- render: StorybookAvatar,
61
+ render: DefaultStory,
62
62
  decorators: [withTheme],
63
63
  parameters: { chromatic: { disableSnapshot: false } },
64
64
  };
@@ -68,9 +68,9 @@ const sampleImage =
68
68
 
69
69
  const row = (size: Size) => (
70
70
  <>
71
- <StorybookAvatar size={size} status='inactive' description='Offline' />
72
- <StorybookAvatar size={size} status='active' />
73
- <StorybookAvatar size={size} status='active' imgSrc={sampleImage} />
71
+ <DefaultStory size={size} status='inactive' description='Offline' />
72
+ <DefaultStory size={size} status='active' />
73
+ <DefaultStory size={size} status='active' imgSrc={sampleImage} />
74
74
  </>
75
75
  );
76
76
 
@@ -93,48 +93,48 @@ export const Default = () => (
93
93
 
94
94
  export const Image = () => (
95
95
  <div>
96
- <StorybookAvatar variant='circle' imgSrc={sampleImage} />
96
+ <DefaultStory variant='circle' imgSrc={sampleImage} />
97
97
  </div>
98
98
  );
99
99
 
100
100
  export const Square = () => (
101
101
  <div className='flex flex-row gap-4'>
102
- <StorybookAvatar variant='square' status='inactive' description='Offline' />
103
- <StorybookAvatar variant='square' status='active' />
104
- <StorybookAvatar variant='square' status='error' />
105
- <StorybookAvatar variant='square' status='warning' />
102
+ <DefaultStory variant='square' status='inactive' description='Offline' />
103
+ <DefaultStory variant='square' status='active' />
104
+ <DefaultStory variant='square' status='error' />
105
+ <DefaultStory variant='square' status='warning' />
106
106
  </div>
107
107
  );
108
108
 
109
109
  export const DefaultEmoji = () => (
110
110
  <div className='flex flex-row gap-4'>
111
- <StorybookAvatar fallbackText='🦄' status='active' animation='pulse' />
112
- <StorybookAvatar fallbackText='🐒' status='warning' animation='pulse' />
113
- <StorybookAvatar fallbackText='🪲' status='inactive' />
114
- <StorybookAvatar fallbackText='🦁' />
111
+ <DefaultStory fallbackText='🦄' status='active' animation='pulse' />
112
+ <DefaultStory fallbackText='🐒' status='warning' animation='pulse' />
113
+ <DefaultStory fallbackText='🪲' status='inactive' />
114
+ <DefaultStory fallbackText='🦁' />
115
115
  </div>
116
116
  );
117
117
 
118
- export const SquareEmoji = () => <StorybookAvatar variant='square' fallbackText='🦄' />;
118
+ export const SquareEmoji = () => <DefaultStory variant='square' fallbackText='🦄' />;
119
119
 
120
120
  export const DefaultText = () => (
121
121
  <div className='flex flex-row gap-4'>
122
- <StorybookAvatar fallbackText='PT' />
123
- <StorybookAvatar fallbackText='AP' />
124
- <StorybookAvatar fallbackText='Z' />
125
- <StorybookAvatar fallbackText='pt' />
126
- <StorybookAvatar fallbackText='ap' />
127
- <StorybookAvatar fallbackText='z' />
122
+ <DefaultStory fallbackText='PT' />
123
+ <DefaultStory fallbackText='AP' />
124
+ <DefaultStory fallbackText='Z' />
125
+ <DefaultStory fallbackText='pt' />
126
+ <DefaultStory fallbackText='ap' />
127
+ <DefaultStory fallbackText='z' />
128
128
  </div>
129
129
  );
130
130
 
131
- export const Error = () => <StorybookAvatar status='error' description='Errored' />;
131
+ export const Error = () => <DefaultStory status='error' description='Errored' />;
132
132
 
133
133
  export const Pulse = () => (
134
134
  <div className='flex flex-row gap-4'>
135
- <StorybookAvatar description='Online' status='active' animation='pulse' />
136
- <StorybookAvatar description='Offline' status='inactive' animation='pulse' />
137
- <StorybookAvatar description='Error' status='error' animation='pulse' />
138
- <StorybookAvatar description='Warning' status='warning' animation='pulse' />
135
+ <DefaultStory description='Online' status='active' animation='pulse' />
136
+ <DefaultStory description='Offline' status='inactive' animation='pulse' />
137
+ <DefaultStory description='Error' status='error' animation='pulse' />
138
+ <DefaultStory description='Warning' status='warning' animation='pulse' />
139
139
  </div>
140
140
  );
@@ -4,13 +4,18 @@
4
4
 
5
5
  import '@dxos/lit-ui/dx-avatar.pcss';
6
6
 
7
- import { createComponent } from '@lit/react';
8
7
  import { createContext } from '@radix-ui/react-context';
9
8
  import { Primitive } from '@radix-ui/react-primitive';
10
9
  import { Slot } from '@radix-ui/react-slot';
11
10
  import React, { type ComponentProps, type ComponentPropsWithRef, forwardRef, type PropsWithChildren } from 'react';
12
11
 
13
- import { type AvatarVariant, type AvatarStatus, type AvatarAnimation, DxAvatar as NaturalDxAvatar } from '@dxos/lit-ui';
12
+ import {
13
+ type AvatarVariant,
14
+ type AvatarStatus,
15
+ type AvatarAnimation,
16
+ type DxAvatar as NaturalDxAvatar,
17
+ } from '@dxos/lit-ui';
18
+ import { DxAvatar } from '@dxos/lit-ui/react';
14
19
  import { useId } from '@dxos/react-hooks';
15
20
  import { mx } from '@dxos/react-ui-theme';
16
21
 
@@ -33,27 +38,24 @@ const AvatarRoot = ({ children, labelId: propsLabelId, descriptionId: propsDescr
33
38
  return <AvatarProvider {...{ labelId, descriptionId }}>{children}</AvatarProvider>;
34
39
  };
35
40
 
36
- const DxAvatar = createComponent({
37
- tagName: 'dx-avatar',
38
- elementClass: NaturalDxAvatar,
39
- react: React,
40
- });
41
-
42
41
  type AvatarContentProps = ThemedClassName<Omit<ComponentProps<typeof DxAvatar>, 'children'>>;
43
42
 
44
- const AvatarContent = ({ icon, classNames, ...props }: AvatarContentProps) => {
45
- const href = useIconHref(icon);
46
- const { labelId, descriptionId } = useAvatarContext('AvatarContent');
47
- return (
48
- <DxAvatar
49
- {...props}
50
- icon={href}
51
- labelId={labelId}
52
- aria-describedby={descriptionId}
53
- rootClassName={mx(classNames)}
54
- />
55
- );
56
- };
43
+ const AvatarContent = forwardRef<NaturalDxAvatar, AvatarContentProps>(
44
+ ({ icon, classNames, ...props }, forwardedRef) => {
45
+ const href = useIconHref(icon);
46
+ const { labelId, descriptionId } = useAvatarContext('AvatarContent');
47
+ return (
48
+ <DxAvatar
49
+ {...props}
50
+ icon={href}
51
+ aria-labelledby={labelId}
52
+ aria-describedby={descriptionId}
53
+ rootClassName={mx(classNames)}
54
+ ref={forwardedRef}
55
+ />
56
+ );
57
+ },
58
+ );
57
59
 
58
60
  type AvatarLabelProps = ThemedClassName<Omit<ComponentPropsWithRef<typeof Primitive.span>, 'id'>> & {
59
61
  asChild?: boolean;
@@ -113,4 +115,5 @@ export type {
113
115
  AvatarContentProps,
114
116
  AvatarLabelProps,
115
117
  AvatarDescriptionProps,
118
+ NaturalDxAvatar as DxAvatar,
116
119
  };
@@ -13,7 +13,7 @@ import { withTheme } from '../../testing';
13
13
 
14
14
  const hues = ['lime', 'teal', 'purple', 'pink'];
15
15
 
16
- const StorybookAvatarGroupItem = ({ n }: { n: number }) => {
16
+ const AvatarItem = ({ n }: { n: number }) => {
17
17
  const emoji = toEmoji(n);
18
18
  return (
19
19
  <Avatar.Root>
@@ -22,12 +22,12 @@ const StorybookAvatarGroupItem = ({ n }: { n: number }) => {
22
22
  );
23
23
  };
24
24
 
25
- const StorybookAvatarGroup = () => {
25
+ const DefaultStory = () => {
26
26
  const labelId = useId('sb-avatar-group');
27
27
  return (
28
28
  <div className='dx-avatar-group' aria-labelledby={labelId}>
29
29
  {[0, 1, 2, 3].map((n) => (
30
- <StorybookAvatarGroupItem key={n} n={n} />
30
+ <AvatarItem key={n} n={n} />
31
31
  ))}
32
32
  <span className='sr-only' id={labelId}>
33
33
  23
@@ -38,8 +38,7 @@ const StorybookAvatarGroup = () => {
38
38
 
39
39
  export default {
40
40
  title: 'ui/react-ui-core/AvatarGroup',
41
- component: StorybookAvatarGroup,
42
- render: StorybookAvatarGroup,
41
+ render: DefaultStory,
43
42
  decorators: [withTheme],
44
43
  parameters: { chromatic: { disableSnapshot: false } },
45
44
  };
@@ -10,7 +10,7 @@ import { Breadcrumb } from './Breadcrumb';
10
10
  import { withTheme } from '../../testing';
11
11
  import { Button } from '../Buttons';
12
12
 
13
- const StorybookBreadcrumb = () => {
13
+ const DefaultStory = () => {
14
14
  return (
15
15
  <Breadcrumb.Root aria-label='Breadcrumb'>
16
16
  <Breadcrumb.List>
@@ -41,7 +41,7 @@ const StorybookBreadcrumb = () => {
41
41
  export default {
42
42
  title: 'ui/react-ui-core/Breadcrumb',
43
43
  component: Breadcrumb,
44
- render: StorybookBreadcrumb,
44
+ render: DefaultStory,
45
45
  decorators: [withTheme],
46
46
  parameters: { chromatic: { disableSnapshot: false } },
47
47
  };
@@ -5,10 +5,11 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { CaretLeft, CaretRight } from '@phosphor-icons/react';
8
+ import { type StoryObj, type Meta } from '@storybook/react';
8
9
  import React from 'react';
9
10
 
10
11
  import { Button, ButtonGroup, type ButtonProps } from './Button';
11
- import { withVariants, withTheme } from '../../testing';
12
+ import { withSurfaceVariantsLayout, withTheme } from '../../testing';
12
13
 
13
14
  const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
14
15
  return (
@@ -31,32 +32,36 @@ const DefaultStory = ({ children, ...args }: Omit<ButtonProps, 'ref'>) => {
31
32
  );
32
33
  };
33
34
 
34
- const defaults = { children: 'Test' };
35
+ const meta: Meta<typeof Button> = {
36
+ title: 'ui/react-ui-core/Button',
37
+ component: Button,
38
+ render: DefaultStory,
39
+ decorators: [withSurfaceVariantsLayout(), withTheme],
40
+ parameters: { chromatic: { disableSnapshot: false } },
41
+ };
42
+
43
+ export default meta;
44
+
45
+ type Story = StoryObj<typeof meta>;
35
46
 
36
- export const Default = {
47
+ const defaults: Story['args'] = { children: 'Test' };
48
+
49
+ export const Default: Story = {
37
50
  args: { ...defaults, variant: 'default' },
38
51
  };
39
52
 
40
- export const Primary = {
53
+ export const Primary: Story = {
41
54
  args: { ...defaults, variant: 'primary' },
42
55
  };
43
56
 
44
- export const Destructive = {
57
+ export const Destructive: Story = {
45
58
  args: { ...defaults, variant: 'destructive' },
46
59
  };
47
60
 
48
- export const Outline = {
61
+ export const Outline: Story = {
49
62
  args: { ...defaults, variant: 'outline' },
50
63
  };
51
64
 
52
- export const Ghost = {
65
+ export const Ghost: Story = {
53
66
  args: { ...defaults, variant: 'ghost' },
54
67
  };
55
-
56
- export default {
57
- title: 'ui/react-ui-core/Button',
58
- component: Button,
59
- decorators: [withVariants(), withTheme],
60
- render: DefaultStory,
61
- parameters: { chromatic: { disableSnapshot: false } },
62
- };
@@ -6,22 +6,18 @@ import '@dxos-theme';
6
6
 
7
7
  import React from 'react';
8
8
 
9
- import { IconButton } from './IconButton';
9
+ import { IconButton, type IconButtonProps } from './IconButton';
10
10
  import { withTheme } from '../../testing';
11
11
  import { Tooltip } from '../Tooltip';
12
12
 
13
- type StorybookIconButtonProps = {
14
- iconOnly?: boolean;
15
- };
16
-
17
- const StorybookIconButton = (props: StorybookIconButtonProps) => {
13
+ const DefaultStory = (props: IconButtonProps) => {
18
14
  return (
19
15
  <Tooltip.Provider>
20
16
  <div className='mbe-4'>
21
- <IconButton label='Bold' icon='ph--text-b--bold' {...props} />
17
+ <IconButton {...props} />
22
18
  </div>
23
19
  <div className='mbe-4'>
24
- <IconButton iconOnly label='Bold' icon='ph--text-b--bold' {...props} />
20
+ <IconButton iconOnly {...props} />
25
21
  </div>
26
22
  </Tooltip.Provider>
27
23
  );
@@ -30,11 +26,14 @@ const StorybookIconButton = (props: StorybookIconButtonProps) => {
30
26
  export default {
31
27
  title: 'ui/react-ui-core/IconButton',
32
28
  component: IconButton,
33
- render: StorybookIconButton,
29
+ render: DefaultStory,
34
30
  decorators: [withTheme],
35
31
  parameters: { chromatic: { disableSnapshot: false } },
36
32
  };
37
33
 
38
34
  export const Default = {
39
- args: {},
35
+ args: {
36
+ label: 'Bold',
37
+ icon: 'ph--text-b--regular',
38
+ },
40
39
  };
@@ -2,69 +2,40 @@
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 } 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'];
24
- suppressNextTooltip?: MutableRefObject<boolean>;
21
+ tooltipSide?: TooltipSide;
25
22
  };
26
23
 
27
24
  const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
28
- (
29
- { noTooltip, tooltipPortal = true, tooltipZIndex: zIndex, tooltipSide, suppressNextTooltip, ...props },
30
- forwardedRef,
31
- ) => {
32
- const [triggerTooltipOpen, setTriggerTooltipOpen] = useState(false);
25
+ ({ noTooltip, tooltipPortal = true, tooltipSide, ...props }, forwardedRef) => {
33
26
  if (noTooltip) {
34
27
  return <LabelledIconButton {...props} ref={forwardedRef} />;
35
28
  }
36
- const content = (
37
- <Tooltip.Content {...(zIndex && { style: { zIndex } })} side={tooltipSide}>
38
- {props.label}
39
- <Tooltip.Arrow />
40
- </Tooltip.Content>
41
- );
42
29
  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>
30
+ <Tooltip.Trigger asChild content={props.label} side={tooltipSide}>
31
+ <LabelledIconButton {...props} ref={forwardedRef} />
32
+ </Tooltip.Trigger>
59
33
  );
60
34
  },
61
35
  );
62
36
 
63
37
  const LabelledIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
64
- (
65
- { icon, size, iconOnly, label, classNames, iconClassNames, caretDown, suppressNextTooltip, ...props },
66
- forwardedRef,
67
- ) => {
38
+ ({ icon, size, iconOnly, label, classNames, iconClassNames, caretDown, ...props }, forwardedRef) => {
68
39
  const { tx } = useThemeContext();
69
40
  return (
70
41
  <Button {...props} classNames={tx('iconButton.root', 'iconButton', {}, classNames)} ref={forwardedRef}>
@@ -12,7 +12,7 @@ import { withTheme } from '../../testing';
12
12
 
13
13
  type StorybookToggleProps = {};
14
14
 
15
- const StorybookToggle = (props: StorybookToggleProps) => {
15
+ const DefaultStory = (props: StorybookToggleProps) => {
16
16
  return (
17
17
  <Toggle {...props}>
18
18
  <TextB />
@@ -23,7 +23,7 @@ const StorybookToggle = (props: StorybookToggleProps) => {
23
23
  export default {
24
24
  title: 'ui/react-ui-core/Toggle',
25
25
  component: Toggle,
26
- render: StorybookToggle,
26
+ render: DefaultStory,
27
27
  decorators: [withTheme],
28
28
  parameters: { chromatic: { disableSnapshot: false } },
29
29
  };
@@ -10,12 +10,8 @@ import React from 'react';
10
10
  import { ToggleGroup, ToggleGroupItem, type ToggleGroupProps } from './ToggleGroup';
11
11
  import { withTheme } from '../../testing';
12
12
 
13
- type StorybookToggleGroupProps = {
14
- type: ToggleGroupProps['type'];
15
- };
16
-
17
- // TODO(burdon): ToggleGroup.Item.
18
- const StorybookToggleGroup = (props: StorybookToggleGroupProps) => {
13
+ // TODO(burdon): Create Radix-style Root, Item, etc?
14
+ const DefaultStory = (props: ToggleGroupProps) => {
19
15
  return (
20
16
  <ToggleGroup {...props}>
21
17
  <ToggleGroupItem value='textb'>
@@ -31,7 +27,7 @@ const StorybookToggleGroup = (props: StorybookToggleGroupProps) => {
31
27
  export default {
32
28
  title: 'ui/react-ui-core/ToggleGroup',
33
29
  component: ToggleGroup,
34
- render: StorybookToggleGroup,
30
+ render: DefaultStory,
35
31
  decorators: [withTheme],
36
32
  parameters: { chromatic: { disableSnapshot: false } },
37
33
  };
@@ -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
  };
@@ -11,23 +11,16 @@ import { withTheme } from '../../testing';
11
11
  import { Button } from '../Buttons';
12
12
  import { Toolbar } from '../Toolbar';
13
13
 
14
- type StorybookAlertDialogProps = Partial<{
14
+ type StoryProps = Partial<{
15
15
  title: string;
16
16
  description: string;
17
17
  body: string;
18
- cancelTrigger: string; // TODO(burdon): Why trigger?
18
+ cancelTrigger: string;
19
19
  actionTrigger: string;
20
20
  openTrigger: string;
21
21
  }>;
22
22
 
23
- const StorybookAlertDialog = ({
24
- title,
25
- openTrigger,
26
- description,
27
- body,
28
- cancelTrigger,
29
- actionTrigger,
30
- }: StorybookAlertDialogProps) => {
23
+ const DefaultStory = ({ title, openTrigger, description, body, cancelTrigger, actionTrigger }: StoryProps) => {
31
24
  return (
32
25
  <AlertDialog.Root defaultOpen>
33
26
  <AlertDialog.Trigger asChild>
@@ -56,7 +49,7 @@ const StorybookAlertDialog = ({
56
49
  export default {
57
50
  title: 'ui/react-ui-core/AlertDialog',
58
51
  component: AlertDialog,
59
- render: StorybookAlertDialog,
52
+ render: DefaultStory,
60
53
  decorators: [withTheme],
61
54
  parameters: { chromatic: { disableSnapshot: false } },
62
55
  };