@moises.ai/design-system 3.10.16 → 3.10.18

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.16",
3
+ "version": "3.10.18",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -55,6 +55,7 @@ function SetlistExpandButton({
55
55
  function NewSetlistButton({
56
56
  onClick,
57
57
  className,
58
+ style,
58
59
  collapsed = false,
59
60
  text = 'New Setlist',
60
61
  }) {
@@ -76,12 +77,9 @@ function NewSetlistButton({
76
77
  </div>
77
78
  }
78
79
  text={text}
79
- className={classNames(
80
- styles.newSetlistItemButton,
81
- styles.collapsedTransition,
82
- className,
83
- )}
80
+ className={classNames(styles.newSetlistItemButton, className)}
84
81
  collapsed={collapsed}
82
+ style={style}
85
83
  />
86
84
  )
87
85
  }
@@ -307,66 +305,86 @@ export const SetlistList = ({
307
305
  onNewSetlistClick?.()
308
306
  if (isMobileDrawer) close()
309
307
  }
308
+
310
309
  const [isHoveredWhenCollapsed, setIsHoveredWhenCollapsed] = useState(false)
311
310
  const [isShrinking, setIsShrinking] = useState(false)
312
- const hoverTimeoutRef = useRef(null)
311
+ const [isExpanding, setIsExpanding] = useState(false)
312
+ const [isCollapseTransitioning, setIsCollapseTransitioning] = useState(false)
313
313
  const shrinkTimeoutRef = useRef(null)
314
+ const expandTimeoutRef = useRef(null)
314
315
  const hoverRegionRef = useRef(null)
315
- const shrinkDuration = 260
316
+ const prevCollapsedRef = useRef(collapsed)
317
+ const staggerBaseDelay = 50
318
+ const staggerItemDuration = 200
316
319
  const collapsedItemHeight = 44
317
320
  const collapsedVisibleOffset = 4
318
321
  const maxCollapsedItems = 4
319
322
  const collapsedNewItemOffset = collapsed && onNewSetlistClick ? 1 : 0
320
- const showCollapsedStack = collapsed && !isHoveredWhenCollapsed
321
- const visibleSetlists = showCollapsedStack
322
- ? setlists.slice(0, maxCollapsedItems)
323
- : setlists
323
+ const showCollapsedStack =
324
+ collapsed && !isHoveredWhenCollapsed && !isCollapseTransitioning
325
+ const visibleSetlists = setlists
326
+
327
+ const totalAnimatedItems = setlists.length + (onNewSetlistClick ? 1 : 0)
328
+ const slideItemCount = Math.min(4, totalAnimatedItems)
329
+ const slideTotalDuration =
330
+ staggerItemDuration + Math.max(0, slideItemCount - 1) * staggerBaseDelay
331
+ const staggerTotalDuration = slideTotalDuration
324
332
 
325
- const leaveCollapseDelay = 2750
333
+ const expandItems = () => {
334
+ if (shrinkTimeoutRef.current) {
335
+ clearTimeout(shrinkTimeoutRef.current)
336
+ shrinkTimeoutRef.current = null
337
+ }
338
+ if (expandTimeoutRef.current) {
339
+ clearTimeout(expandTimeoutRef.current)
340
+ expandTimeoutRef.current = null
341
+ }
342
+ setIsShrinking(false)
343
+ setIsExpanding(true)
344
+ setIsHoveredWhenCollapsed(true)
345
+ expandTimeoutRef.current = setTimeout(() => {
346
+ setIsExpanding(false)
347
+ expandTimeoutRef.current = null
348
+ }, staggerTotalDuration)
349
+ }
326
350
 
327
351
  const handleMouseEnter = () => {
328
352
  if (!collapsed) return
329
- if (hoverTimeoutRef.current) {
330
- clearTimeout(hoverTimeoutRef.current)
331
- hoverTimeoutRef.current = null
332
- }
333
353
  if (shrinkTimeoutRef.current) {
334
354
  clearTimeout(shrinkTimeoutRef.current)
335
355
  shrinkTimeoutRef.current = null
336
356
  }
337
- setIsShrinking(false)
357
+ if (isShrinking) {
358
+ setIsShrinking(false)
359
+ } else if (!isHoveredWhenCollapsed) {
360
+ expandItems()
361
+ }
338
362
  }
339
363
 
340
364
  const handleMouseLeave = () => {
341
365
  if (!collapsed) return
342
366
  if (!isHoveredWhenCollapsed) return
343
- if (hoverTimeoutRef.current) {
344
- clearTimeout(hoverTimeoutRef.current)
367
+ if (expandTimeoutRef.current) {
368
+ clearTimeout(expandTimeoutRef.current)
369
+ expandTimeoutRef.current = null
345
370
  }
346
- hoverTimeoutRef.current = setTimeout(() => {
347
- hoverTimeoutRef.current = null
348
- setIsShrinking(true)
349
- shrinkTimeoutRef.current = setTimeout(() => {
350
- shrinkTimeoutRef.current = null
351
- setIsHoveredWhenCollapsed(false)
352
- setIsShrinking(false)
353
- }, shrinkDuration)
354
- }, leaveCollapseDelay)
371
+ setIsExpanding(false)
372
+ setIsShrinking(true)
373
+ shrinkTimeoutRef.current = setTimeout(() => {
374
+ shrinkTimeoutRef.current = null
375
+ setIsHoveredWhenCollapsed(false)
376
+ setIsShrinking(false)
377
+ }, staggerTotalDuration)
355
378
  }
356
379
 
357
380
  const handleSetlistIconClick = (e) => {
358
381
  if (!collapsed) return
359
382
  e.stopPropagation()
360
- if (hoverTimeoutRef.current) {
361
- clearTimeout(hoverTimeoutRef.current)
362
- hoverTimeoutRef.current = null
363
- }
364
- setIsShrinking(false)
365
- setIsHoveredWhenCollapsed(true)
383
+ expandItems()
366
384
  }
367
385
 
368
386
  const handleFocus = () => {
369
- if (collapsed) setIsHoveredWhenCollapsed(true)
387
+ if (collapsed && !isHoveredWhenCollapsed) expandItems()
370
388
  }
371
389
 
372
390
  const handleBlur = () => {
@@ -380,10 +398,47 @@ export const SetlistList = ({
380
398
  }, 0)
381
399
  }
382
400
 
401
+ if (prevCollapsedRef.current !== collapsed) {
402
+ const wasCollapsed = prevCollapsedRef.current
403
+ prevCollapsedRef.current = collapsed
404
+
405
+ if (collapsed && !wasCollapsed) {
406
+ setIsCollapseTransitioning(true)
407
+ setIsExpanding(false)
408
+ setIsShrinking(true)
409
+ } else if (!collapsed && wasCollapsed) {
410
+ setIsHoveredWhenCollapsed(false)
411
+ setIsCollapseTransitioning(true)
412
+ setIsShrinking(false)
413
+ setIsExpanding(true)
414
+ }
415
+ }
416
+
417
+ useEffect(() => {
418
+ if (!isCollapseTransitioning) return
419
+
420
+ if (shrinkTimeoutRef.current) {
421
+ clearTimeout(shrinkTimeoutRef.current)
422
+ shrinkTimeoutRef.current = null
423
+ }
424
+ if (expandTimeoutRef.current) {
425
+ clearTimeout(expandTimeoutRef.current)
426
+ expandTimeoutRef.current = null
427
+ }
428
+
429
+ const id = setTimeout(() => {
430
+ setIsCollapseTransitioning(false)
431
+ setIsShrinking(false)
432
+ setIsExpanding(false)
433
+ }, staggerTotalDuration)
434
+
435
+ return () => clearTimeout(id)
436
+ }, [isCollapseTransitioning, staggerTotalDuration])
437
+
383
438
  useEffect(() => {
384
439
  return () => {
385
- if (hoverTimeoutRef.current) clearTimeout(hoverTimeoutRef.current)
386
440
  if (shrinkTimeoutRef.current) clearTimeout(shrinkTimeoutRef.current)
441
+ if (expandTimeoutRef.current) clearTimeout(expandTimeoutRef.current)
387
442
  }
388
443
  }, [])
389
444
 
@@ -406,6 +461,13 @@ export const SetlistList = ({
406
461
  '0 3.401px 13.603px -6.801px var(--Overlays-Black-Alpha-2, rgba(0, 0, 0, 0.10)), 0 2.551px 10.202px -3.401px var(--Overlays-Black-Alpha-2, rgba(0, 0, 0, 0.10)), 0 1.701px 2.551px -1.701px var(--Overlays-Black-Alpha-3, rgba(0, 0, 0, 0.15))',
407
462
  ]
408
463
 
464
+ const narrowingPerLevel = 1
465
+ const scale =
466
+ stackPosition === 0
467
+ ? 1
468
+ : (collapsedItemHeight - stackPosition * narrowingPerLevel * 2) /
469
+ collapsedItemHeight
470
+
409
471
  return {
410
472
  position: 'relative',
411
473
  marginTop:
@@ -414,9 +476,65 @@ export const SetlistList = ({
414
476
  : -(collapsedItemHeight - collapsedVisibleOffset),
415
477
  zIndex,
416
478
  boxShadow: boxShadows[index],
479
+ transform: scale < 1 ? `scaleX(${scale})` : undefined,
417
480
  }
418
481
  }
419
482
 
483
+ const isStaggerActive =
484
+ (collapsed && !showCollapsedStack) || isCollapseTransitioning
485
+ const itemCollapsed = collapsed || isCollapseTransitioning
486
+
487
+ const getStaggerStyle = (itemIndex) => {
488
+ if (!isStaggerActive) return undefined
489
+ const isSlideItem = itemIndex < slideItemCount
490
+
491
+ if (isShrinking) {
492
+ if (isSlideItem) {
493
+ const outY = -(
494
+ itemIndex *
495
+ (collapsedItemHeight - collapsedVisibleOffset)
496
+ )
497
+ const outScale =
498
+ itemIndex === 0
499
+ ? 1
500
+ : (collapsedItemHeight - itemIndex * 2) / collapsedItemHeight
501
+ return {
502
+ animationDelay: `${itemIndex * staggerBaseDelay}ms`,
503
+ '--stagger-out-y': `${outY}px`,
504
+ '--stagger-out-scale': outScale,
505
+ zIndex: totalAnimatedItems - itemIndex,
506
+ }
507
+ }
508
+ return {
509
+ '--fade-duration': `${slideTotalDuration}ms`,
510
+ zIndex: totalAnimatedItems - itemIndex,
511
+ }
512
+ }
513
+ if (isExpanding) {
514
+ if (isSlideItem) {
515
+ const inY = -(
516
+ itemIndex *
517
+ (collapsedItemHeight - collapsedVisibleOffset)
518
+ )
519
+ const inScale =
520
+ itemIndex === 0
521
+ ? 1
522
+ : (collapsedItemHeight - itemIndex * 2) / collapsedItemHeight
523
+ return {
524
+ animationDelay: `${(slideItemCount - 1 - itemIndex) * staggerBaseDelay}ms`,
525
+ '--stagger-in-y': `${inY}px`,
526
+ '--stagger-in-scale': inScale,
527
+ zIndex: totalAnimatedItems - itemIndex,
528
+ }
529
+ }
530
+ return {
531
+ '--fade-duration': `${slideTotalDuration}ms`,
532
+ zIndex: totalAnimatedItems - itemIndex,
533
+ }
534
+ }
535
+ return undefined
536
+ }
537
+
420
538
  return (
421
539
  <ScrollArea
422
540
  type="scroll"
@@ -439,7 +557,6 @@ export const SetlistList = ({
439
557
  className={classNames(styles.setlistsContent, {
440
558
  [styles.collapsedStack]: showCollapsedStack,
441
559
  [styles.collapsedMask]: collapsed,
442
- [styles.collapsedShrinking]: isShrinking,
443
560
  })}
444
561
  >
445
562
  {onNewSetlistClick &&
@@ -458,13 +575,20 @@ export const SetlistList = ({
458
575
  ) : (
459
576
  <NewSetlistButton
460
577
  onClick={handleNewSetlistClick}
461
- className={styles.collapsedTransition}
462
- collapsed={collapsed}
578
+ className={classNames({
579
+ [styles.staggerItem]: isStaggerActive,
580
+ [styles.staggerAnimateIn]: isStaggerActive && isExpanding,
581
+ [styles.staggerAnimateOut]: isStaggerActive && isShrinking,
582
+ })}
583
+ style={getStaggerStyle(0)}
584
+ collapsed={itemCollapsed}
463
585
  text={newSetlistButtonText}
464
586
  />
465
587
  ))}
466
588
  {visibleSetlists.map((setlist, index) => {
467
589
  const isSelected = selectedSetlistId === setlist.id
590
+ const itemStaggerIndex = index + collapsedNewItemOffset
591
+ const isSlideItem = itemStaggerIndex < slideItemCount
468
592
  const setlistItem = (
469
593
  <SetlistItem
470
594
  isSelected={isSelected}
@@ -473,9 +597,7 @@ export const SetlistList = ({
473
597
  droppable={droppable}
474
598
  isDropTarget={activeDropSetlistId === setlist.id}
475
599
  dndDroppableId={
476
- enableDndDropTargets
477
- ? `setlist:${setlist.id}`
478
- : undefined
600
+ enableDndDropTargets ? `setlist:${setlist.id}` : undefined
479
601
  }
480
602
  onDragOver={(event) => {
481
603
  onSetlistDragOver?.(setlist.id, event)
@@ -499,13 +621,30 @@ export const SetlistList = ({
499
621
  text={setlist.label}
500
622
  subtitle={setlist.subtitle}
501
623
  dropdownMenuOptions={setlist.dropdownMenuOptions}
502
- collapsed={collapsed}
624
+ collapsed={itemCollapsed}
503
625
  isMobile={isMobile}
504
626
  className={classNames({
505
627
  [styles.collapsedStackItem]: showCollapsedStack,
506
- [styles.collapsedTransition]: collapsed,
628
+ [styles.collapsedTransition]: collapsed && showCollapsedStack,
629
+ [styles.staggerItem]: isStaggerActive,
630
+ [styles.staggerAnimateIn]:
631
+ isStaggerActive && isExpanding && isSlideItem,
632
+ [styles.staggerAnimateOut]:
633
+ isStaggerActive && isShrinking && isSlideItem,
634
+ [styles.fadeAnimateIn]:
635
+ isStaggerActive && isExpanding && !isSlideItem,
636
+ [styles.fadeAnimateOut]:
637
+ isStaggerActive && isShrinking && !isSlideItem,
638
+ [styles.fadeHidden]:
639
+ !isSlideItem &&
640
+ collapsed &&
641
+ !isHoveredWhenCollapsed &&
642
+ !isCollapseTransitioning,
507
643
  })}
508
- style={getCollapsedStackStyle(index)}
644
+ style={{
645
+ ...getCollapsedStackStyle(index),
646
+ ...getStaggerStyle(itemStaggerIndex),
647
+ }}
509
648
  />
510
649
  )
511
650
  return collapsed && !showCollapsedStack ? (
@@ -157,7 +157,7 @@
157
157
  background: var(--neutral-alpha-3);
158
158
 
159
159
  &.collapsed {
160
- /* background: transparent; */
160
+ background: transparent;
161
161
 
162
162
  .avatarSetlist {
163
163
  background: var(--neutral-2);
@@ -165,8 +165,6 @@
165
165
 
166
166
  &:hover,
167
167
  &.menuOpen {
168
- background: transparent !important;
169
-
170
168
  .avatarSetlist {
171
169
  background: var(--neutral-2) !important;
172
170
  }
@@ -265,6 +263,21 @@ sectionTitle {
265
263
  position: relative;
266
264
  }
267
265
 
266
+ .collapsedStack .collapsedStackItem:not(:first-child) {
267
+ background: transparent !important;
268
+ pointer-events: none;
269
+ }
270
+
271
+ .collapsedStack .collapsedStackItem:not(:first-child) .avatarSetlist::after {
272
+ content: '';
273
+ position: absolute;
274
+ inset: 0;
275
+ background: #11111399;
276
+ border-radius: inherit;
277
+ pointer-events: none;
278
+ z-index: 2;
279
+ }
280
+
268
281
  .setlistExpandButton {
269
282
  display: flex;
270
283
  align-items: center;
@@ -298,8 +311,7 @@ sectionTitle {
298
311
  transition: max-height 260ms ease-in-out;
299
312
  }
300
313
 
301
- .collapsedMask.collapsedStack,
302
- .collapsedMask.collapsedShrinking {
314
+ .collapsedMask.collapsedStack {
303
315
  overflow: hidden;
304
316
  max-height: 120px;
305
317
  }
@@ -312,6 +324,69 @@ sectionTitle {
312
324
  transition: margin-top 260ms ease-in-out;
313
325
  }
314
326
 
327
+ @keyframes staggerIn {
328
+ from {
329
+ transform: translateY(var(--stagger-in-y, 0)) scaleX(var(--stagger-in-scale, 1));
330
+ }
331
+ to {
332
+ transform: translateY(0) scaleX(1);
333
+ }
334
+ }
335
+
336
+ @keyframes staggerOut {
337
+ from {
338
+ transform: translateY(0) scaleX(1);
339
+ }
340
+ to {
341
+ transform: translateY(var(--stagger-out-y, 0)) scaleX(var(--stagger-out-scale, 1));
342
+ }
343
+ }
344
+
345
+ .staggerItem {
346
+ opacity: 1;
347
+ transform: translateY(0);
348
+ transition: margin-top 260ms ease-in-out;
349
+ }
350
+
351
+ .staggerAnimateIn {
352
+ animation: staggerIn 200ms ease-out both;
353
+ }
354
+
355
+ .staggerAnimateOut {
356
+ animation: staggerOut 200ms ease-out both;
357
+ }
358
+
359
+ @keyframes fadeIn {
360
+ from {
361
+ opacity: 0;
362
+ }
363
+ to {
364
+ opacity: 1;
365
+ }
366
+ }
367
+
368
+ @keyframes fadeOut {
369
+ from {
370
+ opacity: 1;
371
+ }
372
+ to {
373
+ opacity: 0;
374
+ }
375
+ }
376
+
377
+ .fadeAnimateIn {
378
+ animation: fadeIn var(--fade-duration, 300ms) ease-out both;
379
+ }
380
+
381
+ .fadeAnimateOut {
382
+ animation: fadeOut var(--fade-duration, 300ms) ease-out both;
383
+ }
384
+
385
+ .fadeHidden {
386
+ opacity: 0;
387
+ pointer-events: none;
388
+ }
389
+
315
390
  .contentInner {
316
391
  gap: 12px;
317
392
  flex: 1;