@moises.ai/design-system 3.10.13 → 3.10.15

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.13",
3
+ "version": "3.10.15",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
 
17
17
  .upgradeItem:focus-visible {
18
18
  outline: 2px solid var(--neutral-alpha-8);
19
- outline-offset: -3px;
19
+ outline-offset: 2px;
20
20
  }
21
21
 
22
22
  .upgradeItem:hover {
@@ -2,6 +2,11 @@
2
2
  box-shadow: none;
3
3
  }
4
4
 
5
+ .button:focus-visible:not(.disabled):not(.loading) {
6
+ outline: 2px solid var(--neutral-alpha-8);
7
+ outline-offset: 2px;
8
+ }
9
+
5
10
  .size1 {
6
11
  border-radius: 4px;
7
12
  }
@@ -7,6 +7,11 @@
7
7
  position: relative;
8
8
  }
9
9
 
10
+ .Checkbox:focus-visible:not([disabled]) {
11
+ outline: 2px solid var(--neutral-alpha-8);
12
+ outline-offset: 2px;
13
+ }
14
+
10
15
  .Checkbox[size="1"] {
11
16
  width: 14px;
12
17
  height: 14px;
@@ -124,6 +124,11 @@
124
124
  &:active {
125
125
  color: var(--neutral-11);
126
126
  }
127
+
128
+ &:focus-visible {
129
+ outline: 2px solid var(--neutral-alpha-8);
130
+ outline-offset: 2px;
131
+ }
127
132
  }
128
133
 
129
134
  .sortButtonFirst {
@@ -318,9 +323,8 @@
318
323
  }
319
324
 
320
325
  .rowActionButton:focus-visible {
321
- outline: 2px solid var(--accent-8);
322
- outline-offset: -2px;
323
- border-radius: 6px;
326
+ outline: 2px solid var(--neutral-alpha-8);
327
+ outline-offset: 2px;
324
328
  }
325
329
 
326
330
  .DataTable :global(.rt-TableRow:hover) .projectCell:not(.dropdownColumn) :not(.artistText) {
@@ -3,6 +3,11 @@
3
3
  box-sizing: border-box;
4
4
  }
5
5
 
6
+ .iconButton:focus-visible:not(.disabled):not(.loading) {
7
+ outline: 2px solid var(--neutral-alpha-8);
8
+ outline-offset: 2px;
9
+ }
10
+
6
11
 
7
12
  .ghost.mint {
8
13
  background-color: transparent;
@@ -33,7 +33,7 @@
33
33
  }
34
34
 
35
35
  &:focus-visible {
36
- outline: 2px solid var(--neutral-alpha-6);
36
+ outline: 2px solid var(--neutral-alpha-8);
37
37
  outline-offset: 2px;
38
38
  }
39
39
 
@@ -65,7 +65,7 @@
65
65
 
66
66
  .navItem:focus-visible {
67
67
  outline: 2px solid var(--neutral-alpha-8);
68
- outline-offset: -3px;
68
+ outline-offset: 2px;
69
69
  }
70
70
 
71
71
  .navItemSelected {
@@ -13,7 +13,7 @@
13
13
 
14
14
  .userProfile:focus-visible {
15
15
  outline: 2px solid var(--neutral-alpha-8);
16
- outline-offset: -3px;
16
+ outline-offset: 2px;
17
17
  }
18
18
 
19
19
  .userProfileInner {
@@ -16,7 +16,7 @@
16
16
 
17
17
  &:focus-visible {
18
18
  outline: 2px solid var(--neutral-alpha-8);
19
- outline-offset: -1px;
19
+ outline-offset: 2px;
20
20
  }
21
21
 
22
22
  &:hover,
@@ -289,7 +289,7 @@ sectionTitle {
289
289
 
290
290
  .setlistExpandButton:focus-visible {
291
291
  outline: 2px solid var(--neutral-alpha-8);
292
- outline-offset: -1px;
292
+ outline-offset: 2px;
293
293
  }
294
294
 
295
295
  .collapsedMask {
@@ -27,14 +27,19 @@ export const Shell = ({
27
27
  children,
28
28
  }) => {
29
29
  const [collapsed, setCollapsed] = useState(false)
30
+ const [isTemporarilyExpandedByDrag, setIsTemporarilyExpandedByDrag] =
31
+ useState(false)
30
32
  const { isMobile } = useMobileDrawer()
31
33
 
32
- const effectiveCollapsed = isMobile ? false : collapsed
34
+ const effectiveCollapsed =
35
+ isMobile ? false : collapsed && !isTemporarilyExpandedByDrag
33
36
 
34
37
  return (
35
38
  <>
36
39
  <Sidebar
37
40
  isCollapsed={collapsed}
41
+ isTemporarilyExpandedByDrag={isTemporarilyExpandedByDrag}
42
+ onTemporarilyExpandedByDragChange={setIsTemporarilyExpandedByDrag}
38
43
  onCollapsedChange={setCollapsed}
39
44
  tooltip={sidebarTooltip}
40
45
  >
@@ -2,7 +2,7 @@ import { Flex } from '@radix-ui/themes'
2
2
  import { IconButton } from '../IconButton/IconButton'
3
3
  import { Tooltip } from '../Tooltip/Tooltip'
4
4
  import styles from './Sidebar.module.css'
5
- import { useState } from 'react'
5
+ import { useCallback, useEffect, useState } from 'react'
6
6
  import classNames from 'classnames'
7
7
  import {
8
8
  MoisesIcon,
@@ -18,6 +18,8 @@ export const Sidebar = ({
18
18
  className,
19
19
  children,
20
20
  isCollapsed,
21
+ isTemporarilyExpandedByDrag,
22
+ onTemporarilyExpandedByDragChange,
21
23
  onCollapsedChange,
22
24
  onLogoClick,
23
25
  tooltip = 'Expand menu',
@@ -25,12 +27,29 @@ export const Sidebar = ({
25
27
  }) => {
26
28
  const { isMobile, isOpen: mobileOpen, open, close } = useMobileDrawer()
27
29
  const [isHovered, setIsHovered] = useState(false)
30
+ const [internalTemporarilyExpandedByDrag, setInternalTemporarilyExpandedByDrag] =
31
+ useState(false)
28
32
 
29
- const effectiveCollapsed = isMobile ? false : isCollapsed
33
+ const dragExpanded =
34
+ isTemporarilyExpandedByDrag ?? internalTemporarilyExpandedByDrag
35
+
36
+ const setDragExpanded = useCallback(
37
+ (value) => {
38
+ if (isTemporarilyExpandedByDrag == null) {
39
+ setInternalTemporarilyExpandedByDrag(value)
40
+ }
41
+ onTemporarilyExpandedByDragChange?.(value)
42
+ },
43
+ [isTemporarilyExpandedByDrag, onTemporarilyExpandedByDragChange],
44
+ )
45
+
46
+ const effectiveCollapsed =
47
+ isMobile ? false : isCollapsed && !dragExpanded
30
48
 
31
49
  const handleToggleCollapse = () => {
32
50
  if (isMobile) return
33
51
  setIsHovered(false)
52
+ setDragExpanded(false)
34
53
  onCollapsedChange((prev) => !prev)
35
54
  }
36
55
 
@@ -52,9 +71,57 @@ export const Sidebar = ({
52
71
  }
53
72
  }
54
73
 
74
+ const expandForDragHover = () => {
75
+ if (isMobile || !isCollapsed) return
76
+ setDragExpanded(true)
77
+ }
78
+
79
+ const collapseAfterDrag = () => {
80
+ setDragExpanded(false)
81
+ }
82
+
83
+ const handleSidebarPointerEnter = (e) => {
84
+ handleMouseEnter()
85
+ if (e.buttons > 0) {
86
+ expandForDragHover()
87
+ }
88
+ }
89
+
90
+ const handleSidebarDragEnter = () => {
91
+ expandForDragHover()
92
+ }
93
+
94
+ const handleSidebarDragOver = (e) => {
95
+ if (isMobile || !isCollapsed) return
96
+ e.preventDefault()
97
+ expandForDragHover()
98
+ }
99
+
55
100
  const desktopLogoAriaLabel = effectiveCollapsed ? 'Expand menu' : 'Moises'
56
101
  const mobileLogoAriaLabel = 'Moises'
57
102
 
103
+ useEffect(() => {
104
+ if (!dragExpanded) return undefined
105
+
106
+ const handlePointerUp = () => {
107
+ collapseAfterDrag()
108
+ }
109
+
110
+ const handleDragEnd = () => {
111
+ collapseAfterDrag()
112
+ }
113
+
114
+ window.addEventListener('pointerup', handlePointerUp)
115
+ window.addEventListener('dragend', handleDragEnd)
116
+ window.addEventListener('drop', handleDragEnd)
117
+
118
+ return () => {
119
+ window.removeEventListener('pointerup', handlePointerUp)
120
+ window.removeEventListener('dragend', handleDragEnd)
121
+ window.removeEventListener('drop', handleDragEnd)
122
+ }
123
+ }, [dragExpanded])
124
+
58
125
  const logoContent = (
59
126
  <>
60
127
  <div
@@ -156,8 +223,11 @@ export const Sidebar = ({
156
223
  <Flex
157
224
  direction="column"
158
225
  className={styles.desktopSidebar}
159
- onMouseEnter={handleMouseEnter}
226
+ onMouseEnter={handleSidebarPointerEnter}
160
227
  onMouseLeave={handleMouseLeave}
228
+ onDragEnter={handleSidebarDragEnter}
229
+ onDragOver={handleSidebarDragOver}
230
+ onDrop={collapseAfterDrag}
161
231
  >
162
232
  {effectiveCollapsed ? (
163
233
  <div className={styles.headerWrapper}>
@@ -292,9 +292,8 @@
292
292
 
293
293
  .logoButton:focus-visible,
294
294
  .toggleButton:focus-visible {
295
- outline: 2px solid var(--accent-8);
296
- outline-offset: 4px;
297
- border-radius: 6px;
295
+ outline: 2px solid var(--neutral-alpha-8);
296
+ outline-offset: 2px;
298
297
  }
299
298
 
300
299
  .headerCollapsed {
@@ -1,5 +1,9 @@
1
1
  import { useState } from 'react'
2
2
  import { Sidebar } from './Sidebar'
3
+ import { SidebarSection } from './SidebarSection/SidebarSection'
4
+ import { ProductsList } from '../ProductsList/ProductsList'
5
+ import { SetlistList } from '../SetlistList/SetlistList'
6
+ import { Flex, Text } from '../../index'
3
7
  import {
4
8
  MoisesLogoIcon,
5
9
  SparkBarsIcon,
@@ -246,3 +250,145 @@ export const Default = {
246
250
  )
247
251
  },
248
252
  }
253
+
254
+ export const DragHoverExpand = {
255
+ render: () => {
256
+ const [isCollapsed, setIsCollapsed] = useState(true)
257
+ const [isTemporarilyExpandedByDrag, setIsTemporarilyExpandedByDrag] =
258
+ useState(false)
259
+ const [selectedProduct, setSelectedProduct] = useState('library')
260
+ const [selectedSetlist, setSelectedSetlist] = useState('setlist-1')
261
+ const [isDraggingFile, setIsDraggingFile] = useState(false)
262
+ const effectiveCollapsed = isCollapsed && !isTemporarilyExpandedByDrag
263
+
264
+ const products = [
265
+ {
266
+ id: 'library',
267
+ label: 'Library',
268
+ icon: <LibraryIcon width={16} height={16} />,
269
+ },
270
+ {
271
+ id: 'ai-studio',
272
+ label: 'AI Studio',
273
+ icon: <SparkBarsIcon width={16} height={16} />,
274
+ },
275
+ {
276
+ id: 'mastering',
277
+ label: 'Mastering',
278
+ icon: <MasteringIcon width={16} height={16} />,
279
+ },
280
+ ]
281
+
282
+ const setlists = [
283
+ {
284
+ id: 'setlist-1',
285
+ label: 'Piano Exercises',
286
+ subtitle: 'By Berklee',
287
+ },
288
+ {
289
+ id: 'setlist-2',
290
+ label: 'Band Rehearsal',
291
+ subtitle: 'By Nickyz',
292
+ },
293
+ {
294
+ id: 'setlist-3',
295
+ label: 'Gig Dec 21th',
296
+ },
297
+ ]
298
+
299
+ return (
300
+ <>
301
+ <style>{`
302
+ .SidebarDragHoverStoryLayout {
303
+ display: flex;
304
+ min-height: 100vh;
305
+ min-height: 100dvh;
306
+ background: var(--neutral-2);
307
+ }
308
+
309
+ .SidebarDragHoverStoryMain {
310
+ flex: 1;
311
+ display: flex;
312
+ align-items: center;
313
+ justify-content: center;
314
+ padding: 32px;
315
+ background: linear-gradient(180deg, var(--neutral-2) 0%, var(--neutral-1) 100%);
316
+ }
317
+
318
+ .SidebarDragHoverFile {
319
+ display: flex;
320
+ flex-direction: column;
321
+ gap: 8px;
322
+ width: 280px;
323
+ padding: 16px;
324
+ border-radius: 12px;
325
+ border: 1px solid var(--neutral-alpha-4);
326
+ background: var(--neutral-1);
327
+ box-shadow: 0 12px 24px -18px rgba(0, 0, 0, 0.45);
328
+ cursor: grab;
329
+ user-select: none;
330
+ }
331
+
332
+ .SidebarDragHoverFile[data-dragging='true'] {
333
+ opacity: 0.6;
334
+ cursor: grabbing;
335
+ }
336
+ `}</style>
337
+
338
+ <div className="SidebarDragHoverStoryLayout">
339
+ <Sidebar
340
+ isCollapsed={isCollapsed}
341
+ isTemporarilyExpandedByDrag={isTemporarilyExpandedByDrag}
342
+ onTemporarilyExpandedByDragChange={setIsTemporarilyExpandedByDrag}
343
+ onCollapsedChange={setIsCollapsed}
344
+ >
345
+ <Flex direction="column">
346
+ <SidebarSection title="PRODUCTS" collapsed={effectiveCollapsed} />
347
+ <ProductsList
348
+ products={products}
349
+ selectedProductId={selectedProduct}
350
+ onProductClick={setSelectedProduct}
351
+ collapsed={effectiveCollapsed}
352
+ />
353
+ </Flex>
354
+
355
+ <Flex
356
+ direction="column"
357
+ style={{ overflow: 'hidden', flex: 1, minHeight: 0 }}
358
+ >
359
+ <SidebarSection title="SETLISTS" collapsed={effectiveCollapsed} />
360
+ <SetlistList
361
+ setlists={setlists}
362
+ selectedSetlistId={selectedSetlist}
363
+ onSetlistClick={setSelectedSetlist}
364
+ onNewSetlistClick={() => console.log('New setlist clicked')}
365
+ collapsed={effectiveCollapsed}
366
+ />
367
+ </Flex>
368
+ </Sidebar>
369
+
370
+ <div className="SidebarDragHoverStoryMain">
371
+ <div
372
+ draggable
373
+ data-dragging={isDraggingFile}
374
+ className="SidebarDragHoverFile"
375
+ onDragStart={() => setIsDraggingFile(true)}
376
+ onDragEnd={() => {
377
+ setIsDraggingFile(false)
378
+ setIsTemporarilyExpandedByDrag(false)
379
+ }}
380
+ >
381
+ <Text size="2" weight="bold">
382
+ Drag this file to the sidebar
383
+ </Text>
384
+ <Text size="1" style={{ color: 'var(--neutral-alpha-11)' }}>
385
+ With the sidebar collapsed, drag this card over it. The sidebar should
386
+ expand on hover and collapse again when you release.
387
+ </Text>
388
+ </div>
389
+ </div>
390
+ </div>
391
+ </>
392
+ )
393
+ },
394
+ }