@duro-app/ui 4.4.0 → 5.0.0

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 (273) hide show
  1. package/dist/{Table-JTgcR_Fh.js → Table-BKN_d-mp.js} +506 -410
  2. package/dist/Table-BKN_d-mp.js.map +1 -0
  3. package/dist/components/ActionBar/ActionBar.stories.d.ts.map +1 -1
  4. package/dist/components/ActionBar/styles.css.d.ts +7 -7
  5. package/dist/components/ActionBar/styles.css.d.ts.map +1 -1
  6. package/dist/components/Alert/styles.css.d.ts +2 -2
  7. package/dist/components/Alert/styles.css.d.ts.map +1 -1
  8. package/dist/components/Badge/styles.css.d.ts +2 -2
  9. package/dist/components/Button/styles.css.d.ts +5 -5
  10. package/dist/components/Button/styles.css.d.ts.map +1 -1
  11. package/dist/components/Callout/styles.css.d.ts +1 -1
  12. package/dist/components/Callout/styles.css.d.ts.map +1 -1
  13. package/dist/components/Card/styles.css.d.ts +3 -3
  14. package/dist/components/Card/styles.css.d.ts.map +1 -1
  15. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  16. package/dist/components/Checkbox/styles.css.d.ts +7 -11
  17. package/dist/components/Checkbox/styles.css.d.ts.map +1 -1
  18. package/dist/components/Cluster/Cluster.stories.d.ts.map +1 -1
  19. package/dist/components/ColorInput/styles.css.d.ts +6 -6
  20. package/dist/components/ColorInput/styles.css.d.ts.map +1 -1
  21. package/dist/components/ColorMode/styles.css.d.ts +3 -3
  22. package/dist/components/ColorMode/styles.css.d.ts.map +1 -1
  23. package/dist/components/Combobox/Combobox.d.ts.map +1 -1
  24. package/dist/components/Combobox/Combobox.meta.d.ts.map +1 -1
  25. package/dist/components/Combobox/styles.css.d.ts +3 -3
  26. package/dist/components/Combobox/styles.css.d.ts.map +1 -1
  27. package/dist/components/DetailPanel/DetailPanel.d.ts.map +1 -1
  28. package/dist/components/DetailPanel/DetailPanel.stories.d.ts.map +1 -1
  29. package/dist/components/DetailPanel/styles.css.d.ts +19 -10
  30. package/dist/components/DetailPanel/styles.css.d.ts.map +1 -1
  31. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  32. package/dist/components/Dialog/Dialog.stories.d.ts.map +1 -1
  33. package/dist/components/Dialog/styles.css.d.ts +18 -9
  34. package/dist/components/Dialog/styles.css.d.ts.map +1 -1
  35. package/dist/components/DragDrop/DragDrop.d.ts.map +1 -1
  36. package/dist/components/DragDrop/DragDrop.stories.d.ts.map +1 -1
  37. package/dist/components/DragDrop/styles.css.d.ts +0 -6
  38. package/dist/components/DragDrop/styles.css.d.ts.map +1 -1
  39. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  40. package/dist/components/Drawer/DrawerScroll.stories.d.ts +13 -0
  41. package/dist/components/Drawer/DrawerScroll.stories.d.ts.map +1 -0
  42. package/dist/components/Drawer/styles.css.d.ts +19 -10
  43. package/dist/components/Drawer/styles.css.d.ts.map +1 -1
  44. package/dist/components/Drawer/useSwipeDismiss.d.ts +7 -2
  45. package/dist/components/Drawer/useSwipeDismiss.d.ts.map +1 -1
  46. package/dist/components/Field/Field.stories.d.ts.map +1 -1
  47. package/dist/components/Field/styles.css.d.ts +1 -1
  48. package/dist/components/Field/styles.css.d.ts.map +1 -1
  49. package/dist/components/Form/Form.stories.d.ts.map +1 -1
  50. package/dist/components/Grid/Grid.d.ts +6 -4
  51. package/dist/components/Grid/Grid.d.ts.map +1 -1
  52. package/dist/components/Grid/Grid.stories.d.ts.map +1 -1
  53. package/dist/components/Grid/styles.css.d.ts +3 -3
  54. package/dist/components/Input/Input.stories.d.ts.map +1 -1
  55. package/dist/components/Input/styles.css.d.ts +3 -3
  56. package/dist/components/Input/styles.css.d.ts.map +1 -1
  57. package/dist/components/InputGroup/InputGroup.d.ts +4 -2
  58. package/dist/components/InputGroup/InputGroup.d.ts.map +1 -1
  59. package/dist/components/InputGroup/InputGroup.stories.d.ts.map +1 -1
  60. package/dist/components/InputGroup/styles.css.d.ts +3 -3
  61. package/dist/components/InputGroup/styles.css.d.ts.map +1 -1
  62. package/dist/components/LinkButton/styles.css.d.ts +1 -1
  63. package/dist/components/LinkButton/styles.css.d.ts.map +1 -1
  64. package/dist/components/List/List.stories.d.ts.map +1 -1
  65. package/dist/components/List/styles.css.d.ts +3 -3
  66. package/dist/components/List/styles.css.d.ts.map +1 -1
  67. package/dist/components/Menu/styles.css.d.ts +4 -4
  68. package/dist/components/Menu/styles.css.d.ts.map +1 -1
  69. package/dist/components/Menu/useMenuRoot.d.ts.map +1 -1
  70. package/dist/components/PageShell/styles.css.d.ts +3 -3
  71. package/dist/components/PageShell/styles.css.d.ts.map +1 -1
  72. package/dist/components/Panel/styles.css.d.ts +3 -3
  73. package/dist/components/Panel/styles.css.d.ts.map +1 -1
  74. package/dist/components/Popover/Popover.d.ts.map +1 -1
  75. package/dist/components/Popover/Popover.meta.d.ts.map +1 -1
  76. package/dist/components/Popover/Popover.stories.d.ts.map +1 -1
  77. package/dist/components/Popover/PopoverLayerContext.d.ts +10 -0
  78. package/dist/components/Popover/PopoverLayerContext.d.ts.map +1 -0
  79. package/dist/components/Popover/PopoverLayers.stories.d.ts +13 -0
  80. package/dist/components/Popover/PopoverLayers.stories.d.ts.map +1 -0
  81. package/dist/components/Popover/styles.css.d.ts +2 -2
  82. package/dist/components/Popover/styles.css.d.ts.map +1 -1
  83. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  84. package/dist/components/RadioGroup/styles.css.d.ts +5 -9
  85. package/dist/components/RadioGroup/styles.css.d.ts.map +1 -1
  86. package/dist/components/ScrollArea/ScrollArea.d.ts +10 -3
  87. package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  88. package/dist/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  89. package/dist/components/ScrollArea/styles.css.d.ts +8 -8
  90. package/dist/components/ScrollArea/styles.css.d.ts.map +1 -1
  91. package/dist/components/Select/Select.d.ts.map +1 -1
  92. package/dist/components/Select/Select.meta.d.ts.map +1 -1
  93. package/dist/components/Select/styles.css.d.ts +4 -4
  94. package/dist/components/Select/styles.css.d.ts.map +1 -1
  95. package/dist/components/Select/useSelectRoot.d.ts.map +1 -1
  96. package/dist/components/SideNav/styles.css.d.ts +7 -7
  97. package/dist/components/SideNav/styles.css.d.ts.map +1 -1
  98. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  99. package/dist/components/Spinner/styles.css.d.ts +10 -14
  100. package/dist/components/Spinner/styles.css.d.ts.map +1 -1
  101. package/dist/components/Switch/Switch.d.ts.map +1 -1
  102. package/dist/components/Switch/styles.css.d.ts +10 -14
  103. package/dist/components/Switch/styles.css.d.ts.map +1 -1
  104. package/dist/components/Table/ColumnFilter.d.ts.map +1 -1
  105. package/dist/components/Table/FromTanstack.d.ts +2 -1
  106. package/dist/components/Table/FromTanstack.d.ts.map +1 -1
  107. package/dist/components/Table/Pagination.d.ts.map +1 -1
  108. package/dist/components/Table/SortIndicator.d.ts.map +1 -1
  109. package/dist/components/Table/Table.d.ts +11 -9
  110. package/dist/components/Table/Table.d.ts.map +1 -1
  111. package/dist/components/Table/Table.stories.d.ts.map +1 -1
  112. package/dist/components/Table/styles.css.d.ts +6 -6
  113. package/dist/components/Table/styles.css.d.ts.map +1 -1
  114. package/dist/components/Tabs/styles.css.d.ts +8 -8
  115. package/dist/components/Tabs/styles.css.d.ts.map +1 -1
  116. package/dist/components/Tag/Tag.stories.d.ts.map +1 -1
  117. package/dist/components/Tag/styles.css.d.ts +4 -4
  118. package/dist/components/Tag/styles.css.d.ts.map +1 -1
  119. package/dist/components/TagGroup/TagGroup.d.ts.map +1 -1
  120. package/dist/components/TagGroup/styles.css.d.ts +4 -10
  121. package/dist/components/TagGroup/styles.css.d.ts.map +1 -1
  122. package/dist/components/Textarea/Textarea.stories.d.ts.map +1 -1
  123. package/dist/components/Textarea/styles.css.d.ts +3 -3
  124. package/dist/components/Textarea/styles.css.d.ts.map +1 -1
  125. package/dist/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  126. package/dist/components/Toast/Toast.stories.d.ts.map +1 -1
  127. package/dist/components/Toast/styles.css.d.ts +12 -12
  128. package/dist/components/Toast/styles.css.d.ts.map +1 -1
  129. package/dist/components/Toggle/Toggle.d.ts.map +1 -1
  130. package/dist/components/Toggle/styles.css.d.ts +14 -4
  131. package/dist/components/Toggle/styles.css.d.ts.map +1 -1
  132. package/dist/components/ToggleGroup/ToggleGroup.d.ts +7 -1
  133. package/dist/components/ToggleGroup/ToggleGroup.d.ts.map +1 -1
  134. package/dist/components/ToggleGroup/ToggleGroup.meta.d.ts.map +1 -1
  135. package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts +4 -0
  136. package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts.map +1 -1
  137. package/dist/components/ToggleGroup/ToggleGroupContext.d.ts +6 -0
  138. package/dist/components/ToggleGroup/ToggleGroupContext.d.ts.map +1 -1
  139. package/dist/components/ToggleGroup/styles.css.d.ts +20 -1
  140. package/dist/components/ToggleGroup/styles.css.d.ts.map +1 -1
  141. package/dist/components/ToggleGroup/useRovingFocus.d.ts +17 -0
  142. package/dist/components/ToggleGroup/useRovingFocus.d.ts.map +1 -0
  143. package/dist/components/Tooltip/styles.css.d.ts +1 -1
  144. package/dist/components/Tooltip/styles.css.d.ts.map +1 -1
  145. package/dist/components/Tree/styles.css.d.ts +4 -4
  146. package/dist/components/Tree/styles.css.d.ts.map +1 -1
  147. package/dist/components/VirtualTable/VirtualTable.d.ts +2 -1
  148. package/dist/components/VirtualTable/VirtualTable.d.ts.map +1 -1
  149. package/dist/components/VirtualTable/VirtualTable.stories.d.ts.map +1 -1
  150. package/dist/components/VirtualTable/styles.css.d.ts +7 -7
  151. package/dist/components/VirtualTable/styles.css.d.ts.map +1 -1
  152. package/dist/docs/Spacing.stories.d.ts.map +1 -1
  153. package/dist/docs/Typography.stories.d.ts.map +1 -1
  154. package/dist/docs/helpers.d.ts.map +1 -1
  155. package/dist/index.css +1 -1
  156. package/dist/index.js +3788 -3515
  157. package/dist/index.js.map +1 -1
  158. package/dist/shared/length.d.ts +24 -0
  159. package/dist/shared/length.d.ts.map +1 -0
  160. package/dist/shared/length.typecheck.d.ts +28 -0
  161. package/dist/shared/length.typecheck.d.ts.map +1 -0
  162. package/dist/styles/visually-hidden.css.d.ts +10 -0
  163. package/dist/styles/visually-hidden.css.d.ts.map +1 -0
  164. package/dist/table.js +166 -166
  165. package/dist/table.js.map +1 -1
  166. package/package.json +2 -2
  167. package/src/components/ActionBar/ActionBar.stories.tsx +4 -2
  168. package/src/components/ActionBar/styles.css.ts +11 -9
  169. package/src/components/Alert/styles.css.ts +4 -3
  170. package/src/components/Badge/styles.css.ts +3 -3
  171. package/src/components/Button/styles.css.ts +8 -7
  172. package/src/components/Callout/styles.css.ts +2 -1
  173. package/src/components/Card/styles.css.ts +4 -3
  174. package/src/components/Checkbox/Checkbox.tsx +2 -1
  175. package/src/components/Checkbox/styles.css.ts +10 -11
  176. package/src/components/Cluster/Cluster.stories.tsx +2 -1
  177. package/src/components/ColorInput/styles.css.ts +9 -7
  178. package/src/components/ColorMode/styles.css.ts +4 -3
  179. package/src/components/Combobox/Combobox.meta.ts +6 -0
  180. package/src/components/Combobox/Combobox.tsx +5 -0
  181. package/src/components/Combobox/styles.css.ts +5 -3
  182. package/src/components/DetailPanel/DetailPanel.stories.tsx +5 -3
  183. package/src/components/DetailPanel/DetailPanel.tsx +3 -0
  184. package/src/components/DetailPanel/styles.css.ts +17 -11
  185. package/src/components/Dialog/Dialog.stories.tsx +2 -1
  186. package/src/components/Dialog/Dialog.tsx +3 -0
  187. package/src/components/Dialog/styles.css.ts +14 -9
  188. package/src/components/DragDrop/DragDrop.stories.tsx +2 -1
  189. package/src/components/DragDrop/DragDrop.tsx +2 -1
  190. package/src/components/DragDrop/styles.css.ts +0 -7
  191. package/src/components/Drawer/Drawer.meta.ts +1 -1
  192. package/src/components/Drawer/Drawer.tsx +15 -2
  193. package/src/components/Drawer/DrawerScroll.stories.tsx +292 -0
  194. package/src/components/Drawer/styles.css.ts +15 -10
  195. package/src/components/Drawer/useSwipeDismiss.ts +53 -8
  196. package/src/components/Field/Field.stories.tsx +3 -2
  197. package/src/components/Field/styles.css.ts +2 -1
  198. package/src/components/Form/Form.stories.tsx +4 -3
  199. package/src/components/Grid/Grid.meta.ts +2 -2
  200. package/src/components/Grid/Grid.stories.tsx +3 -2
  201. package/src/components/Grid/Grid.tsx +8 -6
  202. package/src/components/Grid/styles.css.ts +2 -2
  203. package/src/components/Input/Input.stories.tsx +2 -1
  204. package/src/components/Input/styles.css.ts +4 -3
  205. package/src/components/InputGroup/InputGroup.stories.tsx +3 -2
  206. package/src/components/InputGroup/InputGroup.tsx +5 -3
  207. package/src/components/InputGroup/styles.css.ts +4 -3
  208. package/src/components/LinkButton/styles.css.ts +2 -1
  209. package/src/components/List/List.stories.tsx +4 -2
  210. package/src/components/List/styles.css.ts +6 -4
  211. package/src/components/Menu/styles.css.ts +6 -4
  212. package/src/components/Menu/useMenuRoot.ts +5 -1
  213. package/src/components/PageShell/styles.css.ts +4 -3
  214. package/src/components/Panel/styles.css.ts +4 -3
  215. package/src/components/Popover/Popover.meta.ts +7 -0
  216. package/src/components/Popover/Popover.stories.tsx +6 -4
  217. package/src/components/Popover/Popover.tsx +30 -24
  218. package/src/components/Popover/PopoverLayerContext.ts +20 -0
  219. package/src/components/Popover/PopoverLayers.stories.tsx +234 -0
  220. package/src/components/Popover/styles.css.ts +3 -2
  221. package/src/components/RadioGroup/RadioGroup.tsx +2 -1
  222. package/src/components/RadioGroup/styles.css.ts +8 -9
  223. package/src/components/ScrollArea/ScrollArea.meta.ts +2 -2
  224. package/src/components/ScrollArea/ScrollArea.stories.tsx +7 -5
  225. package/src/components/ScrollArea/ScrollArea.tsx +18 -7
  226. package/src/components/ScrollArea/styles.css.ts +10 -9
  227. package/src/components/Select/Select.meta.ts +6 -0
  228. package/src/components/Select/Select.tsx +8 -1
  229. package/src/components/Select/styles.css.ts +6 -4
  230. package/src/components/Select/useSelectRoot.ts +6 -2
  231. package/src/components/SideNav/styles.css.ts +10 -8
  232. package/src/components/Spinner/Spinner.tsx +2 -1
  233. package/src/components/Spinner/styles.css.ts +14 -14
  234. package/src/components/Switch/Switch.tsx +2 -1
  235. package/src/components/Switch/styles.css.ts +15 -15
  236. package/src/components/Table/ColumnFilter.tsx +5 -4
  237. package/src/components/Table/FromTanstack.tsx +2 -1
  238. package/src/components/Table/Pagination.tsx +6 -4
  239. package/src/components/Table/SortIndicator.tsx +4 -2
  240. package/src/components/Table/Table.stories.tsx +8 -8
  241. package/src/components/Table/Table.tsx +19 -15
  242. package/src/components/Table/styles.css.ts +9 -7
  243. package/src/components/Tabs/styles.css.ts +11 -9
  244. package/src/components/Tag/Tag.stories.tsx +4 -2
  245. package/src/components/Tag/styles.css.ts +6 -5
  246. package/src/components/TagGroup/TagGroup.tsx +2 -1
  247. package/src/components/TagGroup/styles.css.ts +6 -10
  248. package/src/components/Textarea/Textarea.stories.tsx +2 -1
  249. package/src/components/Textarea/styles.css.ts +4 -3
  250. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +7 -5
  251. package/src/components/Toast/Toast.stories.tsx +2 -1
  252. package/src/components/Toast/styles.css.ts +16 -14
  253. package/src/components/Toggle/Toggle.meta.ts +1 -1
  254. package/src/components/Toggle/Toggle.tsx +19 -2
  255. package/src/components/Toggle/styles.css.ts +18 -4
  256. package/src/components/ToggleGroup/ToggleGroup.meta.ts +11 -1
  257. package/src/components/ToggleGroup/ToggleGroup.stories.tsx +157 -0
  258. package/src/components/ToggleGroup/ToggleGroup.tsx +87 -10
  259. package/src/components/ToggleGroup/ToggleGroupContext.ts +6 -0
  260. package/src/components/ToggleGroup/styles.css.ts +32 -2
  261. package/src/components/ToggleGroup/useRovingFocus.ts +121 -0
  262. package/src/components/Tooltip/styles.css.ts +2 -1
  263. package/src/components/Tree/styles.css.ts +8 -6
  264. package/src/components/VirtualTable/VirtualTable.stories.tsx +4 -3
  265. package/src/components/VirtualTable/VirtualTable.tsx +5 -3
  266. package/src/components/VirtualTable/styles.css.ts +9 -8
  267. package/src/docs/Spacing.stories.tsx +11 -10
  268. package/src/docs/Typography.stories.tsx +8 -6
  269. package/src/docs/helpers.tsx +3 -2
  270. package/src/shared/length.ts +51 -0
  271. package/src/shared/length.typecheck.tsx +47 -0
  272. package/src/styles/visually-hidden.css.ts +16 -0
  273. package/dist/Table-JTgcR_Fh.js.map +0 -1
@@ -3,6 +3,8 @@ import {colors} from '@duro-app/tokens/tokens/colors.css'
3
3
  import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {typography} from '@duro-app/tokens/tokens/typography.css'
5
5
  import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
6
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
7
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
6
8
 
7
9
  export const styles = css.create({
8
10
  root: {
@@ -19,9 +21,9 @@ export const styles = css.create({
19
21
  cursor: 'not-allowed',
20
22
  },
21
23
  box: {
22
- width: 18,
23
- height: 18,
24
- borderWidth: 1,
24
+ width: sizes.indicator,
25
+ height: sizes.indicator,
26
+ borderWidth: borders.hairline,
25
27
  borderStyle: 'solid',
26
28
  borderRadius: radii.xs,
27
29
  display: 'inline-flex',
@@ -47,12 +49,12 @@ export const styles = css.create({
47
49
  // rotated 45° into a tick. Pure CSS (RSD translates the transform string to
48
50
  // an RN transform), so no SVG / react-native-svg weight reaches web.
49
51
  checkmark: {
50
- width: 5,
51
- height: 9,
52
- borderRightWidth: 2,
52
+ width: sizes.checkMarkW,
53
+ height: sizes.checkMarkH,
54
+ borderRightWidth: borders.strong,
53
55
  borderRightStyle: 'solid',
54
56
  borderRightColor: colors.accentContrast,
55
- borderBottomWidth: 2,
57
+ borderBottomWidth: borders.strong,
56
58
  borderBottomStyle: 'solid',
57
59
  borderBottomColor: colors.accentContrast,
58
60
  transform: 'rotate(45deg)',
@@ -77,12 +79,9 @@ export const styles = css.create({
77
79
  backgroundColor: 'transparent',
78
80
  padding: 0,
79
81
  },
82
+ // Layered on visuallyHidden.base: a native input is also made transparent.
80
83
  input: {
81
- position: 'absolute',
82
- width: 1,
83
- height: 1,
84
84
  opacity: 0,
85
- overflow: 'hidden',
86
85
  },
87
86
  // RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
88
87
  // native via `isNative` (on both .root and .box); web keeps inline-flex.
@@ -5,6 +5,7 @@ import {colors} from '@duro-app/tokens/tokens/colors.css'
5
5
  import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
6
6
  import {SPACING_KEYS} from '@duro-app/tokens/keys'
7
7
  import {typography} from '@duro-app/tokens/tokens/typography.css'
8
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
8
9
 
9
10
  const meta: Meta<typeof Cluster> = {
10
11
  title: 'Layout/Cluster',
@@ -41,7 +42,7 @@ const localStyles = css.create({
41
42
  whiteSpace: 'nowrap',
42
43
  },
43
44
  narrow: {
44
- maxWidth: 300,
45
+ maxWidth: sizes.gridColMd,
45
46
  },
46
47
  })
47
48
 
@@ -1,14 +1,16 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
- import {radii} from '@duro-app/tokens/tokens/spacing.css'
3
+ import {microSpacing, radii} from '@duro-app/tokens/tokens/spacing.css'
4
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
5
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
4
6
 
5
7
  export const styles = css.create({
6
8
  base: {
7
- width: 44,
8
- height: 34,
9
- padding: 2,
9
+ width: sizes.swatchW,
10
+ height: sizes.swatchH,
11
+ padding: microSpacing.px2,
10
12
  backgroundColor: colors.bg,
11
- borderWidth: 1,
13
+ borderWidth: borders.hairline,
12
14
  borderStyle: 'solid',
13
15
  borderColor: {
14
16
  default: colors.border,
@@ -18,7 +20,7 @@ export const styles = css.create({
18
20
  cursor: 'pointer',
19
21
  outlineWidth: {
20
22
  default: 0,
21
- ':focus-visible': 2,
23
+ ':focus-visible': borders.focusRing,
22
24
  },
23
25
  outlineStyle: {
24
26
  default: 'none',
@@ -28,7 +30,7 @@ export const styles = css.create({
28
30
  default: 'transparent',
29
31
  ':focus-visible': colors.accent,
30
32
  },
31
- outlineOffset: 1,
33
+ outlineOffset: borders.focusOffsetSm,
32
34
  },
33
35
  invalid: {
34
36
  borderColor: colors.error,
@@ -2,6 +2,7 @@ import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
3
  import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  button: {
@@ -9,7 +10,7 @@ export const styles = css.create({
9
10
  alignItems: 'center',
10
11
  justifyContent: 'center',
11
12
  padding: spacing.sm,
12
- borderWidth: 1,
13
+ borderWidth: borders.hairline,
13
14
  borderStyle: 'solid',
14
15
  borderColor: {
15
16
  default: colors.border,
@@ -25,9 +26,9 @@ export const styles = css.create({
25
26
  transitionProperty: 'background-color, border-color, color',
26
27
  transitionDuration: duration.fast,
27
28
  transitionTimingFunction: easing.standard,
28
- outlineWidth: {default: 0, ':focus-visible': 2},
29
+ outlineWidth: {default: 0, ':focus-visible': borders.focusRing},
29
30
  outlineStyle: 'solid',
30
31
  outlineColor: colors.accent,
31
- outlineOffset: 2,
32
+ outlineOffset: borders.focusOffset,
32
33
  },
33
34
  })
@@ -18,6 +18,12 @@ export const meta: ComponentMeta = {
18
18
  optional: ['Empty'],
19
19
  },
20
20
  relatedTo: [
21
+ {
22
+ component: 'Popover',
23
+ kind: 'composition',
24
+ relationship:
25
+ 'Inside Popover.Popup a Combobox keeps the popover open while you choose; Escape closes only the list',
26
+ },
21
27
  {
22
28
  component: 'Select',
23
29
  kind: 'contrast',
@@ -5,6 +5,7 @@ import {styles} from './styles.css'
5
5
  import {ComboboxContext, useCombobox} from './ComboboxContext'
6
6
  import {useComboboxRoot} from './useComboboxRoot'
7
7
  import {usePortalMount} from '../ThemeProvider/ThemeProvider'
8
+ import {usePopoverLayer} from '../Popover/PopoverLayerContext'
8
9
 
9
10
  // --- Root ---
10
11
  interface RootProps {
@@ -137,6 +138,7 @@ function Trigger({children}: {children?: ReactNode}) {
137
138
  function Popup({children}: {children: ReactNode}) {
138
139
  const {open, listboxId, rootRef} = useCombobox()
139
140
  const mount = usePortalMount()
141
+ const listboxRef = useRef<HTMLDivElement>(null)
140
142
  const [coords, setCoords] = useState<{top: number; left: number; width: number} | null>(null)
141
143
 
142
144
  // Measure the root each time the popup opens, and re-measure on scroll/resize
@@ -163,10 +165,13 @@ function Popup({children}: {children: ReactNode}) {
163
165
  }
164
166
  }, [open, rootRef])
165
167
 
168
+ usePopoverLayer(listboxRef, {active: open && coords !== null})
169
+
166
170
  if (!open || !coords) return null
167
171
 
168
172
  const node = (
169
173
  <html.div
174
+ ref={listboxRef}
170
175
  id={listboxId}
171
176
  role="listbox"
172
177
  style={[styles.popup, styles.popupPosition(coords.top, coords.left, coords.width)]}
@@ -4,6 +4,8 @@ import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {typography} from '@duro-app/tokens/tokens/typography.css'
5
5
  import {shadows} from '@duro-app/tokens/tokens/shadows.css'
6
6
  import {duration} from '@duro-app/tokens/tokens/motion.css'
7
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
8
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
7
9
 
8
10
  export const styles = css.create({
9
11
  root: {
@@ -17,7 +19,7 @@ export const styles = css.create({
17
19
  paddingLeft: spacing.md,
18
20
  paddingRight: spacing.xs,
19
21
  backgroundColor: colors.bgCard,
20
- borderWidth: 1,
22
+ borderWidth: borders.hairline,
21
23
  borderStyle: 'solid',
22
24
  borderColor: {
23
25
  default: colors.border,
@@ -71,14 +73,14 @@ export const styles = css.create({
71
73
  // ancestor with `overflow: hidden` or `transform` (e.g. inside a Dialog).
72
74
  position: 'fixed',
73
75
  backgroundColor: colors.bgCard,
74
- borderWidth: 1,
76
+ borderWidth: borders.hairline,
75
77
  borderStyle: 'solid',
76
78
  borderColor: colors.border,
77
79
  borderRadius: radii.sm,
78
80
  boxShadow: shadows.md,
79
81
  paddingTop: spacing.xs,
80
82
  paddingBottom: spacing.xs,
81
- maxHeight: 200,
83
+ maxHeight: sizes.listMaxHSm,
82
84
  overflowY: 'auto',
83
85
  zIndex: 1050,
84
86
  // Re-enable pointer events: the portal mount is pointer-events: none so
@@ -11,6 +11,8 @@ import {Inline} from '../Inline/Inline'
11
11
  import {Badge} from '../Badge/Badge'
12
12
  import {colors} from '@duro-app/tokens/tokens/colors.css'
13
13
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
14
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
15
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
14
16
 
15
17
  const meta: Meta = {
16
18
  title: 'Components/DetailPanel',
@@ -22,8 +24,8 @@ type Story = StoryObj
22
24
  const layoutStyles = css.create({
23
25
  container: {
24
26
  display: 'flex',
25
- height: 400,
26
- borderWidth: 1,
27
+ height: sizes.dialogSm,
28
+ borderWidth: borders.hairline,
27
29
  borderStyle: 'solid',
28
30
  borderColor: colors.border,
29
31
  },
@@ -117,7 +119,7 @@ const tableStyles = css.create({
117
119
  paddingBottom: spacing.sm,
118
120
  paddingLeft: spacing.md,
119
121
  paddingRight: spacing.md,
120
- borderBottomWidth: 1,
122
+ borderBottomWidth: borders.hairline,
121
123
  borderBottomStyle: 'solid',
122
124
  borderBottomColor: colors.border,
123
125
  },
@@ -17,7 +17,10 @@ import {styles} from './styles.css'
17
17
 
18
18
  const closeDurationMap = {
19
19
  instant: styles.closeDurationInstant,
20
+ minimal: styles.closeDurationMinimal,
21
+ quick: styles.closeDurationQuick,
20
22
  fast: styles.closeDurationFast,
23
+ brisk: styles.closeDurationBrisk,
21
24
  base: styles.closeDurationBase,
22
25
  slow: styles.closeDurationSlow,
23
26
  } as const satisfies Record<DurationToken, unknown>
@@ -1,8 +1,11 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
- import {spacing} from '@duro-app/tokens/tokens/spacing.css'
3
+ import {radii, spacing} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {shadows} from '@duro-app/tokens/tokens/shadows.css'
5
5
  import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
6
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
7
+ import {typography} from '@duro-app/tokens/tokens/typography.css'
8
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
6
9
 
7
10
  // The "Apple ease" curves and the 280ms open live in the shared motion tokens
8
11
  // (easing.easeOut/easeIn, duration.slow). The close is duration.base, and the
@@ -62,7 +65,7 @@ export const styles = css.create({
62
65
  display: 'flex',
63
66
  flexDirection: 'column',
64
67
  backgroundColor: colors.bgCard,
65
- borderLeftWidth: 1,
68
+ borderLeftWidth: borders.hairline,
66
69
  borderLeftStyle: 'solid',
67
70
  borderLeftColor: colors.border,
68
71
  boxShadow: shadows.sm,
@@ -70,8 +73,8 @@ export const styles = css.create({
70
73
  },
71
74
 
72
75
  // Content must maintain its target width even while wrapper is narrower
73
- contentSm: {width: 360},
74
- contentMd: {width: 480},
76
+ contentSm: {width: sizes.panelSm},
77
+ contentMd: {width: sizes.panelMd},
75
78
 
76
79
  // --- Content slide + fade animations ---
77
80
  slideIn: {
@@ -109,7 +112,10 @@ export const styles = css.create({
109
112
  // The closeAnimationDuration prop token drives both these and the unmount
110
113
  // timeout, so the exit animation can never race the unmount.
111
114
  closeDurationInstant: {animationDuration: duration.instant},
115
+ closeDurationMinimal: {animationDuration: duration.minimal},
116
+ closeDurationQuick: {animationDuration: duration.quick},
112
117
  closeDurationFast: {animationDuration: duration.fast},
118
+ closeDurationBrisk: {animationDuration: duration.brisk},
113
119
  closeDurationBase: {animationDuration: duration.base},
114
120
  closeDurationSlow: {animationDuration: duration.slow},
115
121
 
@@ -123,15 +129,15 @@ export const styles = css.create({
123
129
  paddingRight: spacing.lg,
124
130
  paddingBottom: spacing.lg,
125
131
  gap: spacing.md,
126
- borderBottomWidth: 1,
132
+ borderBottomWidth: borders.hairline,
127
133
  borderBottomStyle: 'solid',
128
134
  borderBottomColor: colors.border,
129
135
  },
130
136
 
131
137
  // --- Title ---
132
138
  title: {
133
- fontSize: 18,
134
- fontWeight: 600,
139
+ fontSize: typography.fontSizeLg,
140
+ fontWeight: typography.fontWeightSemibold,
135
141
  lineHeight: 1.4,
136
142
  color: colors.text,
137
143
  margin: 0,
@@ -166,7 +172,7 @@ export const styles = css.create({
166
172
  paddingBottom: spacing.md,
167
173
  paddingLeft: spacing.lg,
168
174
  paddingRight: spacing.lg,
169
- borderTopWidth: 1,
175
+ borderTopWidth: borders.hairline,
170
176
  borderTopStyle: 'solid',
171
177
  borderTopColor: colors.border,
172
178
  },
@@ -176,9 +182,9 @@ export const styles = css.create({
176
182
  display: 'flex',
177
183
  alignItems: 'center',
178
184
  justifyContent: 'center',
179
- width: 32,
180
- height: 32,
181
- borderRadius: 8,
185
+ width: sizes.iconButton,
186
+ height: sizes.iconButton,
187
+ borderRadius: radii.sm,
182
188
  borderWidth: 0,
183
189
  backgroundColor: {
184
190
  default: 'transparent',
@@ -12,6 +12,7 @@ import {Field} from '../Field/Field'
12
12
  import {Select} from '../Select/Select'
13
13
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
14
14
  import {colors} from '@duro-app/tokens/tokens/colors.css'
15
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
15
16
 
16
17
  const meta: Meta = {
17
18
  title: 'Components/Dialog',
@@ -334,7 +335,7 @@ const barStyles = css.create({
334
335
  bar: {
335
336
  transform: 'translateZ(0)',
336
337
  padding: spacing.sm,
337
- borderWidth: 1,
338
+ borderWidth: borders.hairline,
338
339
  borderStyle: 'solid',
339
340
  borderColor: colors.border,
340
341
  },
@@ -21,7 +21,10 @@ export type DialogSize = 'sm' | 'md' | 'lg'
21
21
 
22
22
  const closeDurationMap = {
23
23
  instant: styles.closeDurationInstant,
24
+ minimal: styles.closeDurationMinimal,
25
+ quick: styles.closeDurationQuick,
24
26
  fast: styles.closeDurationFast,
27
+ brisk: styles.closeDurationBrisk,
25
28
  base: styles.closeDurationBase,
26
29
  slow: styles.closeDurationSlow,
27
30
  } as const satisfies Record<DurationToken, unknown>
@@ -4,13 +4,15 @@ import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {typography} from '@duro-app/tokens/tokens/typography.css'
5
5
  import {shadows} from '@duro-app/tokens/tokens/shadows.css'
6
6
  import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
7
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
8
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
7
9
 
8
10
  export const styles = css.create({
9
11
  // --- Backdrop ---
10
12
  backdrop: {
11
13
  position: 'fixed',
12
14
  inset: 0,
13
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
15
+ backgroundColor: colors.scrim,
14
16
  zIndex: 1000,
15
17
  // Portaled into the ThemeProvider mount, which is pointer-events: none:
16
18
  // the backdrop must take clicks back (outside click dismisses).
@@ -62,7 +64,7 @@ export const styles = css.create({
62
64
  flexDirection: 'column',
63
65
  overflow: 'hidden',
64
66
  pointerEvents: 'auto',
65
- borderWidth: 1,
67
+ borderWidth: borders.hairline,
66
68
  borderStyle: 'solid',
67
69
  borderColor: colors.border,
68
70
  },
@@ -103,14 +105,17 @@ export const styles = css.create({
103
105
  // The closeAnimationDuration prop token drives both these and the unmount
104
106
  // timeout, so the exit animation can never race the unmount.
105
107
  closeDurationInstant: {animationDuration: duration.instant},
108
+ closeDurationMinimal: {animationDuration: duration.minimal},
109
+ closeDurationQuick: {animationDuration: duration.quick},
106
110
  closeDurationFast: {animationDuration: duration.fast},
111
+ closeDurationBrisk: {animationDuration: duration.brisk},
107
112
  closeDurationBase: {animationDuration: duration.base},
108
113
  closeDurationSlow: {animationDuration: duration.slow},
109
114
 
110
115
  // --- Sizes ---
111
- sm: {maxWidth: 400},
112
- md: {maxWidth: 520},
113
- lg: {maxWidth: 680},
116
+ sm: {maxWidth: sizes.dialogSm},
117
+ md: {maxWidth: sizes.dialogMd},
118
+ lg: {maxWidth: sizes.dialogLg},
114
119
 
115
120
  // --- Header ---
116
121
  header: {
@@ -163,7 +168,7 @@ export const styles = css.create({
163
168
  paddingLeft: spacing.lg,
164
169
  paddingRight: spacing.lg,
165
170
  paddingBottom: spacing.lg,
166
- borderTopWidth: 1,
171
+ borderTopWidth: borders.hairline,
167
172
  borderTopStyle: 'solid',
168
173
  borderTopColor: colors.border,
169
174
  },
@@ -173,8 +178,8 @@ export const styles = css.create({
173
178
  display: 'flex',
174
179
  alignItems: 'center',
175
180
  justifyContent: 'center',
176
- width: 32,
177
- height: 32,
181
+ width: sizes.iconButton,
182
+ height: sizes.iconButton,
178
183
  borderRadius: radii.sm,
179
184
  borderWidth: 0,
180
185
  backgroundColor: {
@@ -196,6 +201,6 @@ export const styles = css.create({
196
201
 
197
202
  // --- Reduced motion ---
198
203
  reducedMotion: {
199
- animationDuration: '1ms',
204
+ animationDuration: duration.minimal,
200
205
  },
201
206
  })
@@ -11,6 +11,7 @@ import {Tag} from '../Tag/Tag'
11
11
  import {Text} from '../Text/Text'
12
12
  import {colors} from '@duro-app/tokens/tokens/colors.css'
13
13
  import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
14
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
14
15
 
15
16
  const meta: Meta<typeof DragDrop.Root> = {
16
17
  title: 'Interaction/DragDrop',
@@ -24,7 +25,7 @@ const localStyles = css.create({
24
25
  zone: {
25
26
  padding: spacing.md,
26
27
  minHeight: spacing.xxl,
27
- borderWidth: 1,
28
+ borderWidth: borders.hairline,
28
29
  borderStyle: 'dashed',
29
30
  borderColor: colors.border,
30
31
  borderRadius: radii.sm,
@@ -11,6 +11,7 @@ import {
11
11
  import {html} from 'react-strict-dom'
12
12
  import {styles} from './styles.css'
13
13
  import {isNative} from '../../platform'
14
+ import {visuallyHidden} from '../../styles/visually-hidden.css'
14
15
 
15
16
  // ---------------------------------------------------------------------------
16
17
  // DragDrop — move items between zones with one pointer, on mouse, pen and
@@ -358,7 +359,7 @@ function Root<T = unknown>({onDrop, announce, children}: DragDropRootProps<T>) {
358
359
  {drag.preview}
359
360
  </html.div>
360
361
  )}
361
- <html.div role="status" aria-live="polite" aria-atomic style={styles.liveRegion}>
362
+ <html.div role="status" aria-live="polite" aria-atomic style={visuallyHidden.base}>
362
363
  {announcement}
363
364
  </html.div>
364
365
  </RootContext.Provider>
@@ -52,11 +52,4 @@ export const styles = css.create({
52
52
  height,
53
53
  transform: `translate3d(${x}px, ${y}px, 0)`,
54
54
  }),
55
- // Same visually-hidden recipe as TagGroup's live region.
56
- liveRegion: {
57
- position: 'absolute',
58
- width: 1,
59
- height: 1,
60
- overflow: 'hidden',
61
- },
62
55
  })
@@ -2,7 +2,7 @@ import type {ComponentMeta} from '../component-meta'
2
2
 
3
3
  export const meta: ComponentMeta = {
4
4
  description:
5
- 'Modal sliding panel from a screen edge (right, left, or bottom). Slides in with backdrop overlay. Supports swipe-to-dismiss gestures on mobile, backdrop click dismiss, and Escape key. Use for secondary workflows, settings panels, or mobile-friendly detail views.',
5
+ 'Modal sliding panel from a screen edge (right, left, or bottom). Slides in with backdrop overlay. Supports swipe-to-dismiss gestures on mobile, backdrop click dismiss, and Escape key. Swipe yields to an inner Duro ScrollArea: a drag there scrolls it, and dismisses only toward the edge from the scroll start (a native overflow:auto child is not covered — use ScrollArea). Use for secondary workflows, settings panels, or mobile-friendly detail views.',
6
6
  whenToUse: [
7
7
  'Settings or configuration panels that slide in from the side',
8
8
  'Mobile-friendly detail views (bottom sheet pattern)',
@@ -23,7 +23,10 @@ export type DrawerSize = 'sm' | 'md' | 'lg'
23
23
 
24
24
  const closeDurationMap = {
25
25
  instant: styles.closeDurationInstant,
26
+ minimal: styles.closeDurationMinimal,
27
+ quick: styles.closeDurationQuick,
26
28
  fast: styles.closeDurationFast,
29
+ brisk: styles.closeDurationBrisk,
27
30
  base: styles.closeDurationBase,
28
31
  slow: styles.closeDurationSlow,
29
32
  } as const satisfies Record<DurationToken, unknown>
@@ -233,6 +236,16 @@ function Portal({children, size = 'md'}: PortalProps) {
233
236
  panelRef,
234
237
  } = useDrawer()
235
238
  const mount = usePortalMount()
239
+ // The shown panel element, tracked as state so swipe listeners follow it
240
+ // when the portal mount arrives and the panel is remounted into it.
241
+ const [panel, setPanel] = useState<HTMLDivElement | null>(null)
242
+ const attachPanel = useCallback(
243
+ (el: HTMLDivElement | null) => {
244
+ panelRef.current = el
245
+ setPanel(el)
246
+ },
247
+ [panelRef],
248
+ )
236
249
 
237
250
  const handleBackdropClick = useCallback(() => {
238
251
  if (dismissable) {
@@ -245,7 +258,7 @@ function Portal({children, size = 'md'}: PortalProps) {
245
258
  anchor,
246
259
  enabled: swipeEnabled && open && !closing,
247
260
  onDismiss: requestCloseImmediate,
248
- panelRef,
261
+ panel,
249
262
  })
250
263
 
251
264
  if (!open) return null
@@ -269,7 +282,7 @@ function Portal({children, size = 'md'}: PortalProps) {
269
282
  {/* Viewport */}
270
283
  <html.div style={[styles.viewport, viewportAnchorMap[anchor]]} data-drawer-viewport="">
271
284
  <html.div
272
- ref={panelRef}
285
+ ref={attachPanel}
273
286
  role="dialog"
274
287
  aria-modal={true}
275
288
  aria-labelledby={titleId}