@moises.ai/design-system 3.10.11 → 3.10.13

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moises.ai/design-system",
3
- "version": "3.10.11",
3
+ "version": "3.10.13",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -303,6 +303,7 @@
303
303
  width: 100%;
304
304
  min-width: 0;
305
305
  min-height: 100%;
306
+ font: inherit;
306
307
  padding: 0;
307
308
  border: 0;
308
309
  background: transparent;
@@ -52,6 +52,9 @@ export const Sidebar = ({
52
52
  }
53
53
  }
54
54
 
55
+ const desktopLogoAriaLabel = effectiveCollapsed ? 'Expand menu' : 'Moises'
56
+ const mobileLogoAriaLabel = 'Moises'
57
+
55
58
  const logoContent = (
56
59
  <>
57
60
  <div
@@ -100,16 +103,24 @@ export const Sidebar = ({
100
103
  [styles.mobileTopBarOpen]: isMobile && mobileOpen,
101
104
  })}
102
105
  >
103
- <Flex
104
- align="center"
105
- gap="2"
106
- height="38px"
107
- onClick={onLogoClick}
108
- style={{ cursor: onLogoClick ? 'pointer' : 'default' }}
106
+ <button
107
+ type="button"
108
+ className={styles.logoButton}
109
+ onClick={handleLogoClick}
110
+ aria-label={mobileLogoAriaLabel}
109
111
  >
112
+ <Flex
113
+ align="center"
114
+ gap="2"
115
+ height="38px"
116
+ style={{
117
+ cursor: effectiveCollapsed || onLogoClick ? 'pointer' : 'default',
118
+ }}
119
+ >
110
120
  <MoisesLogoIcon width={32} height={17} />
111
121
  <MoisesIcon height={12.269} />
112
- </Flex>
122
+ </Flex>
123
+ </button>
113
124
 
114
125
  <IconButton
115
126
  variant="ghost"
@@ -159,24 +170,32 @@ export const Sidebar = ({
159
170
  [styles.headerCollapsed]: effectiveCollapsed,
160
171
  })}
161
172
  >
162
- <Flex
163
- align="center"
164
- gap="2"
173
+ <button
174
+ type="button"
175
+ className={styles.logoButton}
165
176
  onClick={handleLogoClick}
166
- style={{ cursor: 'pointer' }}
177
+ aria-label={desktopLogoAriaLabel}
167
178
  >
168
- {logoContent}
169
- </Flex>
170
- <Flex
171
- align="center"
172
- justify="center"
179
+ <Flex
180
+ align="center"
181
+ gap="2"
182
+ style={{
183
+ cursor: effectiveCollapsed || onLogoClick ? 'pointer' : 'default',
184
+ }}
185
+ >
186
+ {logoContent}
187
+ </Flex>
188
+ </button>
189
+ <button
190
+ type="button"
173
191
  onClick={handleToggleCollapse}
174
192
  className={classNames(styles.toggleButton, {
175
193
  [styles.toggleButtonHidden]: effectiveCollapsed,
176
194
  })}
195
+ aria-label="Collapse menu"
177
196
  >
178
197
  <SidebarLeftIcon width={16} height={16} />
179
- </Flex>
198
+ </button>
180
199
  </Flex>
181
200
  </div>
182
201
  </Tooltip>
@@ -190,24 +209,32 @@ export const Sidebar = ({
190
209
  [styles.headerCollapsed]: effectiveCollapsed,
191
210
  })}
192
211
  >
193
- <Flex
194
- align="center"
195
- gap="2"
212
+ <button
213
+ type="button"
214
+ className={styles.logoButton}
196
215
  onClick={handleLogoClick}
197
- style={{ cursor: 'pointer' }}
216
+ aria-label={desktopLogoAriaLabel}
198
217
  >
199
- {logoContent}
200
- </Flex>
201
- <Flex
202
- align="center"
203
- justify="center"
218
+ <Flex
219
+ align="center"
220
+ gap="2"
221
+ style={{
222
+ cursor: effectiveCollapsed || onLogoClick ? 'pointer' : 'default',
223
+ }}
224
+ >
225
+ {logoContent}
226
+ </Flex>
227
+ </button>
228
+ <button
229
+ type="button"
204
230
  onClick={handleToggleCollapse}
205
231
  className={classNames(styles.toggleButton, {
206
232
  [styles.toggleButtonHidden]: effectiveCollapsed,
207
233
  })}
234
+ aria-label="Collapse menu"
208
235
  >
209
236
  <SidebarLeftIcon width={16} height={16} />
210
- </Flex>
237
+ </button>
211
238
  </Flex>
212
239
  </div>
213
240
  )}
@@ -97,6 +97,14 @@
97
97
  }
98
98
 
99
99
  .toggleButton {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ justify-content: center;
103
+ padding: 0;
104
+ border: none;
105
+ background: transparent;
106
+ font: inherit;
107
+ color: inherit;
100
108
  opacity: 1;
101
109
  transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
102
110
  cursor: pointer;
@@ -262,6 +270,33 @@
262
270
  transition: padding 280ms cubic-bezier(0.4, 0, 0.2, 1);
263
271
  }
264
272
 
273
+ .logoButton {
274
+ display: inline-flex;
275
+ align-items: center;
276
+ gap: 8px;
277
+ padding: 0;
278
+ border: none;
279
+ background: transparent;
280
+ font: inherit;
281
+ color: inherit;
282
+ text-align: left;
283
+ }
284
+
285
+ .logoButton:not(:disabled) {
286
+ cursor: pointer;
287
+ }
288
+
289
+ .logoButton:disabled {
290
+ cursor: default;
291
+ }
292
+
293
+ .logoButton:focus-visible,
294
+ .toggleButton:focus-visible {
295
+ outline: 2px solid var(--accent-8);
296
+ outline-offset: 4px;
297
+ border-radius: 6px;
298
+ }
299
+
265
300
  .headerCollapsed {
266
301
  padding-left: 16px;
267
302
  }
@@ -1,4 +1,12 @@
1
- import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'
1
+ import React, {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ } from 'react'
2
10
  import { Toast } from 'radix-ui'
3
11
  import { Callout } from '../Callout/Callout'
4
12
  import styles from './ToastProvider.module.css'
@@ -30,9 +38,31 @@ export const ToastProvider = ({
30
38
  return 'neutral'
31
39
  }, [])
32
40
 
41
+ const getCalloutStyle = useCallback((variant) => {
42
+ if (variant === 'success') {
43
+ return {
44
+ backgroundColor: '#113B29',
45
+ color: '#BBFFD7',
46
+ }
47
+ }
48
+ if (variant === 'error') {
49
+ return {
50
+ backgroundColor: '#201314',
51
+ color: '#FF9592',
52
+ }
53
+ }
54
+ return undefined
55
+ }, [])
56
+
33
57
  const [toasts, setToasts] = useState([])
58
+ const timeoutIdsRef = useRef(new Map())
34
59
 
35
60
  const dismiss = useCallback((id) => {
61
+ const timeoutId = timeoutIdsRef.current.get(id)
62
+ if (timeoutId) {
63
+ clearTimeout(timeoutId)
64
+ timeoutIdsRef.current.delete(id)
65
+ }
36
66
  setToasts((prev) => prev.filter((toastItem) => toastItem.id !== id))
37
67
  }, [])
38
68
 
@@ -43,10 +73,32 @@ export const ToastProvider = ({
43
73
  ...normalized,
44
74
  id: `${Date.now()}-${toastId++}`,
45
75
  }
46
- setToasts((prev) => [...prev.slice(-(maxToasts - 1)), nextToast])
76
+
77
+ const toastDuration = nextToast.duration ?? duration
78
+ const timeoutId = setTimeout(() => {
79
+ dismiss(nextToast.id)
80
+ }, toastDuration)
81
+
82
+ timeoutIdsRef.current.set(nextToast.id, timeoutId)
83
+ setToasts((prev) => {
84
+ const nextToasts = [...prev.slice(-(maxToasts - 1)), nextToast]
85
+ const nextToastIds = new Set(nextToasts.map((toastItem) => toastItem.id))
86
+
87
+ prev.forEach((toastItem) => {
88
+ if (!nextToastIds.has(toastItem.id)) {
89
+ const staleTimeoutId = timeoutIdsRef.current.get(toastItem.id)
90
+ if (staleTimeoutId) {
91
+ clearTimeout(staleTimeoutId)
92
+ timeoutIdsRef.current.delete(toastItem.id)
93
+ }
94
+ }
95
+ })
96
+
97
+ return nextToasts
98
+ })
47
99
  return nextToast.id
48
100
  },
49
- [maxToasts],
101
+ [dismiss, duration, maxToasts],
50
102
  )
51
103
 
52
104
  const success = useCallback(
@@ -73,6 +125,13 @@ export const ToastProvider = ({
73
125
  [show, success, error, dismiss],
74
126
  )
75
127
 
128
+ useEffect(() => {
129
+ return () => {
130
+ timeoutIdsRef.current.forEach((timeoutId) => clearTimeout(timeoutId))
131
+ timeoutIdsRef.current.clear()
132
+ }
133
+ }, [])
134
+
76
135
  return (
77
136
  <ToastContext.Provider value={value}>
78
137
  <Toast.Provider
@@ -98,6 +157,7 @@ export const ToastProvider = ({
98
157
  title={toastItem.title}
99
158
  text={toastItem.description}
100
159
  className={styles.toastCallout}
160
+ style={getCalloutStyle(toastItem.variant)}
101
161
  />
102
162
  </div>
103
163
  </Toast.Description>