@duro-app/ui 0.39.0 → 0.41.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 (85) hide show
  1. package/dist/components/ActionBar/styles.css.d.ts +2 -2
  2. package/dist/components/ActionBar/styles.css.d.ts.map +1 -1
  3. package/dist/components/Checkbox/styles.css.d.ts +2 -2
  4. package/dist/components/Checkbox/styles.css.d.ts.map +1 -1
  5. package/dist/components/ColorMode/styles.css.d.ts +2 -2
  6. package/dist/components/ColorMode/styles.css.d.ts.map +1 -1
  7. package/dist/components/Combobox/styles.css.d.ts +2 -2
  8. package/dist/components/Combobox/styles.css.d.ts.map +1 -1
  9. package/dist/components/Dialog/styles.css.d.ts +5 -5
  10. package/dist/components/Dialog/styles.css.d.ts.map +1 -1
  11. package/dist/components/Drawer/styles.css.d.ts +13 -13
  12. package/dist/components/Drawer/styles.css.d.ts.map +1 -1
  13. package/dist/components/Icon/Icon.d.ts +1 -1
  14. package/dist/components/Icon/Icon.d.ts.map +1 -1
  15. package/dist/components/Input/styles.css.d.ts +2 -2
  16. package/dist/components/Input/styles.css.d.ts.map +1 -1
  17. package/dist/components/InputGroup/styles.css.d.ts +4 -4
  18. package/dist/components/InputGroup/styles.css.d.ts.map +1 -1
  19. package/dist/components/LinkButton/styles.css.d.ts +2 -2
  20. package/dist/components/LinkButton/styles.css.d.ts.map +1 -1
  21. package/dist/components/Menu/styles.css.d.ts +2 -2
  22. package/dist/components/Menu/styles.css.d.ts.map +1 -1
  23. package/dist/components/RadioGroup/styles.css.d.ts +2 -2
  24. package/dist/components/RadioGroup/styles.css.d.ts.map +1 -1
  25. package/dist/components/ScrollArea/styles.css.d.ts +3 -3
  26. package/dist/components/ScrollArea/styles.css.d.ts.map +1 -1
  27. package/dist/components/Select/styles.css.d.ts +2 -2
  28. package/dist/components/Select/styles.css.d.ts.map +1 -1
  29. package/dist/components/SideNav/SideNav.d.ts +16 -1
  30. package/dist/components/SideNav/SideNav.d.ts.map +1 -1
  31. package/dist/components/SideNav/SideNav.meta.d.ts.map +1 -1
  32. package/dist/components/SideNav/SideNav.stories.d.ts +1 -0
  33. package/dist/components/SideNav/SideNav.stories.d.ts.map +1 -1
  34. package/dist/components/SideNav/styles.css.d.ts +54 -6
  35. package/dist/components/SideNav/styles.css.d.ts.map +1 -1
  36. package/dist/components/Switch/styles.css.d.ts +4 -4
  37. package/dist/components/Switch/styles.css.d.ts.map +1 -1
  38. package/dist/components/Table/styles.css.d.ts +2 -2
  39. package/dist/components/Table/styles.css.d.ts.map +1 -1
  40. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  41. package/dist/components/Tabs/TabsContext.d.ts +2 -0
  42. package/dist/components/Tabs/TabsContext.d.ts.map +1 -1
  43. package/dist/components/Tabs/styles.css.d.ts +33 -2
  44. package/dist/components/Tabs/styles.css.d.ts.map +1 -1
  45. package/dist/components/Tabs/useTabsRoot.d.ts.map +1 -1
  46. package/dist/components/TagGroup/styles.css.d.ts +2 -2
  47. package/dist/components/TagGroup/styles.css.d.ts.map +1 -1
  48. package/dist/components/Textarea/styles.css.d.ts +2 -2
  49. package/dist/components/Textarea/styles.css.d.ts.map +1 -1
  50. package/dist/components/Toast/styles.css.d.ts +1 -1
  51. package/dist/components/Toast/styles.css.d.ts.map +1 -1
  52. package/dist/components/Toggle/styles.css.d.ts +2 -2
  53. package/dist/components/Toggle/styles.css.d.ts.map +1 -1
  54. package/dist/index.css +1 -1
  55. package/dist/index.js +2515 -2329
  56. package/dist/index.js.map +1 -1
  57. package/package.json +2 -2
  58. package/src/components/ActionBar/styles.css.ts +3 -2
  59. package/src/components/Checkbox/styles.css.ts +3 -2
  60. package/src/components/ColorMode/styles.css.ts +3 -2
  61. package/src/components/Combobox/styles.css.ts +3 -2
  62. package/src/components/Dialog/styles.css.ts +6 -5
  63. package/src/components/Drawer/styles.css.ts +14 -13
  64. package/src/components/Icon/Icon.tsx +46 -0
  65. package/src/components/Input/styles.css.ts +3 -2
  66. package/src/components/InputGroup/styles.css.ts +5 -4
  67. package/src/components/LinkButton/styles.css.ts +3 -2
  68. package/src/components/Menu/styles.css.ts +3 -2
  69. package/src/components/RadioGroup/styles.css.ts +3 -2
  70. package/src/components/ScrollArea/styles.css.ts +4 -3
  71. package/src/components/Select/styles.css.ts +3 -2
  72. package/src/components/SideNav/SideNav.meta.ts +17 -11
  73. package/src/components/SideNav/SideNav.stories.tsx +47 -3
  74. package/src/components/SideNav/SideNav.tsx +34 -2
  75. package/src/components/SideNav/styles.css.ts +58 -7
  76. package/src/components/Switch/styles.css.ts +5 -4
  77. package/src/components/Table/styles.css.ts +3 -2
  78. package/src/components/Tabs/Tabs.tsx +52 -3
  79. package/src/components/Tabs/TabsContext.ts +6 -0
  80. package/src/components/Tabs/styles.css.ts +41 -2
  81. package/src/components/Tabs/useTabsRoot.ts +12 -2
  82. package/src/components/TagGroup/styles.css.ts +3 -2
  83. package/src/components/Textarea/styles.css.ts +3 -2
  84. package/src/components/Toast/styles.css.ts +2 -1
  85. package/src/components/Toggle/styles.css.ts +3 -2
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  root: {
@@ -34,8 +35,8 @@ export const styles = css.create({
34
35
  borderWidth: 0,
35
36
  cursor: 'pointer',
36
37
  transitionProperty: 'color',
37
- transitionDuration: '150ms',
38
- transitionTimingFunction: 'ease',
38
+ transitionDuration: duration.fast,
39
+ transitionTimingFunction: easing.standard,
39
40
  },
40
41
  groupTriggerActive: {
41
42
  color: colors.text,
@@ -44,18 +45,37 @@ export const styles = css.create({
44
45
  display: 'inline-flex',
45
46
  alignItems: 'center',
46
47
  transitionProperty: 'transform',
47
- transitionDuration: '150ms',
48
- transitionTimingFunction: 'ease',
48
+ transitionDuration: duration.fast,
49
+ transitionTimingFunction: easing.standard,
49
50
  },
50
51
  chevronOpen: {
51
52
  transform: 'rotate(90deg)',
52
53
  },
54
+ // Static (non-collapsible) section — see SideNav.Section.
55
+ section: {
56
+ display: 'flex',
57
+ flexDirection: 'column',
58
+ },
59
+ sectionLabel: {
60
+ paddingTop: spacing.md,
61
+ paddingBottom: spacing.xs,
62
+ paddingLeft: spacing.md,
63
+ paddingRight: spacing.md,
64
+ fontFamily: typography.fontFamily,
65
+ fontSize: typography.fontSizeXs,
66
+ fontWeight: typography.fontWeightSemibold,
67
+ textTransform: 'uppercase' as const,
68
+ letterSpacing: '0.06em',
69
+ color: colors.textMuted,
70
+ },
53
71
  item: {
72
+ position: 'relative',
54
73
  display: 'flex',
55
74
  alignItems: 'center',
75
+ gap: spacing.sm,
56
76
  paddingTop: '6px',
57
77
  paddingBottom: '6px',
58
- paddingLeft: spacing.lg,
78
+ paddingLeft: spacing.md,
59
79
  paddingRight: spacing.md,
60
80
  fontFamily: typography.fontFamily,
61
81
  fontSize: typography.fontSizeSm,
@@ -72,8 +92,8 @@ export const styles = css.create({
72
92
  borderRadius: radii.sm,
73
93
  cursor: 'pointer',
74
94
  transitionProperty: 'color, background-color',
75
- transitionDuration: '150ms',
76
- transitionTimingFunction: 'ease',
95
+ transitionDuration: duration.fast,
96
+ transitionTimingFunction: easing.standard,
77
97
  textAlign: 'left' as const,
78
98
  outlineWidth: {
79
99
  default: 0,
@@ -91,5 +111,36 @@ export const styles = css.create({
91
111
  itemActive: {
92
112
  color: colors.accent,
93
113
  fontWeight: typography.fontWeightMedium,
114
+ backgroundColor: colors.bgCardHover,
115
+ },
116
+ // Active indicator — a bar at the rail's left edge that grows in on select.
117
+ marker: {
118
+ position: 'absolute',
119
+ left: 0,
120
+ top: '50%',
121
+ width: '3px',
122
+ height: 0,
123
+ transform: 'translateY(-50%)',
124
+ borderTopRightRadius: radii.full,
125
+ borderBottomRightRadius: radii.full,
126
+ backgroundColor: colors.accent,
127
+ transitionProperty: 'height',
128
+ transitionDuration: duration.fast,
129
+ transitionTimingFunction: easing.standard,
130
+ },
131
+ markerActive: {
132
+ height: '18px',
133
+ },
134
+ itemIcon: {
135
+ display: 'inline-flex',
136
+ alignItems: 'center',
137
+ justifyContent: 'center',
138
+ flexShrink: 0,
139
+ width: '18px',
140
+ height: '18px',
141
+ },
142
+ itemLabel: {
143
+ flexGrow: 1,
144
+ minWidth: 0,
94
145
  },
95
146
  })
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  root: {
@@ -26,8 +27,8 @@ export const styles = css.create({
26
27
  padding: 0,
27
28
  cursor: 'inherit',
28
29
  transitionProperty: 'background-color',
29
- transitionDuration: '150ms',
30
- transitionTimingFunction: 'ease',
30
+ transitionDuration: duration.fast,
31
+ transitionTimingFunction: easing.standard,
31
32
  outlineWidth: {default: 0, ':focus-visible': 2},
32
33
  outlineStyle: 'solid',
33
34
  outlineColor: colors.accent,
@@ -55,8 +56,8 @@ export const styles = css.create({
55
56
  borderRadius: radii.full,
56
57
  backgroundColor: '#fff',
57
58
  transitionProperty: 'transform',
58
- transitionDuration: '150ms',
59
- transitionTimingFunction: 'ease',
59
+ transitionDuration: duration.fast,
60
+ transitionTimingFunction: easing.standard,
60
61
  },
61
62
  thumbChecked: {
62
63
  transform: 'translateX(16px)',
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  // Container-query thresholds. Picked for typical 5-7 column admin tables —
7
8
  // see Table.stories.tsx "Responsive" for the visual reasoning. Defined
@@ -129,8 +130,8 @@ export const styles = css.create({
129
130
  ':hover': colors.bgCardHover,
130
131
  },
131
132
  transitionProperty: 'background-color',
132
- transitionDuration: '150ms',
133
- transitionTimingFunction: 'ease',
133
+ transitionDuration: duration.fast,
134
+ transitionTimingFunction: easing.standard,
134
135
  // Stack-mode card chrome
135
136
  padding: {
136
137
  default: 0,
@@ -1,4 +1,4 @@
1
- import {type ReactNode, useRef, useId, useEffect} from 'react'
1
+ import {type ReactNode, useRef, useId, useEffect, useLayoutEffect, useState} from 'react'
2
2
  import {html} from 'react-strict-dom'
3
3
  import {styles} from './styles.css'
4
4
  import {TabsContext, useTabs} from './TabsContext'
@@ -39,8 +39,44 @@ interface ListProps {
39
39
  }
40
40
 
41
41
  function List({children}: ListProps) {
42
- const {orientation, activeValue, onSelect, tabsRef, orderRef} = useTabs()
42
+ const {orientation, activeValue, onSelect, tabsRef, orderRef, setIndicatorActive} = useTabs()
43
43
  const listRef = useRef<HTMLDivElement>(null)
44
+ const [indicator, setIndicator] = useState<{offset: number; size: number} | null>(null)
45
+
46
+ // Measure the active tab and drive the sliding indicator. useLayoutEffect so
47
+ // the first position is set before paint (the indicator element mounts already
48
+ // in place — no slide-in from zero; only later tab changes animate). Observes
49
+ // the active tab (its own size, e.g. a changing "(3)" count) and the list
50
+ // (container resize / reflow). A non-active sibling resizing while you're on
51
+ // another tab is the one case not caught; it self-corrects on the next
52
+ // selection or resize.
53
+ useLayoutEffect(() => {
54
+ const list = listRef.current
55
+ if (!list || !activeValue) {
56
+ setIndicator(null)
57
+ setIndicatorActive(false)
58
+ return
59
+ }
60
+ const el = list.querySelector<HTMLElement>(`[data-tab-value="${CSS.escape(activeValue)}"]`)
61
+ if (!el) {
62
+ setIndicator(null)
63
+ setIndicatorActive(false)
64
+ return
65
+ }
66
+ const measure = () => {
67
+ setIndicator(
68
+ orientation === 'horizontal'
69
+ ? {offset: el.offsetLeft, size: el.offsetWidth}
70
+ : {offset: el.offsetTop, size: el.offsetHeight},
71
+ )
72
+ setIndicatorActive(true)
73
+ }
74
+ measure()
75
+ const ro = new ResizeObserver(measure)
76
+ ro.observe(el)
77
+ ro.observe(list)
78
+ return () => ro.disconnect()
79
+ }, [activeValue, orientation, setIndicatorActive])
44
80
 
45
81
  useEffect(() => {
46
82
  const el = listRef.current
@@ -128,6 +164,18 @@ function List({children}: ListProps) {
128
164
  style={[styles.list, orientation === 'vertical' && styles.listVertical]}
129
165
  >
130
166
  {children}
167
+ {indicator && (
168
+ <html.div
169
+ aria-hidden
170
+ style={[
171
+ styles.indicator,
172
+ orientation === 'horizontal' ? styles.indicatorHorizontal : styles.indicatorVertical,
173
+ orientation === 'horizontal'
174
+ ? styles.indicatorOffsetH(indicator.offset, indicator.size)
175
+ : styles.indicatorOffsetV(indicator.offset, indicator.size),
176
+ ]}
177
+ />
178
+ )}
131
179
  </html.div>
132
180
  )
133
181
  }
@@ -141,7 +189,7 @@ interface TabProps {
141
189
  }
142
190
 
143
191
  function Tab({value, disabled = false, children}: TabProps) {
144
- const {activeValue, onSelect, orientation, registerTab} = useTabs()
192
+ const {activeValue, onSelect, orientation, registerTab, indicatorActive} = useTabs()
145
193
  const isActive = activeValue === value
146
194
  const tabId = useId()
147
195
  const panelId = `${tabId}-panel`
@@ -172,6 +220,7 @@ function Tab({value, disabled = false, children}: TabProps) {
172
220
  orientation === 'vertical' && styles.tabVertical,
173
221
  isActive &&
174
222
  (orientation === 'vertical' ? styles.tabActiveVertical : styles.tabActiveHorizontal),
223
+ isActive && indicatorActive && styles.tabIndicatorActive,
175
224
  disabled && styles.tabDisabled,
176
225
  ]}
177
226
  >
@@ -9,6 +9,12 @@ export interface TabsContextValue {
9
9
  registerTab: (value: string, disabled: boolean) => () => void
10
10
  tabsRef: React.RefObject<Map<string, boolean>>
11
11
  orderRef: React.RefObject<string[]>
12
+ // True once the List has measured the active tab and is driving a sliding
13
+ // indicator. Tabs suppress their own accent border while it's true so the
14
+ // single sliding bar is the only underline; it stays false without JS
15
+ // (SSR / no-hydration), where the per-tab border is the graceful fallback.
16
+ indicatorActive: boolean
17
+ setIndicatorActive: (active: boolean) => void
12
18
  }
13
19
 
14
20
  export const TabsContext = createContext<TabsContextValue | null>(null)
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  root: {
@@ -18,6 +19,8 @@ export const styles = css.create({
18
19
  borderBottomStyle: 'solid',
19
20
  borderBottomColor: colors.border,
20
21
  gap: spacing.xs,
22
+ // Positioning context for the sliding indicator.
23
+ position: 'relative',
21
24
  },
22
25
  listVertical: {
23
26
  flexDirection: 'column',
@@ -49,8 +52,8 @@ export const styles = css.create({
49
52
  borderBottomColor: 'transparent',
50
53
  cursor: 'pointer',
51
54
  transitionProperty: 'color, border-color',
52
- transitionDuration: '150ms',
53
- transitionTimingFunction: 'ease',
55
+ transitionDuration: duration.fast,
56
+ transitionTimingFunction: easing.standard,
54
57
  outlineWidth: {
55
58
  default: 0,
56
59
  ':focus-visible': 2,
@@ -83,6 +86,42 @@ export const styles = css.create({
83
86
  color: colors.text,
84
87
  borderRightColor: colors.accent,
85
88
  },
89
+ // Applied to the active tab once JS drives the sliding indicator: drop the
90
+ // per-tab accent border so the single sliding bar is the only underline
91
+ // (avoids a double line and an instant-pop that would undercut the slide).
92
+ tabIndicatorActive: {
93
+ borderBottomColor: 'transparent',
94
+ borderRightColor: 'transparent',
95
+ },
96
+ // --- Sliding active indicator (positioned by measuring the active tab) ---
97
+ indicator: {
98
+ position: 'absolute',
99
+ backgroundColor: colors.accent,
100
+ pointerEvents: 'none',
101
+ transitionProperty: 'transform, width, height',
102
+ transitionDuration: duration.base,
103
+ transitionTimingFunction: easing.easeOut,
104
+ },
105
+ indicatorHorizontal: {
106
+ bottom: -1,
107
+ left: 0,
108
+ height: 2,
109
+ },
110
+ indicatorVertical: {
111
+ right: -1,
112
+ top: 0,
113
+ width: 2,
114
+ },
115
+ // Dynamic transform/size from the measured active tab (StyleX dynamic style:
116
+ // simple identifier params only).
117
+ indicatorOffsetH: (offset: number, size: number) => ({
118
+ transform: `translateX(${offset}px)`,
119
+ width: size,
120
+ }),
121
+ indicatorOffsetV: (offset: number, size: number) => ({
122
+ transform: `translateY(${offset}px)`,
123
+ height: size,
124
+ }),
86
125
  tabDisabled: {
87
126
  opacity: 0.5,
88
127
  cursor: 'not-allowed',
@@ -1,4 +1,4 @@
1
- import {useCallback, useRef} from 'react'
1
+ import {useCallback, useRef, useState} from 'react'
2
2
  import {useControllableValue} from '../../hooks/useControllableValue'
3
3
  import type {Orientation, TabsContextValue} from './TabsContext'
4
4
 
@@ -26,6 +26,7 @@ export function useTabsRoot({
26
26
  )
27
27
  const tabsRef = useRef(new Map<string, boolean>())
28
28
  const orderRef = useRef<string[]>([])
29
+ const [indicatorActive, setIndicatorActive] = useState(false)
29
30
 
30
31
  const registerTab = useCallback((value: string, disabled: boolean) => {
31
32
  tabsRef.current.set(value, disabled)
@@ -38,5 +39,14 @@ export function useTabsRoot({
38
39
  }
39
40
  }, [])
40
41
 
41
- return {activeValue, onSelect, orientation, registerTab, tabsRef, orderRef}
42
+ return {
43
+ activeValue,
44
+ onSelect,
45
+ orientation,
46
+ registerTab,
47
+ tabsRef,
48
+ orderRef,
49
+ indicatorActive,
50
+ setIndicatorActive,
51
+ }
42
52
  }
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  root: {
@@ -48,8 +49,8 @@ export const styles = css.create({
48
49
  paddingRight: spacing.sm,
49
50
  minHeight: 40,
50
51
  transitionProperty: 'border-color',
51
- transitionDuration: '150ms',
52
- transitionTimingFunction: 'ease',
52
+ transitionDuration: duration.fast,
53
+ transitionTimingFunction: easing.standard,
53
54
  outlineWidth: {
54
55
  default: 0,
55
56
  ':focus': 2,
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  base: {
@@ -20,8 +21,8 @@ export const styles = css.create({
20
21
  borderRadius: radii.sm,
21
22
  resize: 'vertical' as const,
22
23
  transitionProperty: 'border-color',
23
- transitionDuration: '150ms',
24
- transitionTimingFunction: 'ease',
24
+ transitionDuration: duration.fast,
25
+ transitionTimingFunction: easing.standard,
25
26
  outlineWidth: {
26
27
  default: 0,
27
28
  ':focus-visible': 2,
@@ -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 {shadows} from '@duro-app/tokens/tokens/shadows.css'
6
+ import {easing} from '@duro-app/tokens/tokens/motion.css'
6
7
 
7
8
  const enter = css.keyframes({
8
9
  from: {opacity: 0, transform: 'translateY(10px)'},
@@ -51,7 +52,7 @@ export const styles = css.create({
51
52
  '@media (prefers-reduced-motion: reduce)': 'none',
52
53
  },
53
54
  animationDuration: '160ms',
54
- animationTimingFunction: 'ease-out',
55
+ animationTimingFunction: easing.easeOut,
55
56
  },
56
57
  success: {borderLeftColor: colors.successBorder},
57
58
  error: {borderLeftColor: colors.errorBorder},
@@ -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 {typography} from '@duro-app/tokens/tokens/typography.css'
5
+ import {duration, easing} from '@duro-app/tokens/tokens/motion.css'
5
6
 
6
7
  export const styles = css.create({
7
8
  base: {
@@ -14,8 +15,8 @@ export const styles = css.create({
14
15
  fontFamily: typography.fontFamily,
15
16
  fontWeight: typography.fontWeightMedium,
16
17
  transitionProperty: 'background-color, border-color, color, opacity',
17
- transitionDuration: '150ms',
18
- transitionTimingFunction: 'ease',
18
+ transitionDuration: duration.fast,
19
+ transitionTimingFunction: easing.standard,
19
20
  outlineWidth: {default: 0, ':focus-visible': 2},
20
21
  outlineStyle: 'solid',
21
22
  outlineColor: colors.accent,