@duro-app/ui 4.5.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 (235) hide show
  1. package/dist/{Table-CUp12BKZ.js → Table-BKN_d-mp.js} +512 -419
  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/styles.css.d.ts +3 -3
  24. package/dist/components/Combobox/styles.css.d.ts.map +1 -1
  25. package/dist/components/DetailPanel/DetailPanel.d.ts.map +1 -1
  26. package/dist/components/DetailPanel/DetailPanel.stories.d.ts.map +1 -1
  27. package/dist/components/DetailPanel/styles.css.d.ts +19 -10
  28. package/dist/components/DetailPanel/styles.css.d.ts.map +1 -1
  29. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  30. package/dist/components/Dialog/Dialog.stories.d.ts.map +1 -1
  31. package/dist/components/Dialog/styles.css.d.ts +18 -9
  32. package/dist/components/Dialog/styles.css.d.ts.map +1 -1
  33. package/dist/components/DragDrop/DragDrop.d.ts.map +1 -1
  34. package/dist/components/DragDrop/DragDrop.stories.d.ts.map +1 -1
  35. package/dist/components/DragDrop/styles.css.d.ts +0 -6
  36. package/dist/components/DragDrop/styles.css.d.ts.map +1 -1
  37. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  38. package/dist/components/Drawer/styles.css.d.ts +19 -10
  39. package/dist/components/Drawer/styles.css.d.ts.map +1 -1
  40. package/dist/components/Field/Field.stories.d.ts.map +1 -1
  41. package/dist/components/Field/styles.css.d.ts +1 -1
  42. package/dist/components/Field/styles.css.d.ts.map +1 -1
  43. package/dist/components/Form/Form.stories.d.ts.map +1 -1
  44. package/dist/components/Grid/Grid.d.ts +6 -4
  45. package/dist/components/Grid/Grid.d.ts.map +1 -1
  46. package/dist/components/Grid/Grid.stories.d.ts.map +1 -1
  47. package/dist/components/Grid/styles.css.d.ts +3 -3
  48. package/dist/components/Input/Input.stories.d.ts.map +1 -1
  49. package/dist/components/Input/styles.css.d.ts +3 -3
  50. package/dist/components/Input/styles.css.d.ts.map +1 -1
  51. package/dist/components/InputGroup/InputGroup.d.ts +4 -2
  52. package/dist/components/InputGroup/InputGroup.d.ts.map +1 -1
  53. package/dist/components/InputGroup/InputGroup.stories.d.ts.map +1 -1
  54. package/dist/components/InputGroup/styles.css.d.ts +3 -3
  55. package/dist/components/InputGroup/styles.css.d.ts.map +1 -1
  56. package/dist/components/LinkButton/styles.css.d.ts +1 -1
  57. package/dist/components/LinkButton/styles.css.d.ts.map +1 -1
  58. package/dist/components/List/List.stories.d.ts.map +1 -1
  59. package/dist/components/List/styles.css.d.ts +3 -3
  60. package/dist/components/List/styles.css.d.ts.map +1 -1
  61. package/dist/components/Menu/styles.css.d.ts +4 -4
  62. package/dist/components/Menu/styles.css.d.ts.map +1 -1
  63. package/dist/components/PageShell/styles.css.d.ts +3 -3
  64. package/dist/components/PageShell/styles.css.d.ts.map +1 -1
  65. package/dist/components/Panel/styles.css.d.ts +3 -3
  66. package/dist/components/Panel/styles.css.d.ts.map +1 -1
  67. package/dist/components/Popover/Popover.stories.d.ts.map +1 -1
  68. package/dist/components/Popover/styles.css.d.ts +2 -2
  69. package/dist/components/Popover/styles.css.d.ts.map +1 -1
  70. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  71. package/dist/components/RadioGroup/styles.css.d.ts +5 -9
  72. package/dist/components/RadioGroup/styles.css.d.ts.map +1 -1
  73. package/dist/components/ScrollArea/ScrollArea.d.ts +2 -1
  74. package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  75. package/dist/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  76. package/dist/components/ScrollArea/styles.css.d.ts +8 -8
  77. package/dist/components/ScrollArea/styles.css.d.ts.map +1 -1
  78. package/dist/components/Select/styles.css.d.ts +4 -4
  79. package/dist/components/Select/styles.css.d.ts.map +1 -1
  80. package/dist/components/SideNav/styles.css.d.ts +7 -7
  81. package/dist/components/SideNav/styles.css.d.ts.map +1 -1
  82. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  83. package/dist/components/Spinner/styles.css.d.ts +10 -14
  84. package/dist/components/Spinner/styles.css.d.ts.map +1 -1
  85. package/dist/components/Switch/Switch.d.ts.map +1 -1
  86. package/dist/components/Switch/styles.css.d.ts +10 -14
  87. package/dist/components/Switch/styles.css.d.ts.map +1 -1
  88. package/dist/components/Table/ColumnFilter.d.ts.map +1 -1
  89. package/dist/components/Table/FromTanstack.d.ts +2 -1
  90. package/dist/components/Table/FromTanstack.d.ts.map +1 -1
  91. package/dist/components/Table/Pagination.d.ts.map +1 -1
  92. package/dist/components/Table/SortIndicator.d.ts.map +1 -1
  93. package/dist/components/Table/Table.d.ts +11 -9
  94. package/dist/components/Table/Table.d.ts.map +1 -1
  95. package/dist/components/Table/Table.stories.d.ts.map +1 -1
  96. package/dist/components/Table/styles.css.d.ts +6 -6
  97. package/dist/components/Table/styles.css.d.ts.map +1 -1
  98. package/dist/components/Tabs/styles.css.d.ts +8 -8
  99. package/dist/components/Tabs/styles.css.d.ts.map +1 -1
  100. package/dist/components/Tag/Tag.stories.d.ts.map +1 -1
  101. package/dist/components/Tag/styles.css.d.ts +4 -4
  102. package/dist/components/Tag/styles.css.d.ts.map +1 -1
  103. package/dist/components/TagGroup/TagGroup.d.ts.map +1 -1
  104. package/dist/components/TagGroup/styles.css.d.ts +4 -10
  105. package/dist/components/TagGroup/styles.css.d.ts.map +1 -1
  106. package/dist/components/Textarea/Textarea.stories.d.ts.map +1 -1
  107. package/dist/components/Textarea/styles.css.d.ts +3 -3
  108. package/dist/components/Textarea/styles.css.d.ts.map +1 -1
  109. package/dist/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  110. package/dist/components/Toast/Toast.stories.d.ts.map +1 -1
  111. package/dist/components/Toast/styles.css.d.ts +12 -12
  112. package/dist/components/Toast/styles.css.d.ts.map +1 -1
  113. package/dist/components/Toggle/styles.css.d.ts +8 -8
  114. package/dist/components/Toggle/styles.css.d.ts.map +1 -1
  115. package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts.map +1 -1
  116. package/dist/components/ToggleGroup/styles.css.d.ts +1 -1
  117. package/dist/components/ToggleGroup/styles.css.d.ts.map +1 -1
  118. package/dist/components/Tooltip/styles.css.d.ts +1 -1
  119. package/dist/components/Tooltip/styles.css.d.ts.map +1 -1
  120. package/dist/components/Tree/styles.css.d.ts +4 -4
  121. package/dist/components/Tree/styles.css.d.ts.map +1 -1
  122. package/dist/components/VirtualTable/VirtualTable.d.ts +2 -1
  123. package/dist/components/VirtualTable/VirtualTable.d.ts.map +1 -1
  124. package/dist/components/VirtualTable/VirtualTable.stories.d.ts.map +1 -1
  125. package/dist/components/VirtualTable/styles.css.d.ts +7 -7
  126. package/dist/components/VirtualTable/styles.css.d.ts.map +1 -1
  127. package/dist/docs/Spacing.stories.d.ts.map +1 -1
  128. package/dist/docs/Typography.stories.d.ts.map +1 -1
  129. package/dist/docs/helpers.d.ts.map +1 -1
  130. package/dist/index.css +1 -1
  131. package/dist/index.js +2790 -2785
  132. package/dist/index.js.map +1 -1
  133. package/dist/shared/length.d.ts +24 -0
  134. package/dist/shared/length.d.ts.map +1 -0
  135. package/dist/shared/length.typecheck.d.ts +28 -0
  136. package/dist/shared/length.typecheck.d.ts.map +1 -0
  137. package/dist/styles/visually-hidden.css.d.ts +10 -0
  138. package/dist/styles/visually-hidden.css.d.ts.map +1 -0
  139. package/dist/table.js +166 -166
  140. package/dist/table.js.map +1 -1
  141. package/package.json +2 -2
  142. package/src/components/ActionBar/ActionBar.stories.tsx +4 -2
  143. package/src/components/ActionBar/styles.css.ts +11 -9
  144. package/src/components/Alert/styles.css.ts +4 -3
  145. package/src/components/Badge/styles.css.ts +3 -3
  146. package/src/components/Button/styles.css.ts +8 -7
  147. package/src/components/Callout/styles.css.ts +2 -1
  148. package/src/components/Card/styles.css.ts +4 -3
  149. package/src/components/Checkbox/Checkbox.tsx +2 -1
  150. package/src/components/Checkbox/styles.css.ts +10 -11
  151. package/src/components/Cluster/Cluster.stories.tsx +2 -1
  152. package/src/components/ColorInput/styles.css.ts +9 -7
  153. package/src/components/ColorMode/styles.css.ts +4 -3
  154. package/src/components/Combobox/styles.css.ts +5 -3
  155. package/src/components/DetailPanel/DetailPanel.stories.tsx +5 -3
  156. package/src/components/DetailPanel/DetailPanel.tsx +3 -0
  157. package/src/components/DetailPanel/styles.css.ts +17 -11
  158. package/src/components/Dialog/Dialog.stories.tsx +2 -1
  159. package/src/components/Dialog/Dialog.tsx +3 -0
  160. package/src/components/Dialog/styles.css.ts +14 -9
  161. package/src/components/DragDrop/DragDrop.stories.tsx +2 -1
  162. package/src/components/DragDrop/DragDrop.tsx +2 -1
  163. package/src/components/DragDrop/styles.css.ts +0 -7
  164. package/src/components/Drawer/Drawer.tsx +3 -0
  165. package/src/components/Drawer/DrawerScroll.stories.tsx +5 -5
  166. package/src/components/Drawer/styles.css.ts +15 -10
  167. package/src/components/Field/Field.stories.tsx +3 -2
  168. package/src/components/Field/styles.css.ts +2 -1
  169. package/src/components/Form/Form.stories.tsx +4 -3
  170. package/src/components/Grid/Grid.meta.ts +2 -2
  171. package/src/components/Grid/Grid.stories.tsx +3 -2
  172. package/src/components/Grid/Grid.tsx +8 -6
  173. package/src/components/Grid/styles.css.ts +2 -2
  174. package/src/components/Input/Input.stories.tsx +2 -1
  175. package/src/components/Input/styles.css.ts +4 -3
  176. package/src/components/InputGroup/InputGroup.stories.tsx +3 -2
  177. package/src/components/InputGroup/InputGroup.tsx +5 -3
  178. package/src/components/InputGroup/styles.css.ts +4 -3
  179. package/src/components/LinkButton/styles.css.ts +2 -1
  180. package/src/components/List/List.stories.tsx +4 -2
  181. package/src/components/List/styles.css.ts +6 -4
  182. package/src/components/Menu/styles.css.ts +6 -4
  183. package/src/components/PageShell/styles.css.ts +4 -3
  184. package/src/components/Panel/styles.css.ts +4 -3
  185. package/src/components/Popover/Popover.stories.tsx +6 -4
  186. package/src/components/Popover/styles.css.ts +3 -2
  187. package/src/components/RadioGroup/RadioGroup.tsx +2 -1
  188. package/src/components/RadioGroup/styles.css.ts +8 -9
  189. package/src/components/ScrollArea/ScrollArea.meta.ts +1 -1
  190. package/src/components/ScrollArea/ScrollArea.stories.tsx +7 -5
  191. package/src/components/ScrollArea/ScrollArea.tsx +7 -2
  192. package/src/components/ScrollArea/styles.css.ts +10 -9
  193. package/src/components/Select/styles.css.ts +6 -4
  194. package/src/components/SideNav/styles.css.ts +10 -8
  195. package/src/components/Spinner/Spinner.tsx +2 -1
  196. package/src/components/Spinner/styles.css.ts +14 -14
  197. package/src/components/Switch/Switch.tsx +2 -1
  198. package/src/components/Switch/styles.css.ts +15 -15
  199. package/src/components/Table/ColumnFilter.tsx +5 -4
  200. package/src/components/Table/FromTanstack.tsx +2 -1
  201. package/src/components/Table/Pagination.tsx +6 -4
  202. package/src/components/Table/SortIndicator.tsx +4 -2
  203. package/src/components/Table/Table.stories.tsx +8 -8
  204. package/src/components/Table/Table.tsx +19 -15
  205. package/src/components/Table/styles.css.ts +9 -7
  206. package/src/components/Tabs/styles.css.ts +11 -9
  207. package/src/components/Tag/Tag.stories.tsx +4 -2
  208. package/src/components/Tag/styles.css.ts +6 -5
  209. package/src/components/TagGroup/TagGroup.tsx +2 -1
  210. package/src/components/TagGroup/styles.css.ts +6 -10
  211. package/src/components/Textarea/Textarea.stories.tsx +2 -1
  212. package/src/components/Textarea/styles.css.ts +4 -3
  213. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +7 -5
  214. package/src/components/Toast/Toast.stories.tsx +2 -1
  215. package/src/components/Toast/styles.css.ts +16 -14
  216. package/src/components/Toggle/Toggle.meta.ts +1 -1
  217. package/src/components/Toggle/styles.css.ts +12 -10
  218. package/src/components/ToggleGroup/ToggleGroup.meta.ts +1 -1
  219. package/src/components/ToggleGroup/ToggleGroup.stories.tsx +7 -6
  220. package/src/components/ToggleGroup/styles.css.ts +7 -6
  221. package/src/components/Tooltip/styles.css.ts +2 -1
  222. package/src/components/Tree/styles.css.ts +8 -6
  223. package/src/components/VirtualTable/VirtualTable.stories.tsx +4 -3
  224. package/src/components/VirtualTable/VirtualTable.tsx +5 -3
  225. package/src/components/VirtualTable/styles.css.ts +9 -8
  226. package/src/docs/Spacing.stories.tsx +11 -10
  227. package/src/docs/Typography.stories.tsx +8 -6
  228. package/src/docs/helpers.tsx +3 -2
  229. package/src/shared/length.ts +51 -0
  230. package/src/shared/length.typecheck.tsx +47 -0
  231. package/src/styles/visually-hidden.css.ts +16 -0
  232. package/dist/Table-CUp12BKZ.js.map +0 -1
  233. package/dist/components/Toggle/rowHeight.d.ts +0 -17
  234. package/dist/components/Toggle/rowHeight.d.ts.map +0 -1
  235. package/src/components/Toggle/rowHeight.ts +0 -12
@@ -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: {
@@ -23,7 +25,7 @@ export const styles = css.create({
23
25
  fontSize: typography.fontSizeSm,
24
26
  color: colors.text,
25
27
  backgroundColor: colors.bgCard,
26
- borderWidth: 1,
28
+ borderWidth: borders.hairline,
27
29
  borderStyle: 'solid',
28
30
  borderColor: {
29
31
  default: colors.border,
@@ -64,15 +66,15 @@ export const styles = css.create({
64
66
  // ancestor with `overflow: hidden` / `transform` (notably inside a Dialog).
65
67
  position: 'fixed',
66
68
  backgroundColor: colors.bgCard,
67
- borderWidth: 1,
69
+ borderWidth: borders.hairline,
68
70
  borderStyle: 'solid',
69
71
  borderColor: colors.border,
70
72
  borderRadius: radii.sm,
71
73
  boxShadow: shadows.md,
72
74
  paddingTop: spacing.xs,
73
75
  paddingBottom: spacing.xs,
74
- minWidth: 120,
75
- maxHeight: 280,
76
+ minWidth: sizes.labelMinW,
77
+ maxHeight: sizes.listMaxH,
76
78
  overflowY: 'auto',
77
79
  zIndex: 1050,
78
80
  // Re-enable pointer events: the portal mount is pointer-events: none.
@@ -1,8 +1,10 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
- import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
3
+ import {microSpacing, radii, spacing} 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: {
@@ -80,8 +82,8 @@ export const styles = css.create({
80
82
  display: 'flex',
81
83
  alignItems: 'center',
82
84
  gap: spacing.sm,
83
- paddingTop: '6px',
84
- paddingBottom: '6px',
85
+ paddingTop: microSpacing.px6,
86
+ paddingBottom: microSpacing.px6,
85
87
  paddingLeft: spacing.md,
86
88
  paddingRight: spacing.md,
87
89
  fontFamily: typography.fontFamily,
@@ -104,7 +106,7 @@ export const styles = css.create({
104
106
  textAlign: 'left' as const,
105
107
  outlineWidth: {
106
108
  default: 0,
107
- ':focus-visible': 2,
109
+ ':focus-visible': borders.focusRing,
108
110
  },
109
111
  outlineStyle: {
110
112
  default: 'none',
@@ -125,7 +127,7 @@ export const styles = css.create({
125
127
  position: 'absolute',
126
128
  left: 0,
127
129
  top: '50%',
128
- width: '3px',
130
+ width: sizes.navMarkerW,
129
131
  height: 0,
130
132
  transform: 'translateY(-50%)',
131
133
  borderTopRightRadius: radii.full,
@@ -136,15 +138,15 @@ export const styles = css.create({
136
138
  transitionTimingFunction: easing.standard,
137
139
  },
138
140
  markerActive: {
139
- height: '18px',
141
+ height: sizes.navMarkerH,
140
142
  },
141
143
  itemIcon: {
142
144
  display: 'inline-flex',
143
145
  alignItems: 'center',
144
146
  justifyContent: 'center',
145
147
  flexShrink: 0,
146
- width: '18px',
147
- height: '18px',
148
+ width: sizes.indicator,
149
+ height: sizes.indicator,
148
150
  },
149
151
  itemLabel: {
150
152
  flexGrow: 1,
@@ -1,5 +1,6 @@
1
1
  import {html} from 'react-strict-dom'
2
2
  import {styles} from './styles.css'
3
+ import {visuallyHidden} from '../../styles/visually-hidden.css'
3
4
 
4
5
  export type SpinnerSize = 'sm' | 'md' | 'lg'
5
6
 
@@ -18,7 +19,7 @@ export function Spinner({size = 'md', label = 'Loading'}: SpinnerProps) {
18
19
  return (
19
20
  <html.div role="status" style={styles.root}>
20
21
  <html.div style={[styles.spinner, sizeMap[size]]} aria-hidden />
21
- <html.span style={styles.srOnly}>{label}</html.span>
22
+ <html.span style={[visuallyHidden.base, styles.srOnly]}>{label}</html.span>
22
23
  </html.div>
23
24
  )
24
25
  }
@@ -1,5 +1,8 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
4
+ import {easing} from '@duro-app/tokens/tokens/motion.css'
5
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
3
6
 
4
7
  const spin = css.keyframes({
5
8
  '0%': {transform: 'rotate(0deg)'},
@@ -19,29 +22,26 @@ export const styles = css.create({
19
22
  borderTopColor: colors.accent,
20
23
  animationName: spin,
21
24
  animationDuration: '0.6s',
22
- animationTimingFunction: 'linear',
25
+ animationTimingFunction: easing.linear,
23
26
  animationIterationCount: 'infinite',
24
27
  },
25
28
  sm: {
26
- width: 16,
27
- height: 16,
28
- borderWidth: 2,
29
+ width: sizes.spinnerSm,
30
+ height: sizes.spinnerSm,
31
+ borderWidth: borders.strong,
29
32
  },
30
33
  md: {
31
- width: 24,
32
- height: 24,
33
- borderWidth: 2,
34
+ width: sizes.spinnerMd,
35
+ height: sizes.spinnerMd,
36
+ borderWidth: borders.strong,
34
37
  },
35
38
  lg: {
36
- width: 40,
37
- height: 40,
38
- borderWidth: 3,
39
+ width: sizes.spinnerLg,
40
+ height: sizes.spinnerLg,
41
+ borderWidth: borders.accent,
39
42
  },
43
+ // Layered on visuallyHidden.base.
40
44
  srOnly: {
41
- position: 'absolute',
42
- width: 1,
43
- height: 1,
44
- overflow: 'hidden',
45
45
  clip: 'rect(0, 0, 0, 0)',
46
46
  },
47
47
  })
@@ -3,6 +3,7 @@ import {html} from 'react-strict-dom'
3
3
  import {isNative} from '../../platform'
4
4
  import {useControllableValue} from '../../hooks/useControllableValue'
5
5
  import {styles} from './styles.css'
6
+ import {visuallyHidden} from '../../styles/visually-hidden.css'
6
7
 
7
8
  interface SwitchProps {
8
9
  /** Controlled checked state. */
@@ -67,7 +68,7 @@ export function Switch({
67
68
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
68
69
  onCheckedChange?.(e.target.checked)
69
70
  }}
70
- style={styles.input}
71
+ style={[visuallyHidden.base, styles.input]}
71
72
  />
72
73
  )}
73
74
  <html.button
@@ -1,8 +1,10 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
- import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
3
+ import {microSpacing, radii, spacing} 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: {
@@ -20,8 +22,8 @@ export const styles = css.create({
20
22
  },
21
23
  track: {
22
24
  position: 'relative',
23
- width: 36,
24
- height: 20,
25
+ width: sizes.switchTrackW,
26
+ height: sizes.switchTrackH,
25
27
  borderRadius: radii.full,
26
28
  borderWidth: 0,
27
29
  padding: 0,
@@ -29,10 +31,10 @@ export const styles = css.create({
29
31
  transitionProperty: 'background-color',
30
32
  transitionDuration: duration.fast,
31
33
  transitionTimingFunction: easing.standard,
32
- outlineWidth: {default: 0, ':focus-visible': 2},
34
+ outlineWidth: {default: 0, ':focus-visible': borders.focusRing},
33
35
  outlineStyle: 'solid',
34
36
  outlineColor: colors.accent,
35
- outlineOffset: 2,
37
+ outlineOffset: borders.focusOffset,
36
38
  flexShrink: 0,
37
39
  },
38
40
  trackUnchecked: {
@@ -49,25 +51,23 @@ export const styles = css.create({
49
51
  },
50
52
  thumb: {
51
53
  position: 'absolute',
52
- top: 2,
53
- left: 2,
54
- width: 16,
55
- height: 16,
54
+ top: microSpacing.px2,
55
+ left: microSpacing.px2,
56
+ width: sizes.switchThumb,
57
+ height: sizes.switchThumb,
56
58
  borderRadius: radii.full,
57
- backgroundColor: '#fff',
59
+ backgroundColor: colors.fixedLight,
58
60
  transitionProperty: 'transform',
59
61
  transitionDuration: duration.fast,
60
62
  transitionTimingFunction: easing.standard,
61
63
  },
62
64
  thumbChecked: {
63
- transform: 'translateX(16px)',
65
+ // Travel: the track less the thumb and both insets.
66
+ transform: `translateX(calc(${sizes.switchTrackW} - ${sizes.switchThumb} - 2 * ${microSpacing.px2}))`,
64
67
  },
68
+ // Layered on visuallyHidden.base: a native input is also made transparent.
65
69
  input: {
66
- position: 'absolute',
67
- width: 1,
68
- height: 1,
69
70
  opacity: 0,
70
- overflow: 'hidden',
71
71
  },
72
72
  // RSD-native only honors display:'flex' (not 'inline-flex'). Layered on
73
73
  // native via `isNative` so the flex container applies; web keeps inline-flex.
@@ -2,18 +2,19 @@ import type {Column} from '@tanstack/react-table'
2
2
  import {html} from 'react-strict-dom'
3
3
  import {css} from 'react-strict-dom'
4
4
  import {colors} from '@duro-app/tokens/tokens/colors.css'
5
- import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
5
+ import {microSpacing, radii, spacing} from '@duro-app/tokens/tokens/spacing.css'
6
6
  import {typography} from '@duro-app/tokens/tokens/typography.css'
7
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
7
8
 
8
9
  const styles = css.create({
9
10
  input: {
10
11
  width: '100%',
11
- paddingTop: 2,
12
- paddingBottom: 2,
12
+ paddingTop: microSpacing.px2,
13
+ paddingBottom: microSpacing.px2,
13
14
  paddingLeft: spacing.xs,
14
15
  paddingRight: spacing.xs,
15
16
  marginTop: spacing.xs,
16
- borderWidth: 1,
17
+ borderWidth: borders.hairline,
17
18
  borderStyle: 'solid',
18
19
  borderColor: colors.border,
19
20
  borderRadius: radii.xs,
@@ -12,6 +12,7 @@ import {
12
12
  } from './Table'
13
13
  import {Pagination} from './Pagination'
14
14
  import {SortChip, type SortValue} from './SortChip'
15
+ import type {Length} from '../../shared/length'
15
16
 
16
17
  // ColumnMeta is augmented in `./tanstack-augmentation` so the types
17
18
  // register independently of whether the consumer imports FromTanstack.
@@ -24,7 +25,7 @@ interface FromTanstackBaseProps<TData> {
24
25
  readonly responsive?: boolean
25
26
  /** Min width (px) each flexible column keeps before the table scrolls
26
27
  * horizontally. Forwarded to Table.Root — see its `minColumnWidth`. */
27
- readonly minColumnWidth?: number
28
+ readonly minColumnWidth?: Length
28
29
  /** Render a SortChip above the grid (stack-mode only). Options derive from
29
30
  * columns where `column.getCanSort()` returns true. Wires value/onChange
30
31
  * through the TanStack sorting state automatically. */
@@ -1,9 +1,11 @@
1
1
  import type {Table} from '@tanstack/react-table'
2
2
  import {html} from 'react-strict-dom'
3
3
  import {css} from 'react-strict-dom'
4
- import {spacing} from '@duro-app/tokens/tokens/spacing.css'
4
+ import {radii, spacing} from '@duro-app/tokens/tokens/spacing.css'
5
5
  import {colors} from '@duro-app/tokens/tokens/colors.css'
6
6
  import {typography} from '@duro-app/tokens/tokens/typography.css'
7
+ import {duration} from '@duro-app/tokens/tokens/motion.css'
8
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
7
9
 
8
10
  const styles = css.create({
9
11
  root: {
@@ -22,10 +24,10 @@ const styles = css.create({
22
24
  paddingBottom: spacing.xs,
23
25
  paddingLeft: spacing.sm,
24
26
  paddingRight: spacing.sm,
25
- borderWidth: 1,
27
+ borderWidth: borders.hairline,
26
28
  borderStyle: 'solid',
27
29
  borderColor: colors.border,
28
- borderRadius: 6,
30
+ borderRadius: radii.px6,
29
31
  backgroundColor: {
30
32
  default: 'transparent',
31
33
  ':hover': colors.bgCardHover,
@@ -34,7 +36,7 @@ const styles = css.create({
34
36
  fontSize: typography.fontSizeSm,
35
37
  cursor: 'pointer',
36
38
  transitionProperty: 'background-color',
37
- transitionDuration: '150ms',
39
+ transitionDuration: duration.fast,
38
40
  },
39
41
  buttonDisabled: {
40
42
  opacity: 0.4,
@@ -2,18 +2,20 @@ import type {Column} from '@tanstack/react-table'
2
2
  import {html} from 'react-strict-dom'
3
3
  import {css} from 'react-strict-dom'
4
4
  import {colors} from '@duro-app/tokens/tokens/colors.css'
5
+ import {duration} from '@duro-app/tokens/tokens/motion.css'
6
+ import {spacing} from '@duro-app/tokens/tokens/spacing.css'
5
7
 
6
8
  const styles = css.create({
7
9
  root: {
8
10
  display: 'inline-flex',
9
11
  alignItems: 'center',
10
- marginLeft: 4,
12
+ marginLeft: spacing.xs,
11
13
  fontSize: 10,
12
14
  userSelect: 'none',
13
15
  // Hidden by default, shown on hover or when active
14
16
  opacity: 0,
15
17
  transitionProperty: 'opacity',
16
- transitionDuration: '120ms',
18
+ transitionDuration: duration.quick,
17
19
  },
18
20
  active: {
19
21
  opacity: 1,
@@ -22,12 +22,13 @@ import {
22
22
  getPaginationRowModel,
23
23
  type SortingState,
24
24
  type ColumnFiltersState,
25
- type PaginationState,
26
25
  } from '@tanstack/react-table'
27
26
  import {useDataTable} from './useDataTable'
28
27
  import {Combobox} from '../Combobox/Combobox'
29
28
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
30
29
  import {typography} from '@duro-app/tokens/tokens/typography.css'
30
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
31
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
31
32
 
32
33
  const meta: Meta = {
33
34
  title: 'Components/Table',
@@ -247,7 +248,6 @@ function CheckboxTableDemo() {
247
248
  const [selected, setSelected] = useState<Set<string>>(new Set())
248
249
 
249
250
  const allSelected = items.length > 0 && items.every((i) => selected.has(i.id))
250
- const someSelected = items.some((i) => selected.has(i.id))
251
251
 
252
252
  const toggleAll = () => {
253
253
  if (allSelected) {
@@ -893,11 +893,11 @@ const responsiveStyles = css.create({
893
893
  resizable: {
894
894
  resize: 'horizontal',
895
895
  overflow: 'auto',
896
- minWidth: '320px',
896
+ minWidth: sizes.panelSm,
897
897
  maxWidth: '100%',
898
- width: '900px',
898
+ width: sizes.pageMd,
899
899
  padding: spacing.sm,
900
- borderWidth: 1,
900
+ borderWidth: borders.hairline,
901
901
  borderStyle: 'dashed',
902
902
  borderColor: colors.border,
903
903
  },
@@ -1149,11 +1149,11 @@ export const SlotPropsOnRoot: Story = {
1149
1149
  const respStyles = css.create({
1150
1150
  // 8 columns × 120px floor = 960px min. At 800px the grid overflows → the
1151
1151
  // wrapper scrolls sideways, but it's still tabular (above 640).
1152
- scrollDense: {width: 800},
1152
+ scrollDense: {width: sizes.pageMd},
1153
1153
  // Same table at 1120px: 960 < 1120, so it fits with no scrollbar.
1154
- roomy: {width: 1120},
1154
+ roomy: {width: sizes.pageLg},
1155
1155
  // Below the 640px card breakpoint → cards.
1156
- phone: {width: 560},
1156
+ phone: {width: sizes.pageSm},
1157
1157
  })
1158
1158
 
1159
1159
  const LONG_EMAIL = 'a-really-long-service-account.address@subdomain.example-company.com'
@@ -13,6 +13,7 @@ import {
13
13
  import {html} from 'react-strict-dom'
14
14
  import {styles} from './styles.css'
15
15
  import {devWarnOnce} from '../../shared/devWarnOnce'
16
+ import {resolveLength, resolveTrack, type GridTrack, type Length} from '../../shared/length'
16
17
 
17
18
  // --- Types ---
18
19
 
@@ -95,7 +96,7 @@ function unwrapElementType(t: unknown): unknown {
95
96
 
96
97
  function extractColumnMeta(
97
98
  children: ReactNode,
98
- minColumnWidth: number,
99
+ minColumnWidth: Length,
99
100
  ): {
100
101
  template: string
101
102
  compactTemplate: string
@@ -120,15 +121,17 @@ function extractColumnMeta(
120
121
  // That floor is what makes a dense table overflow its container
121
122
  // instead of crushing — Root's scroll wrapper then scrolls sideways.
122
123
  // Narrow columns (a checkbox) or naturally-wide ones (an actions
123
- // cell) override this with an explicit `width` (e.g. '40px',
124
- // 'max-content').
125
- const width = props.width || `minmax(${minColumnWidth}px, 1fr)`
124
+ // cell) override this with an explicit `width` (e.g. a size token
125
+ // key, 'max-content').
126
+ const width = props.width
127
+ ? String(resolveTrack(props.width))
128
+ : `minmax(${resolveLength(minColumnWidth)}, 1fr)`
126
129
  widths.push(width)
127
130
  // `compactWidth` lets the consumer switch to a content-aware
128
131
  // layout in the compact band while staying evenly distributed
129
132
  // at desktop. Falls back to `width` so columns that don't opt
130
133
  // in keep one template across both breakpoints.
131
- compactWidths.push(props.compactWidth || width)
134
+ compactWidths.push(props.compactWidth ? String(resolveTrack(props.compactWidth)) : width)
132
135
  const explicit = typeof props.label === 'string' ? props.label : undefined
133
136
  const fallback = extractText(props.children).trim()
134
137
  const label = explicit ?? fallback
@@ -214,13 +217,14 @@ interface RootProps {
214
217
  /** Opt out of responsive behavior (horizontal scroll + card breakpoint). Default true. */
215
218
  responsive?: boolean
216
219
  /**
217
- * Minimum width (px) each flexible column keeps before the table scrolls
218
- * horizontally rather than crushing its cells. Columns still share the row
219
- * evenly (`minmax(<minColumnWidth>px, 1fr)`); this is only the floor. Raise
220
- * it for roomier columns (more scrolling), lower it to fit more before
221
- * scrolling. Columns with an explicit `width` are unaffected. Default 120.
220
+ * Minimum width each flexible column keeps before the table scrolls
221
+ * horizontally rather than crushing its cells: a size token key or a
222
+ * relative length. Columns still share the row evenly
223
+ * (`minmax(<minColumnWidth>, 1fr)`); this is only the floor. Raise it for
224
+ * roomier columns (more scrolling), lower it to fit more before scrolling.
225
+ * Columns with an explicit `width` are unaffected. Default `"labelMinW"`.
222
226
  */
223
- minColumnWidth?: number
227
+ minColumnWidth?: Length
224
228
  /**
225
229
  * Optional sort UI rendered above the grid. Visible only in stack mode
226
230
  * (SortChip carries its own `display: none → inline-flex` rule). Typical
@@ -239,7 +243,7 @@ export function Root({
239
243
  variant = 'default',
240
244
  size = 'md',
241
245
  responsive = true,
242
- minColumnWidth = 120,
246
+ minColumnWidth = 'labelMinW',
243
247
  sortChip,
244
248
  pagination,
245
249
  }: RootProps) {
@@ -438,17 +442,17 @@ export function HeaderCell({
438
442
  }: {
439
443
  children?: ReactNode
440
444
  /** Column width at default (wide) viewport. CSS grid-template-columns
441
- * track value — e.g. '40px', '2fr', 'max-content'. Defaults to
445
+ * track value — e.g. `sizes` key `"iconButton"`, '2fr', 'max-content'. Defaults to
442
446
  * 'minmax(0, 1fr)' so each column shares the row evenly and is free
443
447
  * to shrink below its content's intrinsic size. */
444
- width?: string
448
+ width?: GridTrack
445
449
  /** Column width when the table's container drops into compact mode
446
450
  * (≤720px container). Use this to switch to a content-aware layout
447
451
  * at narrow widths — e.g. give a status badge `max-content` and the
448
452
  * action column `minmax(0, 2fr)` so it absorbs the slack — while
449
453
  * keeping evenly-distributed columns on wide screens. Defaults to the
450
454
  * same value as `width`. */
451
- compactWidth?: string
455
+ compactWidth?: GridTrack
452
456
  /** Stack-mode label string. Optional when children is a plain string — the
453
457
  * text content is used as the label automatically. Required when children
454
458
  * contain JSX (icon + text, sort indicator, etc.). */
@@ -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 {duration, easing} from '@duro-app/tokens/tokens/motion.css'
6
6
  import {breakpoints} from '@duro-app/tokens/tokens/breakpoints.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
  // Container-query thresholds, from the shared breakpoint scale. `sm` (640px)
9
11
  // is the single "card up" line used across every table (Table + VirtualTable);
@@ -42,17 +44,17 @@ export const styles = css.create({
42
44
  cursor: 'pointer',
43
45
  outlineWidth: {
44
46
  default: 0,
45
- ':focus-visible': 2,
47
+ ':focus-visible': borders.focusRing,
46
48
  },
47
49
  outlineStyle: 'solid',
48
50
  outlineColor: colors.accent,
49
- outlineOffset: -2,
51
+ outlineOffset: `calc(-1 * ${borders.focusOffset})`,
50
52
  },
51
53
 
52
54
  // Root — the single grid container for the table itself
53
55
  root: {
54
56
  display: 'grid',
55
- borderWidth: 1,
57
+ borderWidth: borders.hairline,
56
58
  borderStyle: 'solid',
57
59
  borderColor: colors.border,
58
60
  borderRadius: radii.md,
@@ -83,7 +85,7 @@ export const styles = css.create({
83
85
  // The card-list look needs the outer border to disappear in stack
84
86
  // mode — each row paints its own border.
85
87
  borderWidth: {
86
- default: 1,
88
+ default: borders.hairline,
87
89
  [`@container (max-width: ${STACK_BP})`]: 0,
88
90
  },
89
91
  backgroundColor: {
@@ -129,7 +131,7 @@ export const styles = css.create({
129
131
  [`@container (max-width: ${STACK_BP})`]: '1fr',
130
132
  },
131
133
  borderBottomWidth: {
132
- default: 1,
134
+ default: borders.hairline,
133
135
  [`@container (max-width: ${STACK_BP})`]: 0,
134
136
  },
135
137
  borderBottomStyle: 'solid',
@@ -313,7 +315,7 @@ export const styles = css.create({
313
315
  // Variant: bordered (cells get side borders). Suppressed in stack.
314
316
  borderedCell: {
315
317
  borderRightWidth: {
316
- default: 1,
318
+ default: borders.hairline,
317
319
  [`@container (max-width: ${STACK_BP})`]: 0,
318
320
  },
319
321
  borderRightStyle: 'solid',
@@ -360,7 +362,7 @@ export const styles = css.create({
360
362
  position: 'absolute',
361
363
  top: 1,
362
364
  bottom: 1,
363
- width: spacing.xl,
365
+ width: sizes.edgeFade,
364
366
  pointerEvents: 'none',
365
367
  opacity: 0,
366
368
  transitionProperty: 'opacity',
@@ -1,8 +1,10 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
- import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
3
+ import {spacing} 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: {
@@ -15,7 +17,7 @@ export const styles = css.create({
15
17
  list: {
16
18
  display: 'flex',
17
19
  flexDirection: 'row',
18
- borderBottomWidth: 1,
20
+ borderBottomWidth: borders.hairline,
19
21
  borderBottomStyle: 'solid',
20
22
  borderBottomColor: colors.border,
21
23
  gap: spacing.xs,
@@ -25,7 +27,7 @@ export const styles = css.create({
25
27
  listVertical: {
26
28
  flexDirection: 'column',
27
29
  borderBottomWidth: 0,
28
- borderRightWidth: 1,
30
+ borderRightWidth: borders.hairline,
29
31
  borderRightStyle: 'solid',
30
32
  borderRightColor: colors.border,
31
33
  gap: 0,
@@ -47,7 +49,7 @@ export const styles = css.create({
47
49
  },
48
50
  backgroundColor: 'transparent',
49
51
  borderWidth: 0,
50
- borderBottomWidth: 2,
52
+ borderBottomWidth: borders.strong,
51
53
  borderBottomStyle: 'solid',
52
54
  borderBottomColor: 'transparent',
53
55
  cursor: 'pointer',
@@ -56,7 +58,7 @@ export const styles = css.create({
56
58
  transitionTimingFunction: easing.standard,
57
59
  outlineWidth: {
58
60
  default: 0,
59
- ':focus-visible': 2,
61
+ ':focus-visible': borders.focusRing,
60
62
  },
61
63
  outlineStyle: {
62
64
  default: 'none',
@@ -68,13 +70,13 @@ export const styles = css.create({
68
70
  },
69
71
  outlineOffset: {
70
72
  default: 0,
71
- ':focus-visible': -2,
73
+ ':focus-visible': `calc(-1 * ${borders.focusOffset})`,
72
74
  },
73
75
  },
74
76
  tabVertical: {
75
77
  justifyContent: 'flex-start',
76
78
  borderBottomWidth: 0,
77
- borderRightWidth: 2,
79
+ borderRightWidth: borders.strong,
78
80
  borderRightStyle: 'solid',
79
81
  borderRightColor: 'transparent',
80
82
  },
@@ -105,12 +107,12 @@ export const styles = css.create({
105
107
  indicatorHorizontal: {
106
108
  bottom: -1,
107
109
  left: 0,
108
- height: 2,
110
+ height: sizes.tabIndicator,
109
111
  },
110
112
  indicatorVertical: {
111
113
  right: -1,
112
114
  top: 0,
113
- width: 2,
115
+ width: sizes.tabIndicator,
114
116
  },
115
117
  // Dynamic transform/size from the measured active tab (StyleX dynamic style:
116
118
  // simple identifier params only).
@@ -4,6 +4,8 @@ import {css, html} from 'react-strict-dom'
4
4
  import {Tag} from './Tag'
5
5
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
6
6
  import {colors} from '@duro-app/tokens/tokens/colors.css'
7
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
8
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
7
9
 
8
10
  const meta: Meta<typeof Tag> = {
9
11
  title: 'Components/Tag',
@@ -53,8 +55,8 @@ const layoutStyles = css.create({
53
55
  stack: {display: 'flex', flexDirection: 'column', gap: spacing.md},
54
56
  // Narrow column that a long identifier tag would overflow without `wrap`.
55
57
  narrowCol: {
56
- width: 120,
57
- borderWidth: 1,
58
+ width: sizes.labelMinW,
59
+ borderWidth: borders.hairline,
58
60
  borderStyle: 'solid',
59
61
  borderColor: colors.border,
60
62
  padding: spacing.sm,