@duro-app/ui 4.5.0 → 5.1.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 (242) hide show
  1. package/dist/Table-BkrgH0jb.js +1199 -0
  2. package/dist/Table-BkrgH0jb.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/Card.stories.d.ts.map +1 -1
  14. package/dist/components/Card/styles.css.d.ts +3 -3
  15. package/dist/components/Card/styles.css.d.ts.map +1 -1
  16. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  17. package/dist/components/Checkbox/styles.css.d.ts +7 -11
  18. package/dist/components/Checkbox/styles.css.d.ts.map +1 -1
  19. package/dist/components/Cluster/Cluster.stories.d.ts.map +1 -1
  20. package/dist/components/ColorInput/styles.css.d.ts +6 -6
  21. package/dist/components/ColorInput/styles.css.d.ts.map +1 -1
  22. package/dist/components/ColorMode/styles.css.d.ts +3 -3
  23. package/dist/components/ColorMode/styles.css.d.ts.map +1 -1
  24. package/dist/components/Combobox/styles.css.d.ts +3 -3
  25. package/dist/components/Combobox/styles.css.d.ts.map +1 -1
  26. package/dist/components/DetailPanel/DetailPanel.d.ts.map +1 -1
  27. package/dist/components/DetailPanel/DetailPanel.stories.d.ts.map +1 -1
  28. package/dist/components/DetailPanel/styles.css.d.ts +19 -10
  29. package/dist/components/DetailPanel/styles.css.d.ts.map +1 -1
  30. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  31. package/dist/components/Dialog/Dialog.stories.d.ts.map +1 -1
  32. package/dist/components/Dialog/styles.css.d.ts +18 -9
  33. package/dist/components/Dialog/styles.css.d.ts.map +1 -1
  34. package/dist/components/DragDrop/DragDrop.d.ts.map +1 -1
  35. package/dist/components/DragDrop/DragDrop.stories.d.ts.map +1 -1
  36. package/dist/components/DragDrop/styles.css.d.ts +0 -6
  37. package/dist/components/DragDrop/styles.css.d.ts.map +1 -1
  38. package/dist/components/Drawer/Drawer.d.ts.map +1 -1
  39. package/dist/components/Drawer/styles.css.d.ts +19 -10
  40. package/dist/components/Drawer/styles.css.d.ts.map +1 -1
  41. package/dist/components/Field/Field.stories.d.ts.map +1 -1
  42. package/dist/components/Field/styles.css.d.ts +1 -1
  43. package/dist/components/Field/styles.css.d.ts.map +1 -1
  44. package/dist/components/Form/Form.stories.d.ts.map +1 -1
  45. package/dist/components/Grid/Grid.d.ts +6 -4
  46. package/dist/components/Grid/Grid.d.ts.map +1 -1
  47. package/dist/components/Grid/Grid.stories.d.ts.map +1 -1
  48. package/dist/components/Grid/styles.css.d.ts +5 -5
  49. package/dist/components/Grid/styles.css.d.ts.map +1 -1
  50. package/dist/components/Input/Input.stories.d.ts.map +1 -1
  51. package/dist/components/Input/styles.css.d.ts +3 -3
  52. package/dist/components/Input/styles.css.d.ts.map +1 -1
  53. package/dist/components/InputGroup/InputGroup.d.ts +4 -2
  54. package/dist/components/InputGroup/InputGroup.d.ts.map +1 -1
  55. package/dist/components/InputGroup/InputGroup.stories.d.ts.map +1 -1
  56. package/dist/components/InputGroup/styles.css.d.ts +3 -3
  57. package/dist/components/InputGroup/styles.css.d.ts.map +1 -1
  58. package/dist/components/LinkButton/styles.css.d.ts +1 -1
  59. package/dist/components/LinkButton/styles.css.d.ts.map +1 -1
  60. package/dist/components/List/List.stories.d.ts.map +1 -1
  61. package/dist/components/List/styles.css.d.ts +3 -3
  62. package/dist/components/List/styles.css.d.ts.map +1 -1
  63. package/dist/components/Menu/styles.css.d.ts +4 -4
  64. package/dist/components/Menu/styles.css.d.ts.map +1 -1
  65. package/dist/components/PageShell/styles.css.d.ts +3 -3
  66. package/dist/components/PageShell/styles.css.d.ts.map +1 -1
  67. package/dist/components/Panel/styles.css.d.ts +3 -3
  68. package/dist/components/Panel/styles.css.d.ts.map +1 -1
  69. package/dist/components/Popover/Popover.stories.d.ts.map +1 -1
  70. package/dist/components/Popover/styles.css.d.ts +2 -2
  71. package/dist/components/Popover/styles.css.d.ts.map +1 -1
  72. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  73. package/dist/components/RadioGroup/styles.css.d.ts +5 -9
  74. package/dist/components/RadioGroup/styles.css.d.ts.map +1 -1
  75. package/dist/components/ScrollArea/ScrollArea.d.ts +2 -1
  76. package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  77. package/dist/components/ScrollArea/ScrollArea.stories.d.ts.map +1 -1
  78. package/dist/components/ScrollArea/styles.css.d.ts +8 -8
  79. package/dist/components/ScrollArea/styles.css.d.ts.map +1 -1
  80. package/dist/components/Select/styles.css.d.ts +4 -4
  81. package/dist/components/Select/styles.css.d.ts.map +1 -1
  82. package/dist/components/SideNav/styles.css.d.ts +7 -7
  83. package/dist/components/SideNav/styles.css.d.ts.map +1 -1
  84. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  85. package/dist/components/Spinner/styles.css.d.ts +10 -14
  86. package/dist/components/Spinner/styles.css.d.ts.map +1 -1
  87. package/dist/components/StatusIcon/StatusIcon.stories.d.ts.map +1 -1
  88. package/dist/components/Switch/Switch.d.ts.map +1 -1
  89. package/dist/components/Switch/styles.css.d.ts +10 -14
  90. package/dist/components/Switch/styles.css.d.ts.map +1 -1
  91. package/dist/components/Table/ColumnFilter.d.ts.map +1 -1
  92. package/dist/components/Table/FromTanstack.d.ts +2 -1
  93. package/dist/components/Table/FromTanstack.d.ts.map +1 -1
  94. package/dist/components/Table/Pagination.d.ts.map +1 -1
  95. package/dist/components/Table/SortIndicator.d.ts.map +1 -1
  96. package/dist/components/Table/Table.d.ts +11 -9
  97. package/dist/components/Table/Table.d.ts.map +1 -1
  98. package/dist/components/Table/Table.stories.d.ts +1 -0
  99. package/dist/components/Table/Table.stories.d.ts.map +1 -1
  100. package/dist/components/Table/styles.css.d.ts +6 -6
  101. package/dist/components/Table/styles.css.d.ts.map +1 -1
  102. package/dist/components/Tabs/styles.css.d.ts +8 -8
  103. package/dist/components/Tabs/styles.css.d.ts.map +1 -1
  104. package/dist/components/Tag/Tag.stories.d.ts.map +1 -1
  105. package/dist/components/Tag/styles.css.d.ts +4 -4
  106. package/dist/components/Tag/styles.css.d.ts.map +1 -1
  107. package/dist/components/TagGroup/TagGroup.d.ts.map +1 -1
  108. package/dist/components/TagGroup/styles.css.d.ts +4 -10
  109. package/dist/components/TagGroup/styles.css.d.ts.map +1 -1
  110. package/dist/components/Textarea/Textarea.stories.d.ts.map +1 -1
  111. package/dist/components/Textarea/styles.css.d.ts +3 -3
  112. package/dist/components/Textarea/styles.css.d.ts.map +1 -1
  113. package/dist/components/ThemeProvider/ThemeProvider.stories.d.ts.map +1 -1
  114. package/dist/components/Toast/Toast.stories.d.ts.map +1 -1
  115. package/dist/components/Toast/styles.css.d.ts +12 -12
  116. package/dist/components/Toast/styles.css.d.ts.map +1 -1
  117. package/dist/components/Toggle/styles.css.d.ts +8 -8
  118. package/dist/components/Toggle/styles.css.d.ts.map +1 -1
  119. package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts.map +1 -1
  120. package/dist/components/ToggleGroup/styles.css.d.ts +1 -1
  121. package/dist/components/ToggleGroup/styles.css.d.ts.map +1 -1
  122. package/dist/components/Tooltip/styles.css.d.ts +1 -1
  123. package/dist/components/Tooltip/styles.css.d.ts.map +1 -1
  124. package/dist/components/Tree/styles.css.d.ts +4 -4
  125. package/dist/components/Tree/styles.css.d.ts.map +1 -1
  126. package/dist/components/VirtualTable/VirtualTable.d.ts +2 -1
  127. package/dist/components/VirtualTable/VirtualTable.d.ts.map +1 -1
  128. package/dist/components/VirtualTable/VirtualTable.stories.d.ts.map +1 -1
  129. package/dist/components/VirtualTable/styles.css.d.ts +7 -7
  130. package/dist/components/VirtualTable/styles.css.d.ts.map +1 -1
  131. package/dist/docs/Spacing.stories.d.ts.map +1 -1
  132. package/dist/docs/Typography.stories.d.ts.map +1 -1
  133. package/dist/docs/helpers.d.ts.map +1 -1
  134. package/dist/index.css +1 -1
  135. package/dist/index.js +2833 -2828
  136. package/dist/index.js.map +1 -1
  137. package/dist/shared/length.d.ts +29 -0
  138. package/dist/shared/length.d.ts.map +1 -0
  139. package/dist/shared/length.typecheck.d.ts +31 -0
  140. package/dist/shared/length.typecheck.d.ts.map +1 -0
  141. package/dist/styles/visually-hidden.css.d.ts +10 -0
  142. package/dist/styles/visually-hidden.css.d.ts.map +1 -0
  143. package/dist/table.js +166 -166
  144. package/dist/table.js.map +1 -1
  145. package/package.json +2 -2
  146. package/src/components/ActionBar/ActionBar.stories.tsx +4 -2
  147. package/src/components/ActionBar/styles.css.ts +11 -9
  148. package/src/components/Alert/styles.css.ts +4 -3
  149. package/src/components/Badge/styles.css.ts +3 -3
  150. package/src/components/Button/styles.css.ts +8 -7
  151. package/src/components/Callout/styles.css.ts +2 -1
  152. package/src/components/Card/Card.stories.tsx +2 -1
  153. package/src/components/Card/styles.css.ts +4 -3
  154. package/src/components/Checkbox/Checkbox.tsx +2 -1
  155. package/src/components/Checkbox/styles.css.ts +10 -11
  156. package/src/components/Cluster/Cluster.stories.tsx +2 -1
  157. package/src/components/ColorInput/styles.css.ts +9 -7
  158. package/src/components/ColorMode/styles.css.ts +4 -3
  159. package/src/components/Combobox/styles.css.ts +5 -3
  160. package/src/components/DetailPanel/DetailPanel.stories.tsx +5 -3
  161. package/src/components/DetailPanel/DetailPanel.tsx +3 -0
  162. package/src/components/DetailPanel/styles.css.ts +17 -11
  163. package/src/components/Dialog/Dialog.stories.tsx +2 -1
  164. package/src/components/Dialog/Dialog.tsx +3 -0
  165. package/src/components/Dialog/styles.css.ts +14 -9
  166. package/src/components/DragDrop/DragDrop.stories.tsx +2 -1
  167. package/src/components/DragDrop/DragDrop.tsx +2 -1
  168. package/src/components/DragDrop/styles.css.ts +0 -7
  169. package/src/components/Drawer/Drawer.tsx +3 -0
  170. package/src/components/Drawer/DrawerScroll.stories.tsx +5 -5
  171. package/src/components/Drawer/styles.css.ts +15 -10
  172. package/src/components/Field/Field.stories.tsx +3 -2
  173. package/src/components/Field/styles.css.ts +2 -1
  174. package/src/components/Form/Form.stories.tsx +4 -3
  175. package/src/components/Grid/Grid.meta.ts +2 -2
  176. package/src/components/Grid/Grid.stories.tsx +3 -2
  177. package/src/components/Grid/Grid.tsx +8 -6
  178. package/src/components/Grid/styles.css.ts +5 -4
  179. package/src/components/Input/Input.stories.tsx +2 -1
  180. package/src/components/Input/styles.css.ts +4 -3
  181. package/src/components/InputGroup/InputGroup.stories.tsx +3 -2
  182. package/src/components/InputGroup/InputGroup.tsx +5 -3
  183. package/src/components/InputGroup/styles.css.ts +4 -3
  184. package/src/components/LinkButton/styles.css.ts +2 -1
  185. package/src/components/List/List.stories.tsx +4 -2
  186. package/src/components/List/styles.css.ts +6 -4
  187. package/src/components/Menu/styles.css.ts +6 -4
  188. package/src/components/PageShell/styles.css.ts +4 -3
  189. package/src/components/Panel/styles.css.ts +4 -3
  190. package/src/components/Popover/Popover.stories.tsx +6 -4
  191. package/src/components/Popover/styles.css.ts +3 -2
  192. package/src/components/RadioGroup/RadioGroup.tsx +2 -1
  193. package/src/components/RadioGroup/styles.css.ts +8 -9
  194. package/src/components/ScrollArea/ScrollArea.meta.ts +1 -1
  195. package/src/components/ScrollArea/ScrollArea.stories.tsx +7 -5
  196. package/src/components/ScrollArea/ScrollArea.tsx +7 -2
  197. package/src/components/ScrollArea/styles.css.ts +10 -9
  198. package/src/components/Select/styles.css.ts +6 -4
  199. package/src/components/SideNav/styles.css.ts +10 -8
  200. package/src/components/Spinner/Spinner.tsx +2 -1
  201. package/src/components/Spinner/styles.css.ts +14 -14
  202. package/src/components/StatusIcon/StatusIcon.stories.tsx +2 -2
  203. package/src/components/Switch/Switch.tsx +2 -1
  204. package/src/components/Switch/styles.css.ts +15 -15
  205. package/src/components/Table/ColumnFilter.tsx +5 -4
  206. package/src/components/Table/FromTanstack.tsx +2 -1
  207. package/src/components/Table/Pagination.tsx +6 -4
  208. package/src/components/Table/SortIndicator.tsx +4 -2
  209. package/src/components/Table/Table.stories.tsx +47 -8
  210. package/src/components/Table/Table.tsx +19 -15
  211. package/src/components/Table/styles.css.ts +9 -7
  212. package/src/components/Tabs/styles.css.ts +11 -9
  213. package/src/components/Tag/Tag.stories.tsx +4 -2
  214. package/src/components/Tag/styles.css.ts +6 -5
  215. package/src/components/TagGroup/TagGroup.tsx +2 -1
  216. package/src/components/TagGroup/styles.css.ts +6 -10
  217. package/src/components/Textarea/Textarea.stories.tsx +2 -1
  218. package/src/components/Textarea/styles.css.ts +4 -3
  219. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +7 -5
  220. package/src/components/Toast/Toast.stories.tsx +2 -1
  221. package/src/components/Toast/styles.css.ts +16 -14
  222. package/src/components/Toggle/Toggle.meta.ts +1 -1
  223. package/src/components/Toggle/styles.css.ts +12 -10
  224. package/src/components/ToggleGroup/ToggleGroup.meta.ts +1 -1
  225. package/src/components/ToggleGroup/ToggleGroup.stories.tsx +7 -6
  226. package/src/components/ToggleGroup/styles.css.ts +7 -6
  227. package/src/components/Tooltip/styles.css.ts +2 -1
  228. package/src/components/Tree/styles.css.ts +8 -6
  229. package/src/components/VirtualTable/VirtualTable.stories.tsx +4 -3
  230. package/src/components/VirtualTable/VirtualTable.tsx +5 -3
  231. package/src/components/VirtualTable/styles.css.ts +9 -8
  232. package/src/docs/Spacing.stories.tsx +11 -10
  233. package/src/docs/Typography.stories.tsx +8 -6
  234. package/src/docs/helpers.tsx +3 -2
  235. package/src/shared/length.ts +70 -0
  236. package/src/shared/length.typecheck.tsx +56 -0
  237. package/src/styles/visually-hidden.css.ts +16 -0
  238. package/dist/Table-CUp12BKZ.js +0 -1099
  239. package/dist/Table-CUp12BKZ.js.map +0 -1
  240. package/dist/components/Toggle/rowHeight.d.ts +0 -17
  241. package/dist/components/Toggle/rowHeight.d.ts.map +0 -1
  242. package/src/components/Toggle/rowHeight.ts +0 -12
@@ -8,6 +8,7 @@ import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
8
8
  import {SPACING_KEYS} from '@duro-app/tokens/keys'
9
9
  import {useContainerQuery} from '../../hooks/useContainerQuery'
10
10
  import {typography} from '@duro-app/tokens/tokens/typography.css'
11
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
11
12
 
12
13
  const meta: Meta<typeof Grid> = {
13
14
  title: 'Layout/Grid',
@@ -45,7 +46,7 @@ const localStyles = css.create({
45
46
  },
46
47
  frame: (width: number) => ({
47
48
  width,
48
- borderWidth: 1,
49
+ borderWidth: borders.hairline,
49
50
  borderStyle: 'dashed',
50
51
  borderColor: colors.border,
51
52
  }),
@@ -74,7 +75,7 @@ export const FixedColumns: Story = {
74
75
 
75
76
  export const AutoFit: Story = {
76
77
  render: () => (
77
- <Grid gap="md" minColumnWidth="200px">
78
+ <Grid gap="md" minColumnWidth="gridColSm">
78
79
  <Cell>Card A</Cell>
79
80
  <Cell>Card B</Cell>
80
81
  <Cell>Card C</Cell>
@@ -4,6 +4,7 @@ import {styles} from './styles.css'
4
4
  import {isNative} from '../../platform'
5
5
  import {cellBasis, cellPosition, columnWeights, gridTemplate, type GridColumns} from './columns'
6
6
  import type {SpacingToken} from '@duro-app/tokens/keys'
7
+ import {resolveLength, type Length} from '../../shared/length'
7
8
 
8
9
  export type GridLayout = 'split' | 'split-wide'
9
10
 
@@ -13,10 +14,11 @@ interface GridProps {
13
14
  * two-thirds split. Weights are the portable form of a track list — a CSS
14
15
  * template string would be silently ignored on native. */
15
16
  columns?: GridColumns
16
- /** Responsive auto-fit: as many columns of at least this width as fit.
17
- * Wins over `columns` when both are set. On native this approximates to
18
- * cells of that minimum width that grow and wrap. */
19
- minColumnWidth?: string
17
+ /** Responsive auto-fit: as many columns of at least this width as fit — a
18
+ * size token key (`"gridColMd"`) or a relative length. Wins over `columns`
19
+ * when both are set. On native this approximates to cells of that minimum
20
+ * width that grow and wrap. */
21
+ minColumnWidth?: Length
20
22
  /**
21
23
  * A named responsive layout. `split` is list/detail (1:2, list ≥ 240px),
22
24
  * `split-wide` is nav/content (1:3, nav ≥ 280px). Each collapses to one
@@ -101,7 +103,7 @@ export function Grid({gap = 'md', columns, minColumnWidth, layout, children}: Gr
101
103
  const columnStyle = layout
102
104
  ? layoutMap[layout]
103
105
  : minColumnWidth
104
- ? styles.autoFit(minColumnWidth)
106
+ ? styles.autoFit(resolveLength(minColumnWidth))
105
107
  : typeof columns === 'number'
106
108
  ? columnsMap[columns]
107
109
  : columns
@@ -136,7 +138,7 @@ function NativeGrid({gap = 'md', columns, minColumnWidth, children}: GridProps)
136
138
  return (
137
139
  <html.div style={[styles.nativeRow, gapMap[gap]]}>
138
140
  {items.map((child, index) => (
139
- <html.div key={index} style={styles.nativeMinCell(minColumnWidth)}>
141
+ <html.div key={index} style={styles.nativeMinCell(resolveLength(minColumnWidth))}>
140
142
  {child}
141
143
  </html.div>
142
144
  ))}
@@ -1,6 +1,7 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
3
3
  import {breakpoints} from '@duro-app/tokens/tokens/breakpoints.css'
4
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
4
5
 
5
6
  // Where a split collapses to one column — measured on the split's OWN
6
7
  // container, not the viewport. A split nested in another split (a list/detail
@@ -22,7 +23,7 @@ export const styles = css.create({
22
23
  col4: {gridTemplateColumns: 'repeat(4, 1fr)'},
23
24
  col5: {gridTemplateColumns: 'repeat(5, 1fr)'},
24
25
  col6: {gridTemplateColumns: 'repeat(6, 1fr)'},
25
- autoFit: (minWidth: string) => ({
26
+ autoFit: (minWidth: string | number) => ({
26
27
  gridTemplateColumns: `repeat(auto-fill, minmax(${minWidth}, 1fr))`,
27
28
  }),
28
29
  // Hosts the @container query for a named layout. A container cannot query
@@ -40,13 +41,13 @@ export const styles = css.create({
40
41
  split: {
41
42
  gridTemplateColumns: {
42
43
  default: '1fr',
43
- [`@container (min-width: ${SPLIT_BP})`]: 'minmax(240px, 1fr) minmax(0, 2fr)',
44
+ [`@container (min-width: ${SPLIT_BP})`]: `minmax(${sizes.gridColSm}, 1fr) minmax(0, 2fr)`,
44
45
  },
45
46
  },
46
47
  splitWide: {
47
48
  gridTemplateColumns: {
48
49
  default: '1fr',
49
- [`@container (min-width: ${SPLIT_WIDE_BP})`]: 'minmax(280px, 1fr) minmax(0, 3fr)',
50
+ [`@container (min-width: ${SPLIT_WIDE_BP})`]: `minmax(${sizes.gridColMd}, 1fr) minmax(0, 3fr)`,
50
51
  },
51
52
  },
52
53
  // Weighted columns: `[1, 2]` → `1fr 2fr` (see columns.ts).
@@ -86,7 +87,7 @@ export const styles = css.create({
86
87
  // Auto-fit approximation: start at the minimum width, grow to fill. flexGrow
87
88
  // is fine here: this style is native-only, so RSD-web's forced flex-grow: 0
88
89
  // never applies.
89
- nativeMinCell: (minWidth: string) => ({
90
+ nativeMinCell: (minWidth: string | number) => ({
90
91
  flexBasis: minWidth,
91
92
  flexGrow: 1,
92
93
  boxSizing: 'border-box',
@@ -3,6 +3,7 @@ import {expect, fn} from 'storybook/test'
3
3
  import {css, html} from 'react-strict-dom'
4
4
  import {Input} from './Input'
5
5
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
6
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
6
7
 
7
8
  const meta: Meta<typeof Input> = {
8
9
  title: 'Components/Input',
@@ -83,7 +84,7 @@ export const Disabled: Story = {
83
84
  }
84
85
 
85
86
  const stackStyles = css.create({
86
- stack: {display: 'flex', flexDirection: 'column', gap: spacing.ms, maxWidth: 320},
87
+ stack: {display: 'flex', flexDirection: 'column', gap: spacing.ms, maxWidth: sizes.panelSm},
87
88
  })
88
89
 
89
90
  export const AllVariants: Story = {
@@ -3,6 +3,7 @@ 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 {borders} from '@duro-app/tokens/tokens/borders.css'
6
7
 
7
8
  export const styles = css.create({
8
9
  base: {
@@ -16,7 +17,7 @@ export const styles = css.create({
16
17
  lineHeight: typography.lineHeight,
17
18
  color: colors.text,
18
19
  backgroundColor: colors.bg,
19
- borderWidth: 1,
20
+ borderWidth: borders.hairline,
20
21
  borderStyle: 'solid',
21
22
  borderRadius: radii.sm,
22
23
  transitionProperty: 'border-color',
@@ -24,7 +25,7 @@ export const styles = css.create({
24
25
  transitionTimingFunction: easing.standard,
25
26
  outlineWidth: {
26
27
  default: 0,
27
- ':focus-visible': 2,
28
+ ':focus-visible': borders.focusRing,
28
29
  },
29
30
  outlineStyle: {
30
31
  default: 'none',
@@ -36,7 +37,7 @@ export const styles = css.create({
36
37
  },
37
38
  outlineOffset: {
38
39
  default: 0,
39
- ':focus-visible': 1,
40
+ ':focus-visible': borders.focusOffsetSm,
40
41
  },
41
42
  },
42
43
  default: {
@@ -5,6 +5,7 @@ import {InputGroup} from './InputGroup'
5
5
  import {Input} from '../Input/Input'
6
6
  import {Icon} from '../Icon/Icon'
7
7
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
8
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
8
9
 
9
10
  const meta: Meta = {
10
11
  title: 'Components/InputGroup',
@@ -115,8 +116,8 @@ export const StandaloneInput: Story = {
115
116
  }
116
117
 
117
118
  const layoutStyles = css.create({
118
- container: {maxWidth: 400},
119
- stack: {display: 'flex', flexDirection: 'column', gap: spacing.md, maxWidth: 400},
119
+ container: {maxWidth: sizes.dialogSm},
120
+ stack: {display: 'flex', flexDirection: 'column', gap: spacing.md, maxWidth: sizes.dialogSm},
120
121
  })
121
122
 
122
123
  export const AllVariants: Story = {
@@ -4,6 +4,7 @@ import {css, html} from 'react-strict-dom'
4
4
  import {isNative} from '../../platform'
5
5
  import {InputGroupContext} from './InputGroupContext'
6
6
  import {styles} from './styles.css'
7
+ import {resolveLength, type Length} from '../../shared/length'
7
8
 
8
9
  // --- Root ---
9
10
  interface RootProps {
@@ -29,8 +30,9 @@ interface AddonProps {
29
30
  position?: 'start' | 'end'
30
31
  onClick?: () => void
31
32
  disabled?: boolean
32
- /** Optional minimum width to prevent layout shift (e.g. Copy → Copied!) */
33
- minWidth?: number | string
33
+ /** Optional minimum width to prevent layout shift (e.g. Copy → Copied!): a
34
+ * size token key or a relative length. */
35
+ minWidth?: Length
34
36
  children: ReactNode
35
37
  }
36
38
 
@@ -42,7 +44,7 @@ function Addon({position = 'end', onClick, disabled, minWidth, children}: AddonP
42
44
  positionStyle,
43
45
  onClick && !disabled && styles.addonClickable,
44
46
  disabled && styles.addonDisabled,
45
- minWidth != null && dynamicStyles.minWidth(minWidth),
47
+ minWidth != null && dynamicStyles.minWidth(resolveLength(minWidth)),
46
48
  ]
47
49
 
48
50
  if (onClick) {
@@ -3,12 +3,13 @@ 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 {borders} from '@duro-app/tokens/tokens/borders.css'
6
7
 
7
8
  export const styles = css.create({
8
9
  wrapper: {
9
10
  display: 'flex',
10
11
  alignItems: 'stretch',
11
- borderWidth: 1,
12
+ borderWidth: borders.hairline,
12
13
  borderStyle: 'solid',
13
14
  borderColor: {
14
15
  default: colors.border,
@@ -35,12 +36,12 @@ export const styles = css.create({
35
36
  borderWidth: 0,
36
37
  },
37
38
  addonStart: {
38
- borderRightWidth: 1,
39
+ borderRightWidth: borders.hairline,
39
40
  borderRightStyle: 'solid',
40
41
  borderRightColor: colors.border,
41
42
  },
42
43
  addonEnd: {
43
- borderLeftWidth: 1,
44
+ borderLeftWidth: borders.hairline,
44
45
  borderLeftStyle: 'solid',
45
46
  borderLeftColor: colors.border,
46
47
  },
@@ -3,6 +3,7 @@ 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 {borders} from '@duro-app/tokens/tokens/borders.css'
6
7
 
7
8
  export const styles = css.create({
8
9
  base: {
@@ -46,7 +47,7 @@ export const styles = css.create({
46
47
  default: 'transparent',
47
48
  ':hover': colors.bgCardHover,
48
49
  },
49
- borderWidth: 1,
50
+ borderWidth: borders.hairline,
50
51
  borderStyle: 'solid',
51
52
  borderColor: colors.border,
52
53
  color: colors.textMuted,
@@ -8,6 +8,8 @@ import {Button} from '../Button/Button'
8
8
  import {Checkbox} from '../Checkbox/Checkbox'
9
9
  import {colors} from '@duro-app/tokens/tokens/colors.css'
10
10
  import {radii} from '@duro-app/tokens/tokens/spacing.css'
11
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
12
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
11
13
 
12
14
  const meta: Meta = {
13
15
  title: 'Components/List',
@@ -73,8 +75,8 @@ export const Default: Story = {
73
75
 
74
76
  const narrowContainer = css.create({
75
77
  box: {
76
- maxWidth: 360,
77
- borderWidth: 1,
78
+ maxWidth: sizes.panelSm,
79
+ borderWidth: borders.hairline,
78
80
  borderStyle: 'solid',
79
81
  borderColor: colors.border,
80
82
  borderRadius: radii.sm,
@@ -1,7 +1,9 @@
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 {microSpacing, spacing} from '@duro-app/tokens/tokens/spacing.css'
4
4
  import {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration} from '@duro-app/tokens/tokens/motion.css'
6
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
5
7
 
6
8
  export const styles = css.create({
7
9
  // --- Root ---
@@ -21,7 +23,7 @@ export const styles = css.create({
21
23
  paddingBottom: spacing.sm,
22
24
  paddingLeft: spacing.ms,
23
25
  paddingRight: spacing.ms,
24
- borderBottomWidth: 1,
26
+ borderBottomWidth: borders.hairline,
25
27
  borderBottomStyle: 'solid',
26
28
  borderBottomColor: colors.border,
27
29
  backgroundColor: {
@@ -29,7 +31,7 @@ export const styles = css.create({
29
31
  ':hover': colors.bgCardHover,
30
32
  },
31
33
  transitionProperty: 'background-color',
32
- transitionDuration: '120ms',
34
+ transitionDuration: duration.quick,
33
35
  cursor: 'default',
34
36
  },
35
37
  itemSelected: {
@@ -51,7 +53,7 @@ export const styles = css.create({
51
53
  flex: 1,
52
54
  display: 'flex',
53
55
  flexDirection: 'column',
54
- gap: 2,
56
+ gap: microSpacing.px2,
55
57
  minWidth: 0,
56
58
  },
57
59
 
@@ -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: {
@@ -25,7 +27,7 @@ export const styles = css.create({
25
27
  default: 'transparent',
26
28
  ':hover': colors.bgCardHover,
27
29
  },
28
- borderWidth: 1,
30
+ borderWidth: borders.hairline,
29
31
  borderStyle: 'solid',
30
32
  borderColor: colors.border,
31
33
  borderRadius: radii.sm,
@@ -47,14 +49,14 @@ export const styles = css.create({
47
49
  left: 0,
48
50
  marginTop: spacing.xs,
49
51
  backgroundColor: colors.bgCard,
50
- borderWidth: 1,
52
+ borderWidth: borders.hairline,
51
53
  borderStyle: 'solid',
52
54
  borderColor: colors.border,
53
55
  borderRadius: radii.sm,
54
56
  boxShadow: shadows.md,
55
57
  paddingTop: spacing.xs,
56
58
  paddingBottom: spacing.xs,
57
- minWidth: 160,
59
+ minWidth: sizes.popupMinW,
58
60
  zIndex: 50,
59
61
  },
60
62
  popupEnd: {
@@ -84,7 +86,7 @@ export const styles = css.create({
84
86
  height: 0,
85
87
  marginTop: spacing.xs,
86
88
  marginBottom: spacing.xs,
87
- borderTopWidth: 1,
89
+ borderTopWidth: borders.hairline,
88
90
  borderTopStyle: 'solid',
89
91
  borderTopColor: colors.border,
90
92
  },
@@ -1,6 +1,7 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {layoutSpacing} from '@duro-app/tokens/tokens/layout-spacing.css'
3
3
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
4
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
4
5
 
5
6
  export const styles = css.create({
6
7
  root: {
@@ -12,9 +13,9 @@ export const styles = css.create({
12
13
  marginRight: 'auto',
13
14
  },
14
15
  // Max-width presets
15
- maxSm: {maxWidth: 600},
16
- maxMd: {maxWidth: 800},
17
- maxLg: {maxWidth: 1200},
16
+ maxSm: {maxWidth: sizes.pageSm},
17
+ maxMd: {maxWidth: sizes.pageMd},
18
+ maxLg: {maxWidth: sizes.pageLg},
18
19
  // Horizontal padding
19
20
  padSm: {paddingLeft: layoutSpacing.containerSm, paddingRight: layoutSpacing.containerSm},
20
21
  padMd: {paddingLeft: layoutSpacing.containerMd, paddingRight: layoutSpacing.containerMd},
@@ -1,6 +1,7 @@
1
1
  import {css} from 'react-strict-dom'
2
2
  import {colors} from '@duro-app/tokens/tokens/colors.css'
3
3
  import {spacing} from '@duro-app/tokens/tokens/spacing.css'
4
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
4
5
 
5
6
  export const styles = css.create({
6
7
  root: {
@@ -9,7 +10,7 @@ export const styles = css.create({
9
10
  backgroundColor: colors.bgCard,
10
11
  },
11
12
  bordered: {
12
- borderWidth: 1,
13
+ borderWidth: borders.hairline,
13
14
  borderStyle: 'solid',
14
15
  borderColor: colors.border,
15
16
  },
@@ -23,7 +24,7 @@ export const styles = css.create({
23
24
  paddingRight: spacing.lg,
24
25
  paddingBottom: spacing.lg,
25
26
  gap: spacing.md,
26
- borderBottomWidth: 1,
27
+ borderBottomWidth: borders.hairline,
27
28
  borderBottomStyle: 'solid',
28
29
  borderBottomColor: colors.border,
29
30
  },
@@ -53,7 +54,7 @@ export const styles = css.create({
53
54
  paddingBottom: spacing.md,
54
55
  paddingLeft: spacing.lg,
55
56
  paddingRight: spacing.lg,
56
- borderTopWidth: 1,
57
+ borderTopWidth: borders.hairline,
57
58
  borderTopStyle: 'solid',
58
59
  borderTopColor: colors.border,
59
60
  },
@@ -10,6 +10,8 @@ import {Field} from '../Field/Field'
10
10
  import {Input} from '../Input/Input'
11
11
  import {Select} from '../Select/Select'
12
12
  import {Stack} from '../Stack/Stack'
13
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
14
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
13
15
 
14
16
  const meta: Meta = {
15
17
  title: 'Components/Popover',
@@ -24,8 +26,8 @@ const page = () => within(document.body)
24
26
  const styles = css.create({
25
27
  stage: {
26
28
  position: 'relative',
27
- height: 320,
28
- borderWidth: 1,
29
+ height: sizes.panelSm,
30
+ borderWidth: borders.hairline,
29
31
  borderStyle: 'dashed',
30
32
  borderColor: colors.border,
31
33
  padding: spacing.md,
@@ -34,9 +36,9 @@ const styles = css.create({
34
36
  position: 'absolute',
35
37
  top: 120,
36
38
  left: 160,
37
- width: 120,
39
+ width: sizes.labelMinW,
38
40
  padding: spacing.sm,
39
- borderWidth: 1,
41
+ borderWidth: borders.hairline,
40
42
  borderStyle: 'solid',
41
43
  borderColor: colors.accent,
42
44
  },
@@ -4,6 +4,7 @@ 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 {borders} from '@duro-app/tokens/tokens/borders.css'
7
8
 
8
9
  export const styles = css.create({
9
10
  trigger: {
@@ -21,7 +22,7 @@ export const styles = css.create({
21
22
  default: 'transparent',
22
23
  ':hover': colors.bgCardHover,
23
24
  },
24
- borderWidth: 1,
25
+ borderWidth: borders.hairline,
25
26
  borderStyle: 'solid',
26
27
  borderColor: colors.border,
27
28
  borderRadius: radii.sm,
@@ -35,7 +36,7 @@ export const styles = css.create({
35
36
  left: 0,
36
37
  boxSizing: 'border-box',
37
38
  backgroundColor: colors.bgCard,
38
- borderWidth: 1,
39
+ borderWidth: borders.hairline,
39
40
  borderStyle: 'solid',
40
41
  borderColor: colors.border,
41
42
  borderRadius: radii.sm,
@@ -3,6 +3,7 @@ import {html} from 'react-strict-dom'
3
3
  import {useControllableValue} from '../../hooks/useControllableValue'
4
4
  import {styles} from './styles.css'
5
5
  import {useFieldGroupLabelling} from '../Field/FieldContext'
6
+ import {visuallyHidden} from '../../styles/visually-hidden.css'
6
7
 
7
8
  // --- Context ---
8
9
 
@@ -100,7 +101,7 @@ function Item({value, disabled: itemDisabled = false, children}: ItemProps) {
100
101
  checked={isChecked}
101
102
  disabled={isDisabled}
102
103
  onChange={() => onSelect(value)}
103
- style={styles.input}
104
+ style={[visuallyHidden.base, styles.input]}
104
105
  />
105
106
  <html.span
106
107
  style={[styles.circle, isChecked ? styles.circleChecked : styles.circleUnchecked]}
@@ -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: {
@@ -27,9 +29,9 @@ export const styles = css.create({
27
29
  cursor: 'not-allowed',
28
30
  },
29
31
  circle: {
30
- width: 18,
31
- height: 18,
32
- borderWidth: 1,
32
+ width: sizes.indicator,
33
+ height: sizes.indicator,
34
+ borderWidth: borders.hairline,
33
35
  borderStyle: 'solid',
34
36
  borderRadius: radii.full,
35
37
  display: 'inline-flex',
@@ -52,16 +54,13 @@ export const styles = css.create({
52
54
  borderColor: colors.accent,
53
55
  },
54
56
  dot: {
55
- width: 8,
56
- height: 8,
57
+ width: sizes.indicatorDot,
58
+ height: sizes.indicatorDot,
57
59
  borderRadius: radii.full,
58
60
  backgroundColor: colors.accent,
59
61
  },
62
+ // Layered on visuallyHidden.base: a native input is also made transparent.
60
63
  input: {
61
- position: 'absolute',
62
- width: 1,
63
- height: 1,
64
64
  opacity: 0,
65
- overflow: 'hidden',
66
65
  },
67
66
  })
@@ -15,7 +15,7 @@ export const meta: ComponentMeta = {
15
15
  required: ['Root', 'Viewport', 'Content', 'Scrollbar', 'Thumb'],
16
16
  },
17
17
  example: `<ScrollArea.Root>
18
- <ScrollArea.Viewport maxHeight={300}>
18
+ <ScrollArea.Viewport maxHeight="listMaxH">
19
19
  <ScrollArea.Content>
20
20
  {/* Long content here */}
21
21
  </ScrollArea.Content>
@@ -5,6 +5,8 @@ import {ScrollArea} from './ScrollArea'
5
5
  import {colors} from '@duro-app/tokens/tokens/colors.css'
6
6
  import {typography} from '@duro-app/tokens/tokens/typography.css'
7
7
  import {spacing, radii} from '@duro-app/tokens/tokens/spacing.css'
8
+ import {borders} from '@duro-app/tokens/tokens/borders.css'
9
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
8
10
 
9
11
  const meta: Meta = {
10
12
  title: 'Components/ScrollArea',
@@ -15,8 +17,8 @@ type Story = StoryObj
15
17
 
16
18
  const demoStyles = css.create({
17
19
  container: {
18
- width: 300,
19
- borderWidth: 1,
20
+ width: sizes.gridColMd,
21
+ borderWidth: borders.hairline,
20
22
  borderStyle: 'solid',
21
23
  borderColor: colors.border,
22
24
  borderRadius: radii.sm,
@@ -26,7 +28,7 @@ const demoStyles = css.create({
26
28
  paddingBottom: spacing.ms,
27
29
  paddingLeft: spacing.md,
28
30
  paddingRight: spacing.md,
29
- borderBottomWidth: 1,
31
+ borderBottomWidth: borders.hairline,
30
32
  borderBottomStyle: 'solid',
31
33
  borderBottomColor: colors.bgCard,
32
34
  fontSize: typography.fontSizeSm,
@@ -40,7 +42,7 @@ export const Default: Story = {
40
42
  render: () => (
41
43
  <html.div style={demoStyles.container}>
42
44
  <ScrollArea.Root>
43
- <ScrollArea.Viewport maxHeight={300}>
45
+ <ScrollArea.Viewport maxHeight="listMaxH">
44
46
  <ScrollArea.Content>
45
47
  {items.map((item) => (
46
48
  <html.div key={item} style={demoStyles.item}>
@@ -66,7 +68,7 @@ export const ShortContent: Story = {
66
68
  render: () => (
67
69
  <html.div style={demoStyles.container}>
68
70
  <ScrollArea.Root>
69
- <ScrollArea.Viewport maxHeight={300}>
71
+ <ScrollArea.Viewport maxHeight="listMaxH">
70
72
  <ScrollArea.Content>
71
73
  <html.div style={demoStyles.item}>Only one item</html.div>
72
74
  <html.div style={demoStyles.item}>Two items</html.div>
@@ -3,6 +3,7 @@ import {html} from 'react-strict-dom'
3
3
  import {styles} from './styles.css'
4
4
  import {ScrollAreaContext, useScrollArea} from './ScrollAreaContext'
5
5
  import {useScrollAreaRoot} from './useScrollAreaRoot'
6
+ import {resolveLength, type Length} from '../../shared/length'
6
7
 
7
8
  // --- Root ---
8
9
 
@@ -24,7 +25,7 @@ function Root({children}: RootProps) {
24
25
 
25
26
  interface ViewportProps {
26
27
  children: ReactNode
27
- maxHeight?: number | string
28
+ maxHeight?: Length
28
29
  /** Extra styles for the viewport (e.g. a pointer-aware max height). */
29
30
  style?: ComponentProps<typeof html.div>['style']
30
31
  /** A roving-focus group owns the keyboard: drop the viewport's own tab stop
@@ -43,7 +44,11 @@ function Viewport({children, maxHeight, style, rovingOwner = false}: ViewportPro
43
44
  tabIndex={rovingOwner ? undefined : 0}
44
45
  role={rovingOwner ? undefined : 'region'}
45
46
  aria-label={rovingOwner ? undefined : 'Scrollable content'}
46
- style={[styles.viewport, maxHeight != null && styles.viewportMaxHeight(maxHeight), style]}
47
+ style={[
48
+ styles.viewport,
49
+ maxHeight != null && styles.viewportMaxHeight(resolveLength(maxHeight)),
50
+ style,
51
+ ]}
47
52
  >
48
53
  {children}
49
54
  </html.div>
@@ -1,7 +1,8 @@
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
4
  import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
+ import {sizes} from '@duro-app/tokens/tokens/sizes.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  root: {
@@ -34,21 +35,21 @@ export const styles = css.create({
34
35
  top: 0,
35
36
  right: 0,
36
37
  bottom: 0,
37
- width: 8,
38
+ width: sizes.scrollbar,
38
39
  flexDirection: 'column',
39
- paddingTop: 2,
40
- paddingBottom: 2,
41
- paddingRight: 2,
40
+ paddingTop: microSpacing.px2,
41
+ paddingBottom: microSpacing.px2,
42
+ paddingRight: microSpacing.px2,
42
43
  },
43
44
  scrollbarHorizontal: {
44
45
  left: 0,
45
46
  right: 0,
46
47
  bottom: 0,
47
- height: 8,
48
+ height: sizes.scrollbar,
48
49
  flexDirection: 'row',
49
- paddingLeft: 2,
50
- paddingRight: 2,
51
- paddingBottom: 2,
50
+ paddingLeft: microSpacing.px2,
51
+ paddingRight: microSpacing.px2,
52
+ paddingBottom: microSpacing.px2,
52
53
  },
53
54
  scrollbarHidden: {
54
55
  opacity: 0,