@dxos/react-ui 0.9.0 → 0.9.1-staging.ee54ba693a

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 (263) hide show
  1. package/dist/lib/browser/{chunk-5SPBSIWS.mjs → chunk-CMHHVHX3.mjs} +14 -1
  2. package/dist/lib/browser/chunk-CMHHVHX3.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-7JFD5ZHZ.mjs → chunk-GTHV4WYK.mjs} +141 -254
  4. package/dist/lib/browser/chunk-GTHV4WYK.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1553 -1274
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +5 -5
  9. package/dist/lib/browser/testing/index.mjs.map +2 -2
  10. package/dist/lib/browser/translations.mjs +1 -1
  11. package/dist/lib/node-esm/{chunk-TTEL2FP2.mjs → chunk-3VSKWNCQ.mjs} +141 -254
  12. package/dist/lib/node-esm/chunk-3VSKWNCQ.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-FPVTVXND.mjs → chunk-P4KFQGJI.mjs} +14 -1
  14. package/dist/lib/node-esm/chunk-P4KFQGJI.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +1553 -1274
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +5 -5
  19. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  20. package/dist/lib/node-esm/translations.mjs +1 -1
  21. package/dist/types/src/components/Avatars/Avatar.d.ts +1 -1
  22. package/dist/types/src/components/Avatars/Avatar.d.ts.map +1 -1
  23. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts +3 -3
  24. package/dist/types/src/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
  25. package/dist/types/src/components/Button/Button.d.ts +4 -2
  26. package/dist/types/src/components/Button/Button.d.ts.map +1 -1
  27. package/dist/types/src/components/Button/IconButton.d.ts +0 -1
  28. package/dist/types/src/components/Button/IconButton.d.ts.map +1 -1
  29. package/dist/types/src/components/Button/IconButton.stories.d.ts +37 -0
  30. package/dist/types/src/components/Button/IconButton.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Button/MicButton.d.ts +24 -0
  32. package/dist/types/src/components/Button/MicButton.d.ts.map +1 -0
  33. package/dist/types/src/components/Button/MicButton.stories.d.ts +57 -0
  34. package/dist/types/src/components/Button/MicButton.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/Button/SystemIconButton.d.ts +33 -0
  36. package/dist/types/src/components/Button/SystemIconButton.d.ts.map +1 -0
  37. package/dist/types/src/components/Button/SystemIconButton.stories.d.ts +51 -0
  38. package/dist/types/src/components/Button/SystemIconButton.stories.d.ts.map +1 -0
  39. package/dist/types/src/components/Button/ToggleGroup.d.ts +2 -2
  40. package/dist/types/src/components/Button/ToggleGroup.d.ts.map +1 -1
  41. package/dist/types/src/components/Button/ToggleIconButton.d.ts +15 -0
  42. package/dist/types/src/components/Button/ToggleIconButton.d.ts.map +1 -0
  43. package/dist/types/src/components/Button/index.d.ts +3 -0
  44. package/dist/types/src/components/Button/index.d.ts.map +1 -1
  45. package/dist/types/src/components/Calendar/Calendar.d.ts.map +1 -1
  46. package/dist/types/src/components/Calendar/Calendar.theme.d.ts.map +1 -1
  47. package/dist/types/src/components/Card/Card.d.ts +32 -26
  48. package/dist/types/src/components/Card/Card.d.ts.map +1 -1
  49. package/dist/types/src/components/Card/Card.stories.d.ts +3 -3
  50. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/Card/Card.theme.d.ts.map +1 -1
  52. package/dist/types/src/components/Carousel/Carousel.d.ts +29 -6
  53. package/dist/types/src/components/Carousel/Carousel.d.ts.map +1 -1
  54. package/dist/types/src/components/Carousel/Carousel.stories.d.ts +48 -2
  55. package/dist/types/src/components/Carousel/Carousel.stories.d.ts.map +1 -1
  56. package/dist/types/src/components/Clipboard/index.d.ts +1 -0
  57. package/dist/types/src/components/Clipboard/index.d.ts.map +1 -1
  58. package/dist/types/src/components/Column/Column.d.ts +20 -2
  59. package/dist/types/src/components/Column/Column.d.ts.map +1 -1
  60. package/dist/types/src/components/Column/Column.theme.d.ts +8 -0
  61. package/dist/types/src/components/Column/Column.theme.d.ts.map +1 -1
  62. package/dist/types/src/components/Dialog/AlertDialog.d.ts +2 -2
  63. package/dist/types/src/components/Dialog/AlertDialog.d.ts.map +1 -1
  64. package/dist/types/src/components/Dialog/Dialog.d.ts +1 -1
  65. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  66. package/dist/types/src/components/Dialog/Dialog.stories.d.ts +2 -2
  67. package/dist/types/src/components/Dialog/Dialog.stories.d.ts.map +1 -1
  68. package/dist/types/src/components/Icon/Icon.stories.d.ts +5 -0
  69. package/dist/types/src/components/Icon/Icon.stories.d.ts.map +1 -1
  70. package/dist/types/src/components/Input/Input.d.ts +4 -1
  71. package/dist/types/src/components/Input/Input.d.ts.map +1 -1
  72. package/dist/types/src/components/Input/Input.stories.d.ts +3 -3
  73. package/dist/types/src/components/Input/Input.stories.d.ts.map +1 -1
  74. package/dist/types/src/components/Input/Input.theme.d.ts +10 -10
  75. package/dist/types/src/components/Input/Input.theme.d.ts.map +1 -1
  76. package/dist/types/src/components/Input/SegmentedInput.d.ts +8 -8
  77. package/dist/types/src/components/Input/SegmentedInput.d.ts.map +1 -1
  78. package/dist/types/src/components/Input/index.d.ts +0 -1
  79. package/dist/types/src/components/Input/index.d.ts.map +1 -1
  80. package/dist/types/src/components/Main/Main.d.ts +3 -3
  81. package/dist/types/src/components/Main/Main.d.ts.map +1 -1
  82. package/dist/types/src/components/Menu/ContextMenu.d.ts +1 -1
  83. package/dist/types/src/components/Menu/ContextMenu.d.ts.map +1 -1
  84. package/dist/types/src/components/Menu/DropdownMenu.d.ts +2 -2
  85. package/dist/types/src/components/Menu/DropdownMenu.d.ts.map +1 -1
  86. package/dist/types/src/components/Message/Message.d.ts +1 -1
  87. package/dist/types/src/components/Message/Message.d.ts.map +1 -1
  88. package/dist/types/src/components/Message/Message.stories.d.ts +2 -2
  89. package/dist/types/src/components/Message/Message.stories.d.ts.map +1 -1
  90. package/dist/types/src/components/Message/Message.theme.d.ts.map +1 -1
  91. package/dist/types/src/components/Panel/Panel.d.ts +1 -1
  92. package/dist/types/src/components/Panel/Panel.d.ts.map +1 -1
  93. package/dist/types/src/components/Panel/Panel.theme.d.ts.map +1 -1
  94. package/dist/types/src/components/Popover/Popover.d.ts +2 -2
  95. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  96. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts +2 -0
  97. package/dist/types/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  98. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts +1 -0
  99. package/dist/types/src/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  100. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts +1 -1
  101. package/dist/types/src/components/ScrollContainer/ScrollContainer.d.ts.map +1 -1
  102. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts +2 -2
  103. package/dist/types/src/components/ScrollContainer/ScrollContainer.stories.d.ts.map +1 -1
  104. package/dist/types/src/components/Select/Select.d.ts +1 -1
  105. package/dist/types/src/components/Select/Select.d.ts.map +1 -1
  106. package/dist/types/src/components/Select/Select.stories.d.ts +2 -2
  107. package/dist/types/src/components/Select/Select.stories.d.ts.map +1 -1
  108. package/dist/types/src/components/Separator/Separator.d.ts.map +1 -1
  109. package/dist/types/src/components/Splitter/Splitter.d.ts +30 -16
  110. package/dist/types/src/components/Splitter/Splitter.d.ts.map +1 -1
  111. package/dist/types/src/components/Splitter/Splitter.stories.d.ts +6 -1
  112. package/dist/types/src/components/Splitter/Splitter.stories.d.ts.map +1 -1
  113. package/dist/types/src/components/Splitter/Splitter.theme.d.ts +3 -1
  114. package/dist/types/src/components/Splitter/Splitter.theme.d.ts.map +1 -1
  115. package/dist/types/src/components/Tag/Tag.d.ts +1 -1
  116. package/dist/types/src/components/Tag/Tag.d.ts.map +1 -1
  117. package/dist/types/src/components/Tag/Tag.theme.d.ts +1 -1
  118. package/dist/types/src/components/Tag/Tag.theme.d.ts.map +1 -1
  119. package/dist/types/src/components/Toast/Toast.d.ts +1 -1
  120. package/dist/types/src/components/Toast/Toast.d.ts.map +1 -1
  121. package/dist/types/src/components/Toast/Toast.theme.d.ts.map +1 -1
  122. package/dist/types/src/components/Toolbar/Toolbar.d.ts +1 -1
  123. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  124. package/dist/types/src/components/Tooltip/TextTooltip.d.ts +19 -0
  125. package/dist/types/src/components/Tooltip/TextTooltip.d.ts.map +1 -0
  126. package/dist/types/src/components/Tooltip/Tooltip.d.ts +3 -3
  127. package/dist/types/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  128. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts +2 -2
  129. package/dist/types/src/components/Tooltip/Tooltip.stories.d.ts.map +1 -1
  130. package/dist/types/src/components/Tooltip/index.d.ts +1 -0
  131. package/dist/types/src/components/Tooltip/index.d.ts.map +1 -1
  132. package/dist/types/src/components/index.d.ts +0 -1
  133. package/dist/types/src/components/index.d.ts.map +1 -1
  134. package/dist/types/src/index.d.ts +1 -1
  135. package/dist/types/src/index.d.ts.map +1 -1
  136. package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts +1 -8
  137. package/dist/types/src/primitives/ThemeProvider/TranslationsProvider.d.ts.map +1 -1
  138. package/dist/types/src/testing/Loading.d.ts.map +1 -1
  139. package/dist/types/src/theme/defaultTheme.d.ts.map +1 -1
  140. package/dist/types/src/theme/index.d.ts +0 -2
  141. package/dist/types/src/theme/index.d.ts.map +1 -1
  142. package/dist/types/src/translations.d.ts +13 -0
  143. package/dist/types/src/translations.d.ts.map +1 -1
  144. package/dist/types/src/util/slots.d.ts +1 -1
  145. package/dist/types/src/util/slots.d.ts.map +1 -1
  146. package/dist/types/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +22 -21
  148. package/src/components/Avatars/Avatar.stories.tsx +2 -2
  149. package/src/components/Avatars/Avatar.theme.ts +1 -1
  150. package/src/components/Avatars/Avatar.tsx +3 -3
  151. package/src/components/Breadcrumb/Breadcrumb.tsx +6 -6
  152. package/src/components/Button/Button.tsx +25 -4
  153. package/src/components/Button/IconButton.stories.tsx +81 -1
  154. package/src/components/Button/IconButton.tsx +2 -4
  155. package/src/components/Button/MicButton.stories.tsx +60 -0
  156. package/src/components/Button/MicButton.tsx +117 -0
  157. package/src/components/Button/SystemIconButton.stories.tsx +91 -0
  158. package/src/components/Button/SystemIconButton.tsx +264 -0
  159. package/src/components/Button/ToggleGroup.tsx +2 -2
  160. package/src/components/Button/ToggleIconButton.tsx +32 -0
  161. package/src/components/Button/index.ts +3 -0
  162. package/src/components/Calendar/Calendar.theme.ts +2 -0
  163. package/src/components/Calendar/Calendar.tsx +3 -3
  164. package/src/components/Card/Card.stories.tsx +71 -29
  165. package/src/components/Card/Card.theme.ts +27 -9
  166. package/src/components/Card/Card.tsx +176 -99
  167. package/src/components/Carousel/Carousel.stories.tsx +42 -18
  168. package/src/components/Carousel/Carousel.tsx +169 -33
  169. package/src/components/Column/Column.theme.ts +32 -4
  170. package/src/components/Column/Column.tsx +39 -7
  171. package/src/components/Dialog/AlertDialog.stories.tsx +2 -2
  172. package/src/components/Dialog/AlertDialog.tsx +13 -13
  173. package/src/components/Dialog/Dialog.stories.tsx +3 -4
  174. package/src/components/Dialog/Dialog.theme.ts +1 -1
  175. package/src/components/Dialog/Dialog.tsx +12 -12
  176. package/src/components/Icon/Icon.stories.tsx +23 -0
  177. package/src/components/Icon/Icon.theme.ts +1 -1
  178. package/src/components/Input/Input.stories.tsx +13 -5
  179. package/src/components/Input/Input.theme.ts +17 -39
  180. package/src/components/Input/Input.tsx +30 -13
  181. package/src/components/Input/SegmentedInput.tsx +50 -41
  182. package/src/components/Input/index.ts +0 -1
  183. package/src/components/Main/Main.tsx +3 -3
  184. package/src/components/MediaPlayer/MediaPlayer.tsx +4 -4
  185. package/src/components/Menu/ContextMenu.tsx +8 -8
  186. package/src/components/Menu/DropdownMenu.tsx +12 -13
  187. package/src/components/Message/Message.stories.tsx +2 -2
  188. package/src/components/Message/Message.theme.ts +1 -11
  189. package/src/components/Message/Message.tsx +6 -6
  190. package/src/components/Panel/Panel.theme.ts +2 -1
  191. package/src/components/Panel/Panel.tsx +1 -1
  192. package/src/components/Popover/Popover.theme.ts +1 -1
  193. package/src/components/Popover/Popover.tsx +9 -9
  194. package/src/components/ScrollArea/ScrollArea.tsx +7 -4
  195. package/src/components/ScrollContainer/ScrollContainer.stories.tsx +2 -2
  196. package/src/components/ScrollContainer/ScrollContainer.tsx +2 -2
  197. package/src/components/Select/Select.stories.tsx +2 -2
  198. package/src/components/Select/Select.theme.ts +1 -1
  199. package/src/components/Select/Select.tsx +14 -14
  200. package/src/components/Separator/Separator.tsx +1 -0
  201. package/src/components/Splitter/Splitter.stories.tsx +84 -20
  202. package/src/components/Splitter/Splitter.theme.ts +20 -3
  203. package/src/components/Splitter/Splitter.tsx +320 -47
  204. package/src/components/Tag/Tag.stories.tsx +1 -1
  205. package/src/components/Tag/Tag.theme.ts +1 -1
  206. package/src/components/Tag/Tag.tsx +3 -5
  207. package/src/components/Toast/Toast.theme.ts +3 -8
  208. package/src/components/Toast/Toast.tsx +16 -15
  209. package/src/components/Toolbar/Toolbar.tsx +10 -10
  210. package/src/components/Tooltip/TextTooltip.tsx +54 -0
  211. package/src/components/Tooltip/Tooltip.stories.tsx +2 -2
  212. package/src/components/Tooltip/Tooltip.tsx +3 -3
  213. package/src/components/Tooltip/index.ts +1 -0
  214. package/src/components/index.ts +0 -1
  215. package/src/exemplars/tabster.stories.tsx +1 -1
  216. package/src/index.ts +1 -1
  217. package/src/primitives/ThemeProvider/TranslationsProvider.tsx +10 -30
  218. package/src/testing/Loading.tsx +2 -1
  219. package/src/testing/decorators/withLayout.tsx +2 -2
  220. package/src/theme/defaultTheme.ts +0 -4
  221. package/src/theme/index.ts +0 -2
  222. package/src/translations.ts +18 -0
  223. package/src/util/slots.ts +5 -5
  224. package/dist/lib/browser/chunk-5SPBSIWS.mjs.map +0 -7
  225. package/dist/lib/browser/chunk-7JFD5ZHZ.mjs.map +0 -7
  226. package/dist/lib/node-esm/chunk-FPVTVXND.mjs.map +0 -7
  227. package/dist/lib/node-esm/chunk-TTEL2FP2.mjs.map +0 -7
  228. package/dist/types/src/components/Input/constants.d.ts +0 -2
  229. package/dist/types/src/components/Input/constants.d.ts.map +0 -1
  230. package/dist/types/src/components/List/List.d.ts +0 -29
  231. package/dist/types/src/components/List/List.d.ts.map +0 -1
  232. package/dist/types/src/components/List/List.stories.d.ts +0 -16
  233. package/dist/types/src/components/List/List.stories.d.ts.map +0 -1
  234. package/dist/types/src/components/List/List.theme.d.ts +0 -7
  235. package/dist/types/src/components/List/List.theme.d.ts.map +0 -1
  236. package/dist/types/src/components/List/ListDropIndicator.d.ts +0 -13
  237. package/dist/types/src/components/List/ListDropIndicator.d.ts.map +0 -1
  238. package/dist/types/src/components/List/Tree.d.ts +0 -23
  239. package/dist/types/src/components/List/Tree.d.ts.map +0 -1
  240. package/dist/types/src/components/List/Tree.stories.d.ts +0 -15
  241. package/dist/types/src/components/List/Tree.stories.d.ts.map +0 -1
  242. package/dist/types/src/components/List/TreeDropIndicator.d.ts +0 -8
  243. package/dist/types/src/components/List/TreeDropIndicator.d.ts.map +0 -1
  244. package/dist/types/src/components/List/Treegrid.d.ts +0 -33
  245. package/dist/types/src/components/List/Treegrid.d.ts.map +0 -1
  246. package/dist/types/src/components/List/Treegrid.stories.d.ts +0 -12
  247. package/dist/types/src/components/List/Treegrid.stories.d.ts.map +0 -1
  248. package/dist/types/src/components/List/Treegrid.theme.d.ts +0 -7
  249. package/dist/types/src/components/List/Treegrid.theme.d.ts.map +0 -1
  250. package/dist/types/src/components/List/index.d.ts +0 -4
  251. package/dist/types/src/components/List/index.d.ts.map +0 -1
  252. package/src/components/Input/constants.ts +0 -5
  253. package/src/components/List/List.stories.tsx +0 -234
  254. package/src/components/List/List.theme.ts +0 -47
  255. package/src/components/List/List.tsx +0 -171
  256. package/src/components/List/ListDropIndicator.tsx +0 -69
  257. package/src/components/List/Tree.stories.tsx +0 -87
  258. package/src/components/List/Tree.tsx +0 -74
  259. package/src/components/List/TreeDropIndicator.tsx +0 -70
  260. package/src/components/List/Treegrid.stories.tsx +0 -156
  261. package/src/components/List/Treegrid.theme.ts +0 -35
  262. package/src/components/List/Treegrid.tsx +0 -187
  263. package/src/components/List/index.ts +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-staging.ee54ba693a",
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",
@@ -85,17 +85,18 @@
85
85
  "react-error-boundary": "^4.0.13",
86
86
  "react-i18next": "^11.18.6",
87
87
  "react-remove-scroll": "^2.6.0",
88
- "@dxos/async": "0.9.0",
89
- "@dxos/invariant": "0.9.0",
90
- "@dxos/lit-ui": "0.9.0",
91
- "@dxos/react-error-boundary": "0.9.0",
92
- "@dxos/log": "0.9.0",
93
- "@dxos/react-hooks": "0.9.0",
94
- "@dxos/debug": "0.9.0",
95
- "@dxos/react-input": "0.9.0",
96
- "@dxos/ui-types": "0.9.0",
97
- "@dxos/react-list": "0.9.0",
98
- "@dxos/util": "0.9.0"
88
+ "@dxos/debug": "0.9.1-staging.ee54ba693a",
89
+ "@dxos/i18n": "0.9.1-staging.ee54ba693a",
90
+ "@dxos/invariant": "0.9.1-staging.ee54ba693a",
91
+ "@dxos/react-error-boundary": "0.9.1-staging.ee54ba693a",
92
+ "@dxos/async": "0.9.1-staging.ee54ba693a",
93
+ "@dxos/log": "0.9.1-staging.ee54ba693a",
94
+ "@dxos/lit-ui": "0.9.1-staging.ee54ba693a",
95
+ "@dxos/react-hooks": "0.9.1-staging.ee54ba693a",
96
+ "@dxos/react-input": "0.9.1-staging.ee54ba693a",
97
+ "@dxos/ui-types": "0.9.1-staging.ee54ba693a",
98
+ "@dxos/react-list": "0.9.1-staging.ee54ba693a",
99
+ "@dxos/util": "0.9.1-staging.ee54ba693a"
99
100
  },
100
101
  "devDependencies": {
101
102
  "@dnd-kit/core": "^6.0.5",
@@ -103,20 +104,20 @@
103
104
  "@dnd-kit/utilities": "^3.2.0",
104
105
  "@phosphor-icons/react": "2.1.10",
105
106
  "@tanstack/react-virtual": "^3.13.18",
106
- "@types/react": "~19.2.7",
107
+ "@types/react": "~19.2.17",
107
108
  "@types/react-dom": "~19.2.3",
108
- "react": "~19.2.3",
109
- "react-dom": "~19.2.3",
109
+ "react": "~19.2.7",
110
+ "react-dom": "~19.2.7",
110
111
  "tabster": "^8.5.5",
111
112
  "vite": "^8.0.16",
112
- "@dxos/random": "0.9.0",
113
- "@dxos/ui-theme": "0.9.0",
114
- "@dxos/util": "0.9.0"
113
+ "@dxos/random": "0.9.1-staging.ee54ba693a",
114
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a",
115
+ "@dxos/util": "0.9.1-staging.ee54ba693a"
115
116
  },
116
117
  "peerDependencies": {
117
- "react": "~19.2.3",
118
- "react-dom": "~19.2.3",
119
- "@dxos/ui-theme": "0.9.0"
118
+ "react": "~19.2.7",
119
+ "react-dom": "~19.2.7",
120
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a"
120
121
  },
121
122
  "publishConfig": {
122
123
  "access": "public"
@@ -11,7 +11,7 @@ import { hexToFallback } from '@dxos/util';
11
11
  import { withTheme } from '../../testing';
12
12
  import { Avatar, type AvatarAnimation, type AvatarStatus, type AvatarVariant } from './Avatar';
13
13
 
14
- type DefaultStoryProps = PropsWithChildren<{
14
+ type StoryArgs = PropsWithChildren<{
15
15
  id?: string;
16
16
  imgSrc?: string;
17
17
  fallbackText?: string;
@@ -24,7 +24,7 @@ type DefaultStoryProps = PropsWithChildren<{
24
24
  hue?: ChromaticPalette;
25
25
  }>;
26
26
 
27
- const DefaultStory = (props: DefaultStoryProps) => {
27
+ const DefaultStory = (props: StoryArgs) => {
28
28
  const {
29
29
  id = '20970b563fc49b5bb194a6ffdff376031a3a11f9481360c071c3fed87874106b',
30
30
  status,
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { mx, getSize, getHeight } from '@dxos/ui-theme';
5
+ import { getHeight, getSize, mx } from '@dxos/ui-theme';
6
6
  import { type ComponentFunction, type Size, type Theme } from '@dxos/ui-types';
7
7
 
8
8
  export type AvatarStyleProps = Partial<{
@@ -101,11 +101,11 @@ export const Avatar = {
101
101
  export { useAvatarContext };
102
102
 
103
103
  export type {
104
- AvatarStatus,
105
- AvatarVariant,
106
104
  AvatarAnimation,
107
105
  AvatarContentProps,
108
- AvatarLabelProps,
109
106
  AvatarDescriptionProps,
107
+ AvatarLabelProps,
108
+ AvatarStatus,
109
+ AvatarVariant,
110
110
  NaturalDxAvatar as DxAvatar,
111
111
  };
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { Primitive } from '@radix-ui/react-primitive';
6
6
  import { Slot } from '@radix-ui/react-slot';
7
- import React, { type ComponentPropsWithRef, type ComponentPropsWithoutRef, forwardRef } from 'react';
7
+ import React, { type ComponentPropsWithoutRef, type ComponentPropsWithRef, forwardRef } from 'react';
8
8
 
9
9
  import { useThemeContext } from '../../hooks';
10
10
  import { type ThemedClassName } from '../../util';
@@ -13,7 +13,7 @@ import { Link, type LinkProps } from '../Link';
13
13
 
14
14
  type BreadcrumbRootProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.div>> & {
15
15
  'aria-label': string;
16
- asChild?: boolean;
16
+ 'asChild'?: boolean;
17
17
  };
18
18
 
19
19
  const BreadcrumbRoot = forwardRef<HTMLDivElement, BreadcrumbRootProps>(
@@ -101,10 +101,10 @@ export const Breadcrumb = {
101
101
  };
102
102
 
103
103
  export type {
104
- BreadcrumbRootProps,
105
- BreadcrumbListProps,
106
- BreadcrumbListItemProps,
107
- BreadcrumbLinkProps,
108
104
  BreadcrumbCurrentProps,
105
+ BreadcrumbLinkProps,
106
+ BreadcrumbListItemProps,
107
+ BreadcrumbListProps,
108
+ BreadcrumbRootProps,
109
109
  BreadcrumbSeparatorProps,
110
110
  };
@@ -11,12 +11,15 @@ import { type Density, type Elevation } from '@dxos/ui-types';
11
11
 
12
12
  import { useDensityContext, useElevationContext, useThemeContext } from '../../hooks';
13
13
  import { type ThemedClassName } from '../../util';
14
+ import { Icon } from '../Icon';
14
15
 
15
16
  type ButtonProps = ThemedClassName<ComponentPropsWithRef<typeof Primitive.button>> & {
16
17
  variant?: 'default' | 'primary' | 'outline' | 'ghost' | 'destructive' | 'valence';
17
18
  density?: Density;
18
19
  elevation?: Elevation;
19
20
  asChild?: boolean;
21
+ /** Render a trailing caret indicating the button opens a menu. */
22
+ caretDown?: boolean;
20
23
  };
21
24
 
22
25
  type ButtonGroupContextValue = { inGroup?: boolean };
@@ -31,7 +34,16 @@ const [ButtonGroupProvider, useButtonGroupContext] = createContext<ButtonGroupCo
31
34
  const Button = memo(
32
35
  forwardRef<HTMLButtonElement, ButtonProps>(
33
36
  (
34
- { classNames, children, density: densityProp, elevation: elevationProp, variant = 'default', asChild, ...props },
37
+ {
38
+ classNames,
39
+ children,
40
+ density: densityProp,
41
+ elevation: elevationProp,
42
+ variant = 'default',
43
+ asChild,
44
+ caretDown,
45
+ ...props
46
+ },
35
47
  ref,
36
48
  ) => {
37
49
  const { inGroup } = useButtonGroupContext(BUTTON_NAME);
@@ -59,7 +71,16 @@ const Button = memo(
59
71
  )}
60
72
  {...(props.disabled && { disabled: true })}
61
73
  >
62
- {children}
74
+ {/* `asChild` forwards a single child via Slot (React.Children.only); only add the caret in
75
+ the non-`asChild` case so Slot still receives exactly one child. */}
76
+ {caretDown && !asChild ? (
77
+ <>
78
+ {children}
79
+ <Icon size={3} icon='ph--caret-down--bold' />
80
+ </>
81
+ ) : (
82
+ children
83
+ )}
63
84
  </Comp>
64
85
  );
65
86
  },
@@ -88,6 +109,6 @@ const ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(
88
109
 
89
110
  ButtonGroup.displayName = BUTTON_GROUP_NAME;
90
111
 
91
- export { Button, ButtonGroup, BUTTON_GROUP_NAME, useButtonGroupContext };
112
+ export { Button, BUTTON_GROUP_NAME, ButtonGroup, useButtonGroupContext };
92
113
 
93
- export type { ButtonProps, ButtonGroupProps };
114
+ export type { ButtonGroupProps, ButtonProps };
@@ -3,14 +3,16 @@
3
3
  //
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
- import React from 'react';
6
+ import React, { type ReactNode, useState } from 'react';
7
7
 
8
8
  import { type Density } from '@dxos/ui-types';
9
9
 
10
10
  import { withTheme } from '../../testing';
11
+ import { translations } from '../../translations';
11
12
  import { Tooltip } from '../Tooltip';
12
13
  import { Button } from './Button';
13
14
  import { IconButton, type IconButtonProps } from './IconButton';
15
+ import { SystemIconButton } from './SystemIconButton';
14
16
 
15
17
  const DefaultStory = (props: IconButtonProps) => {
16
18
  return (
@@ -60,6 +62,76 @@ const DensitiesStory = (props: Omit<IconButtonProps, 'density' | 'size'>) => {
60
62
  );
61
63
  };
62
64
 
65
+ type SystemPresetVariantProps = Partial<Pick<IconButtonProps, 'variant' | 'iconOnly'>>;
66
+
67
+ const SystemPresetRow = ({
68
+ name,
69
+ button,
70
+ }: {
71
+ name: string;
72
+ button: (props: SystemPresetVariantProps) => ReactNode;
73
+ }) => (
74
+ <div className='grid grid-cols-subgrid col-span-full gap-x-8 items-center'>
75
+ <div className='text-xs font-mono'>{name}</div>
76
+ <div>{button({})}</div>
77
+ <div>{button({ variant: 'ghost' })}</div>
78
+ <div>{button({ variant: 'ghost', iconOnly: true })}</div>
79
+ </div>
80
+ );
81
+
82
+ const SystemStory = () => {
83
+ const [state, setState] = useState<Record<string, boolean>>({});
84
+
85
+ return (
86
+ <Tooltip.Provider>
87
+ <div className='grid grid-cols-[auto_1fr_1fr_auto] gap-y-3 items-center'>
88
+ <div className='grid grid-cols-subgrid col-span-full gap-x-8'>
89
+ <div />
90
+ <div className='text-xs text-subdued uppercase'>default</div>
91
+ <div className='text-xs text-subdued uppercase'>ghost</div>
92
+ <div className='text-xs text-subdued uppercase'>iconOnly</div>
93
+ </div>
94
+
95
+ <SystemPresetRow
96
+ name='Star'
97
+ button={(props) => (
98
+ <SystemIconButton.Star
99
+ active={state.star}
100
+ onClick={() => setState((prev) => ({ ...prev, star: !prev.star }))}
101
+ {...props}
102
+ />
103
+ )}
104
+ />
105
+ <SystemPresetRow
106
+ name='Bookmark'
107
+ button={(props) => (
108
+ <SystemIconButton.Bookmark
109
+ active={state.bookmark}
110
+ onClick={() => setState((prev) => ({ ...prev, bookmark: !prev.bookmark }))}
111
+ {...props}
112
+ />
113
+ )}
114
+ />
115
+ <SystemPresetRow
116
+ name='Expander'
117
+ button={(props) => (
118
+ <SystemIconButton.Expander
119
+ active={state.expander}
120
+ onClick={() => setState((prev) => ({ ...prev, expander: !prev.expander }))}
121
+ {...props}
122
+ />
123
+ )}
124
+ />
125
+ <br />
126
+ <SystemPresetRow name='Add' button={(props) => <SystemIconButton.Add {...props} />} />
127
+ <SystemPresetRow name='Delete' button={(props) => <SystemIconButton.Delete {...props} />} />
128
+ <SystemPresetRow name='Edit' button={(props) => <SystemIconButton.Edit {...props} />} />
129
+ <SystemPresetRow name='Close' button={(props) => <SystemIconButton.Close {...props} />} />
130
+ </div>
131
+ </Tooltip.Provider>
132
+ );
133
+ };
134
+
63
135
  const meta = {
64
136
  title: 'ui/react-ui-core/components/IconButton',
65
137
  component: IconButton,
@@ -67,6 +139,7 @@ const meta = {
67
139
  decorators: [withTheme()],
68
140
  parameters: {
69
141
  layout: 'centered',
142
+ translations,
70
143
  },
71
144
  } satisfies Meta<typeof IconButton>;
72
145
 
@@ -90,3 +163,10 @@ export const Ghost: Story = {
90
163
  variant: 'ghost',
91
164
  },
92
165
  };
166
+
167
+ export const System: Story = {
168
+ render: SystemStory,
169
+ args: {
170
+ label: 'System',
171
+ },
172
+ };
@@ -14,9 +14,8 @@ type IconButtonProps = Omit<ButtonProps, 'children'> &
14
14
  Partial<Pick<IconProps, 'icon' | 'size'>> & {
15
15
  label: string;
16
16
  noTooltip?: boolean;
17
- caretDown?: boolean;
18
17
  iconOnly?: boolean;
19
- square?: boolean; // TODO(burdon): Handle more uniformly.
18
+ square?: boolean; // TODO(burdon): Should be automatic in style?
20
19
  iconEnd?: boolean;
21
20
  iconClassNames?: ThemedClassName<any>['classNames'];
22
21
  tooltipSide?: TooltipSide;
@@ -46,7 +45,7 @@ const IconOnlyButton = forwardRef<HTMLButtonElement, IconButtonProps>(
46
45
 
47
46
  const LabelledIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
48
47
  (
49
- { size, icon, iconOnly, square, iconEnd, iconClassNames, label, caretDown, noTooltip: _, classNames, ...props },
48
+ { size, icon, iconOnly, square, iconEnd, iconClassNames, label, noTooltip: _, classNames, ...props },
50
49
  forwardedRef,
51
50
  ) => {
52
51
  const { tx } = useThemeContext();
@@ -55,7 +54,6 @@ const LabelledIconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
55
54
  {icon && !iconEnd && <Icon icon={icon} size={size} classNames={iconClassNames} />}
56
55
  <span className={iconOnly ? 'sr-only' : undefined}>{label}</span>
57
56
  {icon && iconEnd && <Icon icon={icon} size={size} classNames={iconClassNames} />}
58
- {caretDown && <Icon size={3} icon='ph--caret-down--bold' />}
59
57
  </Button>
60
58
  );
61
59
  },
@@ -0,0 +1,60 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { withTheme } from '../../testing';
9
+ import { translations } from '../../translations';
10
+ import { Tooltip } from '../Tooltip';
11
+ import { MicButton, type MicButtonProps } from './MicButton';
12
+
13
+ const DefaultStory = ({ mode = 'toggle', ...props }: MicButtonProps) => {
14
+ const [recording, setRecording] = useState(false);
15
+
16
+ return (
17
+ <Tooltip.Provider>
18
+ <MicButton
19
+ iconOnly
20
+ variant='ghost'
21
+ {...props}
22
+ mode={mode}
23
+ // `label`/`recording`/handlers are driven by story state so the demo reacts to interaction.
24
+ label={recording ? 'Stop recording' : mode === 'hold' ? 'Hold to record' : 'Start recording'}
25
+ recording={recording}
26
+ onToggle={() => setRecording((value) => !value)}
27
+ onPressStart={() => setRecording(true)}
28
+ onPressEnd={() => setRecording(false)}
29
+ />
30
+ </Tooltip.Provider>
31
+ );
32
+ };
33
+
34
+ const meta = {
35
+ title: 'ui/react-ui-core/components/MicButton',
36
+ decorators: [withTheme()],
37
+ component: MicButton,
38
+ render: DefaultStory,
39
+ args: { label: 'Record', mode: 'toggle' },
40
+ parameters: {
41
+ layout: 'centered',
42
+ translations,
43
+ },
44
+ } satisfies Meta<typeof MicButton>;
45
+
46
+ export default meta;
47
+
48
+ type Story = StoryObj<typeof meta>;
49
+
50
+ export const Toggle: Story = {
51
+ args: {
52
+ mode: 'toggle',
53
+ },
54
+ };
55
+
56
+ export const Hold: Story = {
57
+ args: {
58
+ mode: 'hold',
59
+ },
60
+ };
@@ -0,0 +1,117 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { type KeyboardEvent, type PointerEvent, forwardRef, useCallback, useRef } from 'react';
6
+
7
+ import { IconButton, type IconButtonProps } from './IconButton';
8
+
9
+ export type MicButtonMode = 'toggle' | 'hold';
10
+
11
+ export type MicButtonProps = Omit<IconButtonProps, 'icon' | 'onClick'> & {
12
+ /** Defaults to a microphone glyph. */
13
+ icon?: IconButtonProps['icon'];
14
+ /** `toggle`: click flips recording. `hold`: records only while held (push-to-talk). */
15
+ mode?: MicButtonMode;
16
+ /** Whether recording is active; drives the active (recording) styling. */
17
+ recording?: boolean;
18
+ /** Fired in `toggle` mode on click. */
19
+ onToggle?: () => void;
20
+ /** Fired in `hold` mode when the press begins. */
21
+ onPressStart?: () => void;
22
+ /** Fired in `hold` mode when the press ends (release, cancel, or lost capture). */
23
+ onPressEnd?: () => void;
24
+ };
25
+
26
+ /**
27
+ * Microphone record button. In `toggle` mode a click flips recording; in `hold` mode recording is
28
+ * active only while the button is held (push-to-talk), using pointer capture so the release still
29
+ * fires if the pointer leaves the button. Presentational — the caller owns recording state.
30
+ */
31
+ export const MicButton = forwardRef<HTMLButtonElement, MicButtonProps>(
32
+ (
33
+ {
34
+ classNames,
35
+ icon = 'ph--microphone--regular',
36
+ mode = 'toggle',
37
+ recording,
38
+ onToggle,
39
+ onPressStart,
40
+ onPressEnd,
41
+ ...props
42
+ },
43
+ forwardedRef,
44
+ ) => {
45
+ // A press spans pointer down→up (or key down→up). The guard makes start/end fire exactly once
46
+ // even though release surfaces as both `pointerup` and `lostpointercapture`.
47
+ const pressedRef = useRef(false);
48
+ const beginPress = useCallback(() => {
49
+ if (!pressedRef.current) {
50
+ pressedRef.current = true;
51
+ onPressStart?.();
52
+ }
53
+ }, [onPressStart]);
54
+
55
+ const endPress = useCallback(() => {
56
+ if (pressedRef.current) {
57
+ pressedRef.current = false;
58
+ onPressEnd?.();
59
+ }
60
+ }, [onPressEnd]);
61
+ const handlePointerDown = useCallback(
62
+ (event: PointerEvent<HTMLButtonElement>) => {
63
+ // Capture so the matching release fires on this button even if the pointer leaves it.
64
+ event.currentTarget.setPointerCapture(event.pointerId);
65
+ beginPress();
66
+ },
67
+ [beginPress],
68
+ );
69
+ const handleKeyDown = useCallback(
70
+ (event: KeyboardEvent<HTMLButtonElement>) => {
71
+ // Keyboard push-to-talk: hold Space/Enter to record. Ignore auto-repeat.
72
+ if ((event.key === ' ' || event.key === 'Enter') && !event.repeat) {
73
+ event.preventDefault();
74
+ beginPress();
75
+ }
76
+ },
77
+ [beginPress],
78
+ );
79
+ const handleKeyUp = useCallback(
80
+ (event: KeyboardEvent<HTMLButtonElement>) => {
81
+ if (event.key === ' ' || event.key === 'Enter') {
82
+ event.preventDefault();
83
+ endPress();
84
+ }
85
+ },
86
+ [endPress],
87
+ );
88
+
89
+ // Highlight with the error (rose) tone while recording.
90
+ const recordingClassNames = recording ? 'bg-error-surface' : undefined;
91
+ const holdHandlers =
92
+ mode === 'hold'
93
+ ? {
94
+ onPointerDown: handlePointerDown,
95
+ onPointerUp: endPress,
96
+ onPointerCancel: endPress,
97
+ onLostPointerCapture: endPress,
98
+ onKeyDown: handleKeyDown,
99
+ onKeyUp: handleKeyUp,
100
+ // Releasing focus mid-hold (e.g. tabbing away) must still end the press.
101
+ onBlur: endPress,
102
+ }
103
+ : {
104
+ onClick: onToggle,
105
+ };
106
+
107
+ return (
108
+ <IconButton
109
+ {...props}
110
+ {...holdHandlers}
111
+ classNames={[recordingClassNames, classNames]}
112
+ icon={icon}
113
+ ref={forwardedRef}
114
+ />
115
+ );
116
+ },
117
+ );
@@ -0,0 +1,91 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { withTheme } from '../../testing';
9
+ import { translations } from '../../translations';
10
+ import { Toolbar } from '../Toolbar';
11
+ import { Tooltip } from '../Tooltip';
12
+ import { SystemIconButton } from './SystemIconButton';
13
+
14
+ const iconOnly = { iconOnly: true, variant: 'ghost' as const };
15
+
16
+ const ToolbarStory = () => {
17
+ const [state, setState] = useState({ star: false, bookmark: false, expander: false });
18
+
19
+ return (
20
+ <Tooltip.Provider>
21
+ <Toolbar.Root>
22
+ <Toolbar.Button asChild>
23
+ <SystemIconButton.Star
24
+ {...iconOnly}
25
+ active={state.star}
26
+ onClick={() => setState((prev) => ({ ...prev, star: !prev.star }))}
27
+ />
28
+ </Toolbar.Button>
29
+ <Toolbar.Button asChild>
30
+ <SystemIconButton.Bookmark
31
+ {...iconOnly}
32
+ active={state.bookmark}
33
+ onClick={() => setState((prev) => ({ ...prev, bookmark: !prev.bookmark }))}
34
+ />
35
+ </Toolbar.Button>
36
+ <Toolbar.Button asChild>
37
+ <SystemIconButton.Expander
38
+ {...iconOnly}
39
+ active={state.expander}
40
+ onClick={() => setState((prev) => ({ ...prev, expander: !prev.expander }))}
41
+ />
42
+ </Toolbar.Button>
43
+ <Toolbar.Separator variant='line' />
44
+ <Toolbar.Button asChild>
45
+ <SystemIconButton.Add {...iconOnly} />
46
+ </Toolbar.Button>
47
+ <Toolbar.Button asChild>
48
+ <SystemIconButton.Edit {...iconOnly} />
49
+ </Toolbar.Button>
50
+ <Toolbar.Button asChild>
51
+ <SystemIconButton.Delete {...iconOnly} />
52
+ </Toolbar.Button>
53
+ <Toolbar.Separator variant='line' />
54
+ <Toolbar.Button asChild>
55
+ <SystemIconButton.Clipboard {...iconOnly} onCopy={() => 'Copied from toolbar'} />
56
+ </Toolbar.Button>
57
+ <SystemIconButton.Upload {...iconOnly} accept='*/*' />
58
+ <Toolbar.Button asChild>
59
+ <SystemIconButton.Download
60
+ {...iconOnly}
61
+ filename='example.txt'
62
+ onDownload={() => new Blob(['Hello from SystemIconButton'])}
63
+ />
64
+ </Toolbar.Button>
65
+ <Toolbar.Separator variant='line' />
66
+ <Toolbar.Button asChild>
67
+ <SystemIconButton.Close {...iconOnly} />
68
+ </Toolbar.Button>
69
+ </Toolbar.Root>
70
+ </Tooltip.Provider>
71
+ );
72
+ };
73
+
74
+ const meta = {
75
+ title: 'ui/react-ui-core/components/SystemIconButton',
76
+ component: SystemIconButton.Add,
77
+ render: ToolbarStory,
78
+ decorators: [withTheme()],
79
+ parameters: {
80
+ layout: 'centered',
81
+ translations,
82
+ },
83
+ } satisfies Meta<typeof SystemIconButton.Add>;
84
+
85
+ export default meta;
86
+
87
+ type Story = StoryObj<typeof meta>;
88
+
89
+ export const Default: Story = {
90
+ args: {},
91
+ };