@moises.ai/design-system 4.16.2 → 4.16.3

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": "4.16.2",
3
+ "version": "4.16.3",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -1,14 +1,15 @@
1
1
  import { Flex } from '@radix-ui/themes'
2
- import styles from './DropdownButton.module.css'
3
2
  import classNames from 'classnames'
4
3
  import { Popover } from 'radix-ui'
5
- import { Button } from '../Button/Button'
6
- import { ChevronDownIcon } from '../../icons/ChevronDownIcon'
7
4
  import { useState } from 'react'
5
+ import { ChevronDownIcon } from '../../icons/ChevronDownIcon'
6
+ import { Button } from '../Button/Button'
7
+ import styles from './DropdownButton.module.css'
8
8
 
9
9
  export const DropdownButton = ({
10
10
  children,
11
11
  trigger,
12
+ withIconTrigger = true,
12
13
  className,
13
14
  showSeparator = true,
14
15
  onTriggerClick,
@@ -36,13 +37,10 @@ export const DropdownButton = ({
36
37
  className={classNames({
37
38
  [styles.triggerWithClick]: onTriggerClick,
38
39
  [styles.hasLeftColor]: leftColor,
40
+ [styles.freeWidthTrigger]: !withIconTrigger,
39
41
  })}
40
- onMouseEnter={() => {
41
- setHover(true)
42
- }}
43
- onMouseLeave={() => {
44
- setHover(false)
45
- }}
42
+ onMouseEnter={() => setHover(true)}
43
+ onMouseLeave={() => setHover(false)}
46
44
  onClick={handleTriggerClick}
47
45
  >
48
46
  <Button
@@ -52,9 +50,9 @@ export const DropdownButton = ({
52
50
  padding: leftColor
53
51
  ? '8px 10px'
54
52
  : showSeparator
55
- ? '0px 8px 0 6px'
56
- : '0 6px',
57
- width: '32px',
53
+ ? '0px 8px 0 6px'
54
+ : '0 6px',
55
+ width: withIconTrigger ? '32px' : undefined,
58
56
  backgroundColor: leftColor,
59
57
  borderRadius: leftColor ? '3px' : '0px',
60
58
  }}
@@ -86,8 +84,8 @@ export const DropdownButton = ({
86
84
  padding: leftColor
87
85
  ? '8px 10px'
88
86
  : showSeparator
89
- ? '0px 8px 0 6px'
90
- : '0 6px',
87
+ ? '0px 8px 0 6px'
88
+ : '0 6px',
91
89
  backgroundColor: leftColor,
92
90
  borderRadius: leftColor ? '3px' : '0px',
93
91
  }}
@@ -113,7 +111,11 @@ export const DropdownButton = ({
113
111
  />
114
112
  </div>
115
113
  </Popover.Trigger>
116
- <Popover.Content className={styles.content} sideOffset={5}>
114
+ <Popover.Content
115
+ className={styles.content}
116
+ sideOffset={5}
117
+ onCloseAutoFocus={(event) => event.preventDefault()}
118
+ >
117
119
  {children}
118
120
  </Popover.Content>
119
121
  </Popover.Root>
@@ -5,7 +5,7 @@
5
5
  align-items: center;
6
6
  padding: 4px;
7
7
 
8
- border: 1px solid var(--neutral-alpha-3);
8
+ border: 1px solid var(--neutral-alpha-3);
9
9
 
10
10
  &.hasLeftColor {
11
11
  padding: 0px 4px 0px 0px;
@@ -13,12 +13,11 @@
13
13
 
14
14
  &.triggerWithClick {
15
15
  cursor: pointer;
16
-
17
- }
16
+ }
18
17
  }
19
18
 
20
19
  .triggerWithClick {
21
- border-width: 1px 0 1px 1px; /* top right bottom left */
20
+ border-width: 1px 0 1px 1px; /* top right bottom left */
22
21
  border-style: solid;
23
22
  border-color: var(--neutral-alpha-3);
24
23
  display: flex;
@@ -39,8 +38,12 @@
39
38
  }
40
39
  }
41
40
 
41
+ .triggerWithClick.freeWidthTrigger {
42
+ width: auto;
43
+ }
44
+
42
45
  .hasTriggerWithClick {
43
- border-width: 1px 1px 1px 0; /* top right bottom left */
46
+ border-width: 1px 1px 1px 0; /* top right bottom left */
44
47
  border-style: solid;
45
48
  border-color: var(--neutral-alpha-3);
46
49
  display: flex;
@@ -52,7 +55,6 @@
52
55
  justify-content: center !important;
53
56
  align-items: center;
54
57
  padding: 0 4px 0 0;
55
-
56
58
  }
57
59
 
58
60
  .hover {
@@ -86,7 +88,9 @@
86
88
  border-radius: 8px;
87
89
  border: 1px solid var(--neutral-alpha-3);
88
90
  background: var(--panel-solid);
89
- box-shadow: 0px 12px 32px -16px rgba(0, 0, 0, 0.30), 0px 12px 60px 0px rgba(0, 0, 0, 0.15);
91
+ box-shadow:
92
+ 0px 12px 32px -16px rgba(0, 0, 0, 0.3),
93
+ 0px 12px 60px 0px rgba(0, 0, 0, 0.15);
90
94
 
91
95
  display: flex;
92
96
  width: fit-content;
@@ -163,4 +167,4 @@
163
167
 
164
168
  .chevron {
165
169
  color: var(--neutral-alpha-11);
166
- }
170
+ }
@@ -0,0 +1,249 @@
1
+ import classNames from 'classnames'
2
+ import {
3
+ MusicNoteIcon,
4
+ PlayIcon,
5
+ More2Icon,
6
+ Volume2Icon,
7
+ RewindBarFillIcon,
8
+ ForwardBarFillIcon,
9
+ PauseFilledIcon,
10
+ PlayOnRepeatIcon,
11
+ KaraokeMicIcon,
12
+ ChordsDetectionIcon,
13
+ MetronomeIcon,
14
+ ChevronDownIcon,
15
+ Share2Icon,
16
+ Video2Icon,
17
+ ChevronUpIcon,
18
+ } from '../../icons'
19
+ import { Text, Flex, IconButton, DropdownMenu, DropdownButton, Separator, Popover } from '../../index'
20
+ import styles from './PlayerBar.module.css'
21
+ import { PlayerSlider } from '../PlayerSlider/PlayerSlider'
22
+
23
+
24
+ const formatTime = (time) => {
25
+ const totalSeconds = Math.floor(time)
26
+ const minutes = Math.floor(totalSeconds / 60)
27
+ const seconds = totalSeconds % 60
28
+ return `${minutes}:${seconds.toString().padStart(2, '0')}`
29
+ }
30
+
31
+ export const PlayerBar = ({
32
+ title = 'Untitled track',
33
+ subtitle,
34
+ cover,
35
+ menuOptions,
36
+ showSlider = true,
37
+ color = 'gray', // can be 'gray' or 'dark'
38
+ className,
39
+ // playback time
40
+ currentTime = 0,
41
+ duration = 0,
42
+ // transport
43
+ onSeekBackward,
44
+ onSeekForward,
45
+ onPlayPause,
46
+ isPlaying = false,
47
+ // timeline
48
+ audio,
49
+ onSeek,
50
+ // version dropdown
51
+ versionTrigger,
52
+ versionContent,
53
+ // tempo and pitch dropdown
54
+ tempoPitchContent,
55
+ tempo,
56
+ pitch,
57
+ // metronome dropdown
58
+ metronomeContent,
59
+ metronomeEnabled,
60
+ onMetronomeToggle,
61
+ // volume popover
62
+ volumeContent,
63
+ onVolumeClick,
64
+ // lyrics
65
+ lyricsEnabled,
66
+ onLyricsToggle,
67
+ // chords detection
68
+ chordsEnabled = false,
69
+ onChordsToggle,
70
+ // loop
71
+ loopEnabled,
72
+ onLoopToggle,
73
+ // video and share
74
+ onVideoClick,
75
+ onShareClick,
76
+ // expand
77
+ expanded,
78
+ onExpandToggle,
79
+ }) => {
80
+ return (
81
+ <section
82
+ aria-label="Player controls"
83
+ className={classNames(styles.playerBarContainer, className)}
84
+ >
85
+ {showSlider && (
86
+ <PlayerSlider
87
+ currentTime={currentTime}
88
+ duration={duration}
89
+ audio={audio}
90
+ onSeek={onSeek}
91
+ />
92
+ )}
93
+ <Flex
94
+ gap="6"
95
+ className={classNames(styles.playerBar, {
96
+ [styles.gray]: color === 'gray',
97
+ [styles.dark]: color === 'dark',
98
+ })}
99
+ align="start"
100
+ >
101
+ <Flex align="center" gap="3" className={styles.flex2}>
102
+ <Flex align="center" gap="4">
103
+ {cover ? (
104
+ <img src={cover} alt="Cover" className={styles.cover} />
105
+ ) : (
106
+ <div className={styles.cover}>
107
+ <MusicNoteIcon width={16} height={16} />
108
+ </div>
109
+ )}
110
+ </Flex>
111
+ <Flex gap="3" pt="5px" align="start">
112
+ <Flex direction="column" gap="0" className={styles.trackMeta}>
113
+ <Text size="2" weight="medium" className={classNames(styles.trackLabel, styles.neutral12)}>
114
+ {title}
115
+ </Text>
116
+ {subtitle ? (
117
+ <Text size="1" weight="regular" className={classNames(styles.trackLabel, styles.neutralAlpha10)}>
118
+ {subtitle}
119
+ </Text>
120
+ ) : null}
121
+ </Flex>
122
+ <Flex align="center" gap="2">{menuOptions && (
123
+ <DropdownMenu
124
+ trigger={
125
+ <IconButton variant="ghost" size="2" className={styles.menuOptionsTrigger}>
126
+ <More2Icon width={16} height={16} />
127
+ </IconButton>}
128
+ options={menuOptions}
129
+ />
130
+ )}
131
+ {versionContent && versionTrigger && (
132
+ <DropdownButton trigger={versionTrigger} showSeparator={false} className={styles.customDropdownButton}>
133
+ {versionContent}
134
+ </DropdownButton>
135
+ )}
136
+ </Flex>
137
+ </Flex>
138
+
139
+ </Flex>
140
+
141
+ <Flex className={styles.flex1} direction="column" gap="0" align="center">
142
+ <Flex align="center" gap="3">
143
+ <Popover.Root>
144
+ <Popover.Trigger>
145
+ <IconButton variant="ghost" size="2" onClick={onVolumeClick}>
146
+ <Volume2Icon width={16} height={16} />
147
+ </IconButton>
148
+ </Popover.Trigger>
149
+ <Popover.Content>
150
+ {volumeContent}
151
+ </Popover.Content>
152
+ </Popover.Root>
153
+ <Flex gap='0' >
154
+ <IconButton variant="ghost" size="4" onClick={onSeekBackward} className={styles.controlsIconButton}>
155
+ <RewindBarFillIcon width={30} height={30} />
156
+ </IconButton>
157
+ <IconButton variant="ghost" size="4" onClick={onPlayPause} className={styles.controlsIconButton}>
158
+ {isPlaying ? <PauseFilledIcon width={30} height={30} /> : <PlayIcon width={30} height={30} />}
159
+ </IconButton>
160
+ <IconButton variant="ghost" size="4" onClick={onSeekForward} className={styles.controlsIconButton}>
161
+ <ForwardBarFillIcon width={30} height={30} />
162
+ </IconButton>
163
+ </Flex>
164
+ <IconButton variant="ghost" size="2" onClick={onLoopToggle}>
165
+ <PlayOnRepeatIcon width={16} height={16}
166
+ className={classNames({
167
+ [styles.actionIconActive]: !loopEnabled,
168
+ [styles.actionIconDefault]: loopEnabled
169
+ })}
170
+ />
171
+ </IconButton>
172
+ </Flex>
173
+ <Text size="1" weight="regular" className={styles.neutralAlpha10}>
174
+ {formatTime(currentTime)} / {formatTime(duration)}
175
+ </Text>
176
+ </Flex>
177
+
178
+ <Flex align="center" gap="3" className={classNames(styles.flex2, styles.actionsContainer)}>
179
+ {tempoPitchContent && (
180
+ <DropdownButton trigger={
181
+ <Text className={styles.neutralAlpha11}>
182
+ {tempo} bpm
183
+ <Text className={styles.neutralAlpha6}> / </Text>
184
+ {pitch}
185
+ </Text>
186
+ } showSeparator={false} className={styles.customDropdownButton}>
187
+ {tempoPitchContent}
188
+ </DropdownButton>
189
+ )}
190
+ {metronomeContent && (
191
+ <DropdownButton
192
+ trigger={
193
+ <MetronomeIcon width={16} height={16}
194
+ className={classNames({
195
+ [styles.actionIconActive]: !metronomeEnabled,
196
+ [styles.actionIconDefault]: metronomeEnabled
197
+ })}
198
+ />
199
+ }
200
+ onTriggerClick={onMetronomeToggle}
201
+ >
202
+ {metronomeContent}
203
+ </DropdownButton>
204
+ )}
205
+ {onLyricsToggle && (
206
+ <IconButton variant="ghost" size="2" onClick={onLyricsToggle}>
207
+ <KaraokeMicIcon width={16} height={16}
208
+ className={classNames({
209
+ [styles.actionIconActive]: !lyricsEnabled,
210
+ [styles.actionIconDefault]: lyricsEnabled
211
+ })}
212
+ />
213
+ </IconButton>
214
+ )}
215
+ {onChordsToggle && (
216
+ <IconButton variant="ghost" size="2" onClick={onChordsToggle}>
217
+ <ChordsDetectionIcon width={16} height={16}
218
+ className={classNames({
219
+ [styles.actionIconActive]: !chordsEnabled,
220
+ [styles.actionIconDefault]: chordsEnabled
221
+ })} />
222
+ </IconButton>
223
+ )}
224
+ {onVideoClick && (
225
+ <IconButton variant="ghost" size="2" onClick={onVideoClick}>
226
+ <Video2Icon width={16} height={16} />
227
+ </IconButton>
228
+ )}
229
+
230
+ <Separator orientation="vertical" />
231
+
232
+ {onShareClick && (
233
+ <IconButton variant="ghost" size="2" onClick={onShareClick}>
234
+ <Share2Icon width={16} height={16} />
235
+ </IconButton>
236
+ )}
237
+
238
+ {onExpandToggle && (
239
+ <IconButton variant="soft" color={expanded ? 'accent' : 'neutral'} size="2" onClick={onExpandToggle}>
240
+ {expanded ? <ChevronDownIcon width={16} height={16} /> : <ChevronUpIcon width={16} height={16} />}
241
+ </IconButton>
242
+ )}
243
+ </Flex>
244
+ </Flex>
245
+ </section >
246
+ )
247
+ }
248
+
249
+ PlayerBar.displayName = 'PlayerBar'
@@ -0,0 +1,135 @@
1
+ .playerBar {
2
+ width: 100%;
3
+ padding: 20px 20px 12px 20px;
4
+ }
5
+
6
+ .playerBarContainer {
7
+ position: relative;
8
+ width: 100%;
9
+ }
10
+
11
+ .playerBarContainer:has([data-interacting='true']) {
12
+ z-index: 1;
13
+ }
14
+
15
+ .playerBar.gray {
16
+ background: var(--neutral-2);
17
+ }
18
+
19
+ .playerBar.dark {
20
+ background: var(--neutral-1);
21
+ }
22
+
23
+ .cover {
24
+ display: flex;
25
+ width: 48px;
26
+ height: 48px;
27
+ justify-content: center;
28
+ align-items: center;
29
+ gap: 8px;
30
+ aspect-ratio: 1/1;
31
+ background: var(--neutral-alpha-3);
32
+ border-radius: 6px;
33
+ }
34
+
35
+ .trackMeta {
36
+ min-width: 0;
37
+ }
38
+
39
+ .trackLabel {
40
+ display: block;
41
+ max-width: 89px;
42
+ min-width: 89px;
43
+ overflow: hidden;
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ }
47
+
48
+ .neutral12 {
49
+ color: var(--neutral-12);
50
+ }
51
+
52
+ .neutralAlpha10 {
53
+ color: var(--neutral-alpha-10);
54
+ }
55
+
56
+ .neutralAlpha8 {
57
+ color: var(--neutral-alpha-8);
58
+ }
59
+
60
+ .neutralAlpha11 {
61
+ color: var(--neutral-alpha-11);
62
+ }
63
+
64
+ .neutralAlpha6 {
65
+ color: var(--neutral-alpha-6);
66
+ }
67
+
68
+ .menuOptionsTrigger {
69
+ svg {
70
+ color: var(--neutral-alpha-8);
71
+ }
72
+
73
+ &:hover {
74
+ svg {
75
+ color: var(--neutral-alpha-12);
76
+ }
77
+ }
78
+ }
79
+
80
+ .customDropdownButton> :first-child {
81
+ padding: 0px 4px !important;
82
+ box-shadow: inset 0 0 0 1px var(--neutral-alpha-3) !important;
83
+ border: 0 !important;
84
+ }
85
+
86
+ .flex1 {
87
+ flex: 1;
88
+ }
89
+
90
+ .flex2 {
91
+ flex: 2;
92
+ }
93
+
94
+ .controlsIconButton {
95
+ svg {
96
+ color: var(--neutral-12)
97
+ }
98
+
99
+
100
+ &:hover {
101
+ svg {
102
+ color: #fff !important;
103
+ }
104
+ }
105
+
106
+ &:active {
107
+ svg {
108
+ color: var(--neutral-10) !important;
109
+ }
110
+ }
111
+
112
+ }
113
+
114
+ .actionIconActive,
115
+ .actionIconActive:active {
116
+ color: var(--neutral-11) !important;
117
+ }
118
+
119
+ .actionIconActive:hover {
120
+ color: var(--neutral-12) !important;
121
+ }
122
+
123
+ .actionIconDefault,
124
+ .actionIconDefault:active {
125
+ color: #0AFFA7 !important;
126
+ }
127
+
128
+ .actionIconDefault:hover {
129
+ color: #07db8d !important;
130
+ }
131
+
132
+ .actionsContainer {
133
+ padding-top: 8px;
134
+ justify-content: flex-end;
135
+ }