@dxos/react-ui 0.8.4-main.422d1c7879 → 0.8.4-main.4f23b4e393

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 (177) hide show
  1. package/dist/lib/browser/{chunk-OCVRIJCH.mjs → chunk-BDBC6H6V.mjs} +1 -1
  2. package/dist/lib/browser/{chunk-OCVRIJCH.mjs.map → chunk-BDBC6H6V.mjs.map} +2 -2
  3. package/dist/lib/browser/index.mjs +71 -85
  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 +1 -7
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/browser/translations.mjs +18 -0
  9. package/dist/lib/browser/translations.mjs.map +7 -0
  10. package/dist/lib/node-esm/{chunk-QUD5P3RU.mjs → chunk-3JSJK2ZY.mjs} +1 -1
  11. package/dist/lib/node-esm/{chunk-QUD5P3RU.mjs.map → chunk-3JSJK2ZY.mjs.map} +2 -2
  12. package/dist/lib/node-esm/index.mjs +71 -85
  13. package/dist/lib/node-esm/index.mjs.map +4 -4
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/testing/index.mjs +1 -7
  16. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  17. package/dist/lib/node-esm/translations.mjs +20 -0
  18. package/dist/lib/node-esm/translations.mjs.map +7 -0
  19. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  20. package/dist/types/src/components/Avatars/Avatar.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/Avatars/AvatarGroup.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  23. package/dist/types/src/components/Breadcrumb/Breadcrumb.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Button/Button.stories.d.ts +1 -1
  25. package/dist/types/src/components/Button/Button.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/Button/IconButton.d.ts +1 -0
  27. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  28. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Button/Toggle.stories.d.ts.map +1 -1
  30. package/dist/types/src/components/Button/ToggleGroup.d.ts +2 -2
  31. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts +2 -2
  32. package/dist/types/src/components/Button/ToggleGroup.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/Card/Card.d.ts +13 -16
  34. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  35. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -1
  37. package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -1
  38. package/dist/types/src/components/Clipboard/index.d.ts +1 -1
  39. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  40. package/dist/types/src/components/DensityProvider/DensityProvider.d.ts.map +1 -1
  41. package/dist/types/src/components/Dialog/AlertDialog.d.ts +17 -17
  42. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  43. package/dist/types/src/components/Dialog/AlertDialog.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/Dialog/Dialog.d.ts +16 -16
  45. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  46. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/ElevationProvider/ElevationProvider.d.ts.map +1 -1
  48. package/dist/types/src/components/ErrorFallback/ErrorFallback.d.ts.map +1 -1
  49. package/dist/types/src/components/ErrorFallback/ErrorFallback.stories.d.ts.map +1 -1
  50. package/dist/types/src/components/ErrorFallback/ErrorStack.d.ts.map +1 -1
  51. package/dist/types/src/components/ErrorFallback/ThrowError.d.ts.map +1 -1
  52. package/dist/types/src/components/Focus/Focus.d.ts +2 -2
  53. package/dist/types/src/components/Focus/Focus.stories.d.ts.map +1 -1
  54. package/dist/types/src/components/Icon/Icon.d.ts +1 -0
  55. package/dist/types/src/components/Icon/Icon.d.ts.map +1 -1
  56. package/dist/types/src/components/Icon/Icon.stories.d.ts +1 -1
  57. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/Image/Image.d.ts.map +1 -1
  59. package/dist/types/src/components/Image/Image.stories.d.ts +2 -2
  60. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -1
  61. package/dist/types/src/components/Input/Input.d.ts +12 -15
  62. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  63. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  64. package/dist/types/src/components/Link/Link.stories.d.ts.map +1 -1
  65. package/dist/types/src/components/List/List.d.ts +2 -2
  66. package/dist/types/src/components/List/List.stories.d.ts +1 -1
  67. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  68. package/dist/types/src/components/List/ListDropIndicator.d.ts.map +1 -1
  69. package/dist/types/src/components/List/Tree.d.ts +2 -2
  70. package/dist/types/src/components/List/Tree.d.ts.map +1 -1
  71. package/dist/types/src/components/List/Tree.stories.d.ts.map +1 -1
  72. package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +1 -1
  73. package/dist/types/src/components/List/Treegrid.d.ts +1 -1
  74. package/dist/types/src/components/List/Treegrid.d.ts.map +1 -1
  75. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/Main/Main.d.ts +7 -3
  77. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  78. package/dist/types/src/components/Main/Main.stories.d.ts.map +1 -1
  79. package/dist/types/src/components/Main/useSwipeToDismiss.d.ts.map +1 -1
  80. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
  81. package/dist/types/src/components/Menu/ContextMenu.stories.d.ts.map +1 -1
  82. package/dist/types/src/components/Menu/DropdownMenu.d.ts +11 -3
  83. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  84. package/dist/types/src/components/Menu/DropdownMenu.stories.d.ts.map +1 -1
  85. package/dist/types/src/components/Message/Message.d.ts +1 -1
  86. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  87. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  88. package/dist/types/src/components/Popover/Popover.d.ts +10 -2
  89. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  90. package/dist/types/src/components/Popover/Popover.stories.d.ts.map +1 -1
  91. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +2 -2
  92. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  93. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +2 -2
  94. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  95. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +11 -3
  96. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  97. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  98. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  99. package/dist/types/src/components/Select/Select.stories.d.ts.map +1 -1
  100. package/dist/types/src/components/Skeleton/Skeleton.stories.d.ts.map +1 -1
  101. package/dist/types/src/components/Splitter/Splitter.d.ts +3 -3
  102. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/Status/Status.stories.d.ts.map +1 -1
  104. package/dist/types/src/components/Tag/Tag.stories.d.ts.map +1 -1
  105. package/dist/types/src/components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  106. package/dist/types/src/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  107. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts +54 -55
  108. package/dist/types/src/components/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  109. package/dist/types/src/components/ThemeProvider/index.d.ts +1 -1
  110. package/dist/types/src/components/ThemeProvider/index.d.ts.map +1 -1
  111. package/dist/types/src/components/Toast/Toast.d.ts +4 -4
  112. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  113. package/dist/types/src/components/Toast/Toast.stories.d.ts.map +1 -1
  114. package/dist/types/src/components/Toolbar/Toolbar.d.ts +5 -5
  115. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  116. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  117. package/dist/types/src/components/Tooltip/Tooltip.d.ts +2 -2
  118. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  119. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  120. package/dist/types/src/exemplars/generics.stories.d.ts +1 -1
  121. package/dist/types/src/exemplars/generics.stories.d.ts.map +1 -1
  122. package/dist/types/src/exemplars/slot.stories.d.ts.map +1 -1
  123. package/dist/types/src/exemplars/tabster.stories.d.ts.map +1 -1
  124. package/dist/types/src/exemplars/virtualizer.stories.d.ts.map +1 -1
  125. package/dist/types/src/hooks/useDensityContext.d.ts.map +1 -1
  126. package/dist/types/src/hooks/useElevationContext.d.ts.map +1 -1
  127. package/dist/types/src/hooks/useIconHref.d.ts.map +1 -1
  128. package/dist/types/src/hooks/useSafeArea.d.ts.map +1 -1
  129. package/dist/types/src/hooks/useSafeCollisionPadding.d.ts.map +1 -1
  130. package/dist/types/src/hooks/useVisualViewport.d.ts.map +1 -1
  131. package/dist/types/src/playground/Controls.stories.d.ts.map +1 -1
  132. package/dist/types/src/playground/Custom.stories.d.ts +1 -1
  133. package/dist/types/src/playground/Custom.stories.d.ts.map +1 -1
  134. package/dist/types/src/playground/Typography.stories.d.ts.map +1 -1
  135. package/dist/types/src/primitives/Column/Column.d.ts +4 -4
  136. package/dist/types/src/primitives/Column/Column.d.ts.map +1 -1
  137. package/dist/types/src/primitives/Column/Column.stories.d.ts.map +1 -1
  138. package/dist/types/src/primitives/Container/Container.d.ts +1 -1
  139. package/dist/types/src/primitives/Container/Container.stories.d.ts.map +1 -1
  140. package/dist/types/src/primitives/Flex/Flex.d.ts +1 -1
  141. package/dist/types/src/primitives/Flex/Flex.stories.d.ts.map +1 -1
  142. package/dist/types/src/primitives/Grid/Grid.d.ts +1 -1
  143. package/dist/types/src/primitives/Grid/Grid.stories.d.ts.map +1 -1
  144. package/dist/types/src/primitives/Panel/Panel.d.ts +4 -4
  145. package/dist/types/src/primitives/Panel/Panel.d.ts.map +1 -1
  146. package/dist/types/src/primitives/Panel/Panel.stories.d.ts.map +1 -1
  147. package/dist/types/src/testing/Loading.d.ts.map +1 -1
  148. package/dist/types/src/testing/decorators/withLayout.d.ts.map +1 -1
  149. package/dist/types/src/testing/decorators/withLayoutVariants.d.ts.map +1 -1
  150. package/dist/types/src/testing/decorators/withTheme.d.ts.map +1 -1
  151. package/dist/types/src/translations.d.ts +3 -3
  152. package/dist/types/src/translations.d.ts.map +1 -1
  153. package/dist/types/src/util/usePx.d.ts.map +1 -1
  154. package/dist/types/tsconfig.tsbuildinfo +1 -1
  155. package/package.json +26 -17
  156. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  157. package/src/components/Button/IconButton.stories.tsx +1 -1
  158. package/src/components/Button/IconButton.tsx +3 -2
  159. package/src/components/Card/Card.stories.tsx +3 -3
  160. package/src/components/Card/Card.tsx +25 -16
  161. package/src/components/Clipboard/CopyButton.tsx +2 -2
  162. package/src/components/Icon/Icon.tsx +10 -3
  163. package/src/components/Image/Image.tsx +15 -5
  164. package/src/components/List/List.stories.tsx +1 -1
  165. package/src/components/List/List.tsx +1 -1
  166. package/src/components/List/ListDropIndicator.tsx +0 -1
  167. package/src/components/List/Tree.stories.tsx +1 -1
  168. package/src/components/Message/Message.stories.tsx +1 -1
  169. package/src/components/Message/Message.tsx +24 -7
  170. package/src/components/ScrollArea/ScrollArea.stories.tsx +1 -5
  171. package/src/components/ScrollContainer/ScrollContainer.tsx +1 -3
  172. package/src/components/ThemeProvider/index.ts +1 -1
  173. package/src/components/Toolbar/Toolbar.tsx +2 -1
  174. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  175. package/src/exemplars/slot.stories.tsx +2 -4
  176. package/src/exemplars/virtualizer.stories.tsx +0 -1
  177. package/src/testing/decorators/withLayout.tsx +6 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui",
3
- "version": "0.8.4-main.422d1c7879",
3
+ "version": "0.8.4-main.4f23b4e393",
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",
@@ -12,6 +12,9 @@
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": false,
14
14
  "type": "module",
15
+ "imports": {
16
+ "#translations": "./src/translations.ts"
17
+ },
15
18
  "exports": {
16
19
  ".": {
17
20
  "source": "./src/index.ts",
@@ -24,6 +27,12 @@
24
27
  "browser": "./dist/lib/browser/testing/index.mjs",
25
28
  "node": "./dist/lib/node-esm/testing/index.mjs",
26
29
  "types": "./dist/types/src/testing/index.d.ts"
30
+ },
31
+ "./translations": {
32
+ "source": "./src/translations.ts",
33
+ "types": "./dist/types/src/translations.d.ts",
34
+ "browser": "./dist/lib/browser/translations.mjs",
35
+ "node": "./dist/lib/node-esm/translations.mjs"
27
36
  }
28
37
  },
29
38
  "types": "dist/types/src/index.d.ts",
@@ -74,17 +83,17 @@
74
83
  "react-error-boundary": "^4.0.13",
75
84
  "react-i18next": "^11.18.6",
76
85
  "react-remove-scroll": "^2.6.0",
77
- "@dxos/invariant": "0.8.4-main.422d1c7879",
78
- "@dxos/lit-ui": "0.8.4-main.422d1c7879",
79
- "@dxos/log": "0.8.4-main.422d1c7879",
80
- "@dxos/react-error-boundary": "0.8.4-main.422d1c7879",
81
- "@dxos/debug": "0.8.4-main.422d1c7879",
82
- "@dxos/react-hooks": "0.8.4-main.422d1c7879",
83
- "@dxos/react-list": "0.8.4-main.422d1c7879",
84
- "@dxos/react-input": "0.8.4-main.422d1c7879",
85
- "@dxos/async": "0.8.4-main.422d1c7879",
86
- "@dxos/ui-types": "0.8.4-main.422d1c7879",
87
- "@dxos/util": "0.8.4-main.422d1c7879"
86
+ "@dxos/async": "0.8.4-main.4f23b4e393",
87
+ "@dxos/invariant": "0.8.4-main.4f23b4e393",
88
+ "@dxos/lit-ui": "0.8.4-main.4f23b4e393",
89
+ "@dxos/log": "0.8.4-main.4f23b4e393",
90
+ "@dxos/debug": "0.8.4-main.4f23b4e393",
91
+ "@dxos/react-error-boundary": "0.8.4-main.4f23b4e393",
92
+ "@dxos/react-hooks": "0.8.4-main.4f23b4e393",
93
+ "@dxos/react-input": "0.8.4-main.4f23b4e393",
94
+ "@dxos/ui-types": "0.8.4-main.4f23b4e393",
95
+ "@dxos/util": "0.8.4-main.4f23b4e393",
96
+ "@dxos/react-list": "0.8.4-main.4f23b4e393"
88
97
  },
89
98
  "devDependencies": {
90
99
  "@dnd-kit/core": "^6.0.5",
@@ -97,15 +106,15 @@
97
106
  "react": "~19.2.3",
98
107
  "react-dom": "~19.2.3",
99
108
  "tabster": "^8.5.5",
100
- "vite": "^7.1.11",
101
- "@dxos/ui-theme": "0.8.4-main.422d1c7879",
102
- "@dxos/util": "0.8.4-main.422d1c7879",
103
- "@dxos/random": "0.8.4-main.422d1c7879"
109
+ "vite": "^8.0.10",
110
+ "@dxos/random": "0.8.4-main.4f23b4e393",
111
+ "@dxos/util": "0.8.4-main.4f23b4e393",
112
+ "@dxos/ui-theme": "0.8.4-main.4f23b4e393"
104
113
  },
105
114
  "peerDependencies": {
106
115
  "react": "~19.2.3",
107
116
  "react-dom": "~19.2.3",
108
- "@dxos/ui-theme": "0.8.4-main.422d1c7879"
117
+ "@dxos/ui-theme": "0.8.4-main.4f23b4e393"
109
118
  },
110
119
  "publishConfig": {
111
120
  "access": "public"
@@ -15,7 +15,7 @@ const DefaultStory = (props: BreadcrumbRootProps) => {
15
15
  <Breadcrumb.List>
16
16
  <Breadcrumb.ListItem>
17
17
  <Breadcrumb.Link asChild>
18
- <Button variant='ghost' classNames='px-0 text-base-surface-text font-normal'>
18
+ <Button variant='ghost' classNames='px-0 text-base-foreground font-normal'>
19
19
  Grocery
20
20
  </Button>
21
21
  </Breadcrumb.Link>
@@ -13,7 +13,7 @@ import { IconButton, type IconButtonProps } from './IconButton';
13
13
  const DefaultStory = (props: IconButtonProps) => {
14
14
  return (
15
15
  <Tooltip.Provider>
16
- <div role='none' className='flex gap-4'>
16
+ <div className='flex gap-4'>
17
17
  <IconButton {...props} />
18
18
  <IconButton iconOnly {...props} />
19
19
  <Button>{props.label}</Button>
@@ -16,6 +16,7 @@ type IconButtonProps = Omit<ButtonProps, 'children'> &
16
16
  noTooltip?: boolean;
17
17
  caretDown?: boolean;
18
18
  iconOnly?: boolean;
19
+ square?: boolean; // TODO(burdon): Handle more uniformly.
19
20
  iconEnd?: boolean;
20
21
  iconClassNames?: ThemedClassName<any>['classNames'];
21
22
  tooltipSide?: TooltipSide;
@@ -45,12 +46,12 @@ const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
45
46
 
46
47
  const LabelledIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
47
48
  (
48
- { size, icon, iconOnly, iconEnd, iconClassNames, label, caretDown, noTooltip: _, classNames, ...props },
49
+ { size, icon, iconOnly, square, iconEnd, iconClassNames, label, caretDown, noTooltip: _, classNames, ...props },
49
50
  forwardedRef,
50
51
  ) => {
51
52
  const { tx } = useThemeContext();
52
53
  return (
53
- <Button {...props} classNames={tx('iconButton.root', { iconOnly }, classNames)} ref={forwardedRef}>
54
+ <Button {...props} classNames={tx('iconButton.root', { iconOnly, square }, classNames)} ref={forwardedRef}>
54
55
  {icon && !iconEnd && <Icon icon={icon} size={size} classNames={iconClassNames} />}
55
56
  <span className={iconOnly ? 'sr-only' : undefined}>{label}</span>
56
57
  {icon && iconEnd && <Icon icon={icon} size={size} classNames={iconClassNames} />}
@@ -129,18 +129,18 @@ export const Description: Story = {
129
129
  export const Mock = () => (
130
130
  <div className='grid grid-cols-[2rem_1fr_2rem] w-full dx-card-min-width dx-card-max-width border border-separator rounded-xs'>
131
131
  <div className='grid grid-cols-subgrid col-span-full'>
132
- <div role='none' className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
132
+ <div className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
133
133
  <Icon icon='ph--dots-six-vertical--regular' />
134
134
  </div>
135
135
  <div className='p-1 whitespace-normal break-words text-description items-center'>
136
136
  This line is very very long and it should wrap.
137
137
  </div>
138
- <div role='none' className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
138
+ <div className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
139
139
  <Icon icon='ph--x--regular' />
140
140
  </div>
141
141
  </div>
142
142
  <div className='grid grid-cols-subgrid col-span-3'>
143
- <div role='none' className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
143
+ <div className='grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center'>
144
144
  <Icon icon='ph--dots-six-vertical--regular' />
145
145
  </div>
146
146
  <div className='p-1 text-description items-center col-span-2'>
@@ -52,7 +52,7 @@ const CardContext = createContext<CardContextValue>({});
52
52
 
53
53
  const CARD_ROOT_NAME = 'Card.Root';
54
54
 
55
- type CardRootOwnProps = {
55
+ type CardRootProps = {
56
56
  id?: string;
57
57
  border?: boolean;
58
58
  fullWidth?: boolean;
@@ -64,24 +64,33 @@ type CardRootOwnProps = {
64
64
  'data-testid'?: string;
65
65
  };
66
66
 
67
- type CardRootProps = CardRootOwnProps;
68
-
69
- const CardRoot = slottable<HTMLDivElement, CardRootOwnProps>(
70
- ({ children, id, asChild, role, border = true, fullWidth, density, ...props }, forwardedRef) => {
67
+ /**
68
+ * `Card.Root` does not support `asChild`. The Column grid is the root element
69
+ * (one `<div>` carrying both the `dx-card` and `dx-column-root` classes
70
+ * instead of the previous outer-card + inner-column pair), so caller-provided
71
+ * HTML attributes — `onClick`, `tabIndex`, `style`, `data-*`, `grid-template-rows`
72
+ * overrides via `classNames` — land directly on the grid container.
73
+ * Slot-parents (`Focus.Item asChild`, `Mosaic.Tile asChild`, etc.) continue to
74
+ * work because `composable()` preserves the COMPOSABLE marker that slottable parents
75
+ * check before warning, and Radix `Slot` merges the parent's props onto the inner
76
+ * `<div>` exactly the way `slottable`'s `Slot`/`Primitive.div` branch did.
77
+ */
78
+ const CardRoot = composable<HTMLDivElement, CardRootProps>(
79
+ ({ children, id, role, border = true, fullWidth, density, ...props }, forwardedRef) => {
71
80
  const { className, ...rest } = composableProps(props);
72
- const Comp = asChild ? Slot : Primitive.div;
73
81
  const { tx } = useThemeContext();
74
82
 
75
83
  return (
76
- <Comp
77
- {...rest}
78
- {...(id && { 'data-object-id': id })}
84
+ <Column.Root
85
+ asChild
86
+ gutter={density === 'coarse' ? 'lg' : 'md'}
87
+ classNames={tx('card.root', { border, fullWidth }, className)}
79
88
  role={role ?? 'group'}
80
- className={tx('card.root', { border, fullWidth }, className)}
81
- ref={forwardedRef}
82
89
  >
83
- <Column.Root gutter={density === 'coarse' ? 'lg' : 'md'}>{children}</Column.Root>
84
- </Comp>
90
+ <div {...rest} {...(id && { 'data-object-id': id })} ref={forwardedRef}>
91
+ {children}
92
+ </div>
93
+ </Column.Root>
85
94
  );
86
95
  },
87
96
  );
@@ -194,7 +203,7 @@ const CardIconBlock = forwardRef<HTMLDivElement, ThemedClassName<PropsWithChildr
194
203
  const { tx } = useThemeContext();
195
204
 
196
205
  return (
197
- <div {...props} role='none' className={tx('card.icon-block', { padding }, classNames)} ref={forwardedRef}>
206
+ <div {...props} className={tx('card.icon-block', { padding }, classNames)} ref={forwardedRef}>
198
207
  {children}
199
208
  </div>
200
209
  );
@@ -251,6 +260,7 @@ const CARD_ROW_NAME = 'Card.Row';
251
260
 
252
261
  type CardRowProps = { icon?: string; fullWidth?: boolean };
253
262
 
263
+ // TODO(burdon): fullWidth should mean no columns.
254
264
  const CardRow = slottable<HTMLDivElement, CardRowProps>(({ children, asChild, icon, ...props }, forwardedRef) => {
255
265
  const { className, ...rest } = composableProps(props);
256
266
  const Comp = asChild ? Slot : Primitive.div;
@@ -363,7 +373,6 @@ const CardHtml = ({ html, variant = 'default', ...props }: CardHtmlProps & Theme
363
373
  return (
364
374
  <div
365
375
  {...props}
366
- role='none'
367
376
  className={tx('card.text', { variant })}
368
377
  // eslint-disable-next-line react/no-danger
369
378
  dangerouslySetInnerHTML={{ __html: sanitized }}
@@ -399,7 +408,7 @@ const CardPoster = (props: CardPosterProps) => {
399
408
 
400
409
  if (props.image) {
401
410
  return (
402
- <div role='none' className='col-span-full'>
411
+ <div className='col-span-full'>
403
412
  <Image
404
413
  classNames={[tx('card.poster', {}), aspect, props.classNames]}
405
414
  src={props.image}
@@ -30,11 +30,11 @@ export const CopyButton = ({ classNames, value, size = 5, ...props }: CopyButton
30
30
  onClick={() => setTextValue(value)}
31
31
  data-testid='copy-invitation'
32
32
  >
33
- <div role='none' className={mx('flex gap-1 items-center', isCopied && inactiveLabelStyles)}>
33
+ <div className={mx('flex gap-1 items-center', isCopied && inactiveLabelStyles)}>
34
34
  <span className='px-1'>{t('copy.label')}</span>
35
35
  <Icon icon='ph--copy--regular' size={size} />
36
36
  </div>
37
- <div role='none' className={mx('flex gap-1 items-center', !isCopied && inactiveLabelStyles)}>
37
+ <div className={mx('flex gap-1 items-center', !isCopied && inactiveLabelStyles)}>
38
38
  <span className='px-1'>{t('copy-success.label')}</span>
39
39
  <Icon icon='ph--check--regular' size={size} />
40
40
  </div>
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { type Primitive } from '@radix-ui/react-primitive';
6
- import React, { type ComponentPropsWithRef, forwardRef, memo } from 'react';
6
+ import React, { type ComponentPropsWithRef, forwardRef, memo, useMemo } from 'react';
7
7
 
8
8
  import { type Size } from '@dxos/ui-types';
9
9
 
@@ -13,18 +13,25 @@ import { type ThemedClassName } from '../../util';
13
13
  export type IconProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.svg>> & {
14
14
  icon: string;
15
15
  size?: Size;
16
+ synchronized?: boolean;
16
17
  };
17
18
 
18
19
  /**
19
20
  * The Icon's size can be set directly or inherited from the `--dx-icon-size` CSS variable.
20
21
  */
21
22
  export const Icon = memo(
22
- forwardRef<SVGSVGElement, IconProps>(({ icon, classNames, size, ...props }, forwardedRef) => {
23
+ forwardRef<SVGSVGElement, IconProps>(({ classNames, icon, size, synchronized, style, ...props }, forwardedRef) => {
23
24
  const { tx } = useThemeContext();
25
+ const spinDelay = useMemo(() => (synchronized ? `${-(Date.now() % 1_000)}ms` : undefined), [synchronized]);
24
26
  const href = useIconHref(icon);
25
27
 
26
28
  return (
27
- <svg {...props} className={tx('icon.root', { size }, classNames)} ref={forwardedRef}>
29
+ <svg
30
+ {...props}
31
+ style={{ ...style, animationDelay: spinDelay }}
32
+ className={tx('icon.root', { size }, classNames)}
33
+ ref={forwardedRef}
34
+ >
28
35
  <use href={href} />
29
36
  </svg>
30
37
  );
@@ -175,7 +175,9 @@ const extractDominantColor = (
175
175
  const alpha = pixels[i + 3];
176
176
 
177
177
  // Skip transparent pixels.
178
- if (alpha === 0) continue;
178
+ if (alpha === 0) {
179
+ continue;
180
+ }
179
181
 
180
182
  // Calculate saturation to weight vibrant colors more.
181
183
  const max = Math.max(red, green, blue);
@@ -215,21 +217,29 @@ const isTransparent = (pixels: Uint8ClampedArray, sampleSize: number, threshold:
215
217
  for (let x = 0; x < sampleSize; x++) {
216
218
  // Top edge.
217
219
  const topIndex = x * 4;
218
- if (pixels[topIndex + 3] === 0) edgeTransparentPixels++;
220
+ if (pixels[topIndex + 3] === 0) {
221
+ edgeTransparentPixels++;
222
+ }
219
223
 
220
224
  // Bottom edge.
221
225
  const bottomIndex = ((sampleSize - 1) * sampleSize + x) * 4;
222
- if (pixels[bottomIndex + 3] === 0) edgeTransparentPixels++;
226
+ if (pixels[bottomIndex + 3] === 0) {
227
+ edgeTransparentPixels++;
228
+ }
223
229
  }
224
230
 
225
231
  for (let y = 1; y < sampleSize - 1; y++) {
226
232
  // Left edge.
227
233
  const leftIndex = y * sampleSize * 4;
228
- if (pixels[leftIndex + 3] === 0) edgeTransparentPixels++;
234
+ if (pixels[leftIndex + 3] === 0) {
235
+ edgeTransparentPixels++;
236
+ }
229
237
 
230
238
  // Right edge.
231
239
  const rightIndex = (y * sampleSize + sampleSize - 1) * 4;
232
- if (pixels[rightIndex + 3] === 0) edgeTransparentPixels++;
240
+ if (pixels[rightIndex + 3] === 0) {
241
+ edgeTransparentPixels++;
242
+ }
233
243
  }
234
244
 
235
245
  return edgeTransparentPixels / edgePixels > threshold;
@@ -176,7 +176,7 @@ export const Collapsible: Story = {
176
176
  <List {...args}>
177
177
  {items.map(({ id, text, body }, index) => (
178
178
  <ListItem.Root key={id} id={id} collapsible={index !== 2} defaultOpen={index % 2 === 0}>
179
- <div role='none' className='grow flex'>
179
+ <div className='grow flex'>
180
180
  {index !== 2 ? <ListItem.OpenTrigger /> : <ListItem.MockOpenTrigger />}
181
181
  <ListItem.Heading classNames='grow pt-2'>{text}</ListItem.Heading>
182
182
  <ListItem.Endcap>
@@ -75,7 +75,7 @@ const MockListItemOpenTrigger = ({
75
75
  }: ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'children'>>) => {
76
76
  const density = useDensityContext();
77
77
  const { tx } = useThemeContext();
78
- return <div role='none' {...props} className={tx('list.item.openTrigger', { density }, classNames)} />;
78
+ return <div {...props} className={tx('list.item.openTrigger', { density }, classNames)} />;
79
79
  };
80
80
 
81
81
  type ListItemHeadingProps = ThemedClassName<ListPrimitiveItemHeadingProps>;
@@ -52,7 +52,6 @@ export const ListDropIndicator = ({
52
52
 
53
53
  return (
54
54
  <div
55
- role='none'
56
55
  style={
57
56
  {
58
57
  '--line-thickness': `${strokeSize}px`,
@@ -32,7 +32,7 @@ const StorybookTreeItem = ({ data, prefix }: StorybookTreeItemProps) => {
32
32
 
33
33
  return (
34
34
  <TreeItem.Root key={id} id={id} collapsible={!valueIsScalar} defaultOpen>
35
- <div role='none' className='grow flex'>
35
+ <div className='grow flex'>
36
36
  {valueIsScalar ? <TreeItem.MockOpenTrigger /> : <TreeItem.OpenTrigger />}
37
37
  <TreeItem.Heading classNames='grow pt-1'>{valueIsScalar ? String(value) : key}</TreeItem.Heading>
38
38
  </div>
@@ -22,7 +22,7 @@ type DefaultStoryProps = {
22
22
  const DefaultStory = ({ valence, title, body }: DefaultStoryProps) => (
23
23
  <div className='w-[30rem]'>
24
24
  <Message.Root valence={valence}>
25
- {title && <Message.Title>{title}</Message.Title>}
25
+ {title && <Message.Title onClose={() => console.log('close')}>{title}</Message.Title>}
26
26
  {body && <Message.Content>{body}</Message.Content>}
27
27
  </Message.Root>
28
28
  </div>
@@ -6,12 +6,16 @@ import { createContext } from '@radix-ui/react-context';
6
6
  import { Primitive } from '@radix-ui/react-primitive';
7
7
  import { Slot } from '@radix-ui/react-slot';
8
8
  import React, { type ComponentPropsWithRef, forwardRef } from 'react';
9
+ import { useTranslation } from 'react-i18next';
9
10
 
10
11
  import { useId } from '@dxos/react-hooks';
11
12
  import { type Elevation, type MessageValence } from '@dxos/ui-types';
12
13
 
14
+ import { translationKey } from '#translations';
15
+
13
16
  import { useElevationContext, useThemeContext } from '../../hooks';
14
17
  import { type ThemedClassName } from '../../util';
18
+ import { IconButton } from '../Button';
15
19
  import { Icon } from '../Icon';
16
20
 
17
21
  const messageIcons: Record<MessageValence, string> = {
@@ -84,23 +88,36 @@ MessageRoot.displayName = MESSAGE_NAME;
84
88
  //
85
89
 
86
90
  type MessageTitleProps = Omit<ThemedClassName<ComponentPropsWithRef<typeof Primitive.h2>>, 'id'> & {
87
- asChild?: boolean;
88
91
  icon?: string;
92
+ onClose?: () => void;
89
93
  };
90
94
 
91
95
  const MESSAGE_TITLE_NAME = 'MessageTitle';
92
96
 
93
97
  const MessageTitle = forwardRef<HTMLHeadingElement, MessageTitleProps>(
94
- ({ asChild, classNames, children, icon: iconProp, ...props }, forwardedRef) => {
98
+ ({ classNames, children, icon: iconProp, onClose }, forwardedRef) => {
99
+ const { t } = useTranslation(translationKey);
95
100
  const { tx } = useThemeContext();
96
101
  const { titleId, valence } = useMessageContext(MESSAGE_TITLE_NAME);
97
- const Comp = asChild ? Slot : Primitive.h2;
98
102
  const icon = iconProp ?? messageIcons[valence];
99
103
  return (
100
- <Comp {...props} className={tx('message.header', {}, classNames)} id={titleId} ref={forwardedRef}>
101
- {!icon && valence === 'neutral' ? <div /> : <Icon icon={icon} classNames={tx('message.icon', { valence })} />}
102
- <span className={tx('message.title', {}, classNames)}>{children}</span>
103
- </Comp>
104
+ <div className={tx('message.header', {}, classNames)} id={titleId} ref={forwardedRef}>
105
+ {icon && (
106
+ <div className={tx('message.icon', { valence })}>
107
+ <Icon icon={icon} />
108
+ </div>
109
+ )}
110
+ <h2 className={tx('message.title', {}, classNames)}>{children}</h2>
111
+ {onClose && (
112
+ <IconButton
113
+ variant='ghost'
114
+ icon='ph--x--regular'
115
+ iconOnly
116
+ label={t('toolbar-close.label')}
117
+ onClick={onClose}
118
+ />
119
+ )}
120
+ </div>
104
121
  );
105
122
  },
106
123
  );
@@ -48,11 +48,7 @@ const Row = ({ items = 50 }: { items?: number }) => (
48
48
  );
49
49
 
50
50
  const Container = ({ classNames, children }: ThemedClassName<PropsWithChildren>) => {
51
- return (
52
- <div role='none' className={mx('border border-separator rounded-md overflow-hidden', classNames)}>
53
- {children}
54
- </div>
55
- );
51
+ return <div className={mx('border border-separator rounded-md overflow-hidden', classNames)}>{children}</div>;
56
52
  };
57
53
 
58
54
  export const Vertical = {
@@ -276,13 +276,12 @@ const Fade = () => {
276
276
 
277
277
  return (
278
278
  <div
279
- role='none'
280
279
  data-visible={overflow}
281
280
  className={mx(
282
281
  // NOTE: Gradients may not be visible with dark reader extensions.
283
282
  'z-10 absolute top-0 inset-x-0 h-24 w-full',
284
283
  'opacity-0 duration-200 transition-opacity data-[visible="true"]:opacity-100',
285
- 'bg-gradient-to-b from-(--surface-bg) to-transparent pointer-events-none',
284
+ 'bg-gradient-to-b from-(--color-base-surface) to-transparent pointer-events-none',
286
285
  )}
287
286
  />
288
287
  );
@@ -303,7 +302,6 @@ const ScrollDownButton = ({ classNames }: ScrollDownButtonProps) => {
303
302
 
304
303
  return (
305
304
  <div
306
- role='none'
307
305
  className={mx(
308
306
  'absolute bottom-2 right-4 opacity-100 transition-opacity duration-300',
309
307
  pinned && 'opacity-0',
@@ -2,7 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- export { type Label, isLabel, toLocalizedString } from '@dxos/ui-types';
5
+ export { type Label, isLabel, toLocalizedString } from '@dxos/ui-types/translations';
6
6
 
7
7
  export * from './ThemeProvider';
8
8
  export { useTranslation } from './TranslationsProvider';
@@ -12,8 +12,9 @@ import { useTranslation } from 'react-i18next';
12
12
  import { composable, composableProps, slottable, type ToolbarStyleProps } from '@dxos/ui-theme';
13
13
  import { type SlottableProps } from '@dxos/ui-types';
14
14
 
15
+ import { translationKey } from '#translations';
16
+
15
17
  import { useThemeContext } from '../../hooks';
16
- import { translationKey } from '../../translations';
17
18
  import {
18
19
  Button,
19
20
  ButtonGroup,
@@ -19,7 +19,7 @@ type DefaultStoryProps = {
19
19
  const DefaultStory = ({ tooltips, defaultOpen }: DefaultStoryProps) => {
20
20
  return (
21
21
  <Tooltip.Provider defaultOpen={defaultOpen}>
22
- <div role='none' className='w-32'>
22
+ <div className='w-32'>
23
23
  {tooltips.map(({ label, content }, i) => (
24
24
  <Tooltip.Trigger asChild key={i} content={content} side='right'>
25
25
  <Button classNames='block w-full'>{label}</Button>
@@ -59,9 +59,7 @@ const Leaf = composable<HTMLButtonElement>(({ children, ...props }, forwardedRef
59
59
 
60
60
  /** This isn't a valid child for a `slottable` component. */
61
61
  const Simple = ({ children, classNames }: ThemedClassName<PropsWithChildren>) => (
62
- <div role='none' className={mx(classNames)}>
63
- {children}
64
- </div>
62
+ <div className={mx(classNames)}>{children}</div>
65
63
  );
66
64
 
67
65
  const meta = {
@@ -99,7 +97,7 @@ export const Inner: Story = {
99
97
  <Outer asChild role='article' classNames='border-orange-500'>
100
98
  <Middle asChild>
101
99
  <Leaf>
102
- <div role='none'>Leaf</div>
100
+ <div>Leaf</div>
103
101
  </Leaf>
104
102
  </Middle>
105
103
  </Outer>
@@ -66,7 +66,6 @@ export const Default = {
66
66
  <ScrollArea.Root orientation='vertical' centered>
67
67
  <ScrollArea.Viewport classNames='p-2' ref={setViewport}>
68
68
  <div
69
- role='none'
70
69
  style={{
71
70
  position: 'relative',
72
71
  height: virtualizer.getTotalSize(),
@@ -47,31 +47,21 @@ export const withLayout =
47
47
  };
48
48
 
49
49
  const layouts: Record<ContainerType, FC<ContainerProps>> = {
50
- default: ({ classNames, children }: ContainerProps) => (
51
- <div role='none' className={mx('p-4', classNames)}>
52
- {children}
53
- </div>
54
- ),
50
+ default: ({ classNames, children }: ContainerProps) => <div className={mx('p-4', classNames)}>{children}</div>,
55
51
 
56
52
  fullscreen: ({ classNames, children }: ContainerProps) => (
57
- <div role='none' className={mx('fixed inset-0 flex overflow-hidden bg-black', classNames)}>
58
- {children}
59
- </div>
53
+ <div className={mx('fixed inset-0 flex overflow-hidden bg-black', classNames)}>{children}</div>
60
54
  ),
61
55
 
62
56
  centered: ({ classNames, children }: ContainerProps) => (
63
- <div role='none' className={mx('fixed inset-0 grid overflow-hidden place-items-center bg-black')}>
64
- <div role='none' className={mx('flex flex-col bg-base-surface', classNames)}>
65
- {children}
66
- </div>
57
+ <div className={mx('fixed inset-0 grid overflow-hidden place-items-center bg-black')}>
58
+ <div className={mx('flex flex-col bg-base-surface', classNames)}>{children}</div>
67
59
  </div>
68
60
  ),
69
61
 
70
62
  column: ({ classNames, children }: ContainerProps) => (
71
- <div role='none' className='fixed inset-0 flex overflow-hidden justify-center bg-black'>
72
- <div role='none' className={mx('flex flex-col w-[40rem] bg-base-surface', classNames)}>
73
- {children}
74
- </div>
63
+ <div className='fixed inset-0 flex overflow-hidden justify-center bg-black'>
64
+ <div className={mx('flex flex-col w-[40rem] bg-base-surface', classNames)}>{children}</div>
75
65
  </div>
76
66
  ),
77
67
  };