@moises.ai/design-system 3.10.17 → 3.11.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.
@@ -1,27 +1,43 @@
1
- import { DotsVerticalIcon } from '@radix-ui/react-icons'
2
- import { IconButton } from '@radix-ui/themes'
3
1
  import classNames from 'classnames'
4
2
  import { memo, useCallback } from 'react'
5
- import { DropdownMenu, HorizontalVolume, PanControl, Text, Tooltip } from '../../index'
6
- import { TrackControlButton } from '../TrackControlButton'
3
+ import {
4
+ ChevronDownFilledIcon,
5
+ ChevronRightFilledIcon,
6
+ More2Icon,
7
+ } from '../../icons'
8
+ import {
9
+ DropdownMenu,
10
+ Flex,
11
+ HorizontalVolume,
12
+ IconButton,
13
+ PanControl,
14
+ Text,
15
+ Tooltip,
16
+ TrackControlsToggle,
17
+ } from '../../index'
7
18
  import styles from './TrackHeader.module.css'
8
- import { TrackHeaderOptions } from './TrackHeaderOptions'
9
19
 
10
20
  export const TrackHeader = memo(
11
21
  ({
12
22
  // Config
13
23
  title,
14
24
  menuOptions,
25
+ instrumentOptions,
26
+ onInstrumentChange,
27
+ instrumentSelected,
15
28
  showPan = true,
16
29
  showVolumeControls = true,
17
30
  isGrouped = false,
18
31
  height = 81,
19
32
  compact = false,
33
+ isActive = false,
20
34
 
21
35
  // State
22
36
  volume,
23
37
  pan,
24
38
  isMuted,
39
+ isRecord,
40
+ isAutoMuted,
25
41
  isSolo,
26
42
  isOpen,
27
43
 
@@ -29,6 +45,7 @@ export const TrackHeader = memo(
29
45
  onVolumeChange,
30
46
  onPanChange,
31
47
  onMutedChange,
48
+ onRecordChange,
32
49
  onSoloChange,
33
50
  onOpenChange,
34
51
 
@@ -36,10 +53,15 @@ export const TrackHeader = memo(
36
53
  children,
37
54
  }) => {
38
55
  const hasChildren = Boolean(children)
39
- const handleToggleOpen = useCallback(() => onOpenChange?.(!isOpen), [isOpen, onOpenChange])
56
+ const handleToggleOpen = useCallback(
57
+ () => onOpenChange?.(!isOpen),
58
+ [isOpen, onOpenChange],
59
+ )
40
60
 
41
61
  return (
42
- <div className={classNames(styles.container, { [styles.isOpen]: isOpen })}>
62
+ <div
63
+ className={classNames(styles.container, { [styles.isOpen]: isOpen })}
64
+ >
43
65
  <div
44
66
  className={classNames(styles.track, {
45
67
  [styles.isParentTrack]: hasChildren,
@@ -47,46 +69,125 @@ export const TrackHeader = memo(
47
69
  })}
48
70
  style={{ height: `${height}px` }}
49
71
  >
50
- <div className={styles.trackContent}>
72
+ <Flex
73
+ className={classNames(styles.trackContent, {
74
+ [styles.isActive]: isActive,
75
+ })}
76
+ direction="column"
77
+ gap="2"
78
+ p="12px 12px 12px 4px"
79
+ >
51
80
  <div className={styles.line}>
52
- <div className={styles.left}>
53
- <div
54
- className={styles.leftIcon}
81
+ <Flex
82
+ align="center"
83
+ justify="between"
84
+ direction="row"
85
+ gap="3"
86
+ className={styles.headerActions}
87
+ >
88
+ <Flex
89
+ align="center"
90
+ direction="row"
91
+ gap="1"
92
+ flexGrow="1"
93
+ style={{ minWidth: 0, overflow: 'hidden' }}
94
+ >
95
+ <IconButton
96
+ onPointerDown={(e) => e.stopPropagation()}
97
+ onMouseDown={(e) => e.stopPropagation()}
98
+ onTouchStart={(e) => e.stopPropagation()}
99
+ variant="ghost"
100
+ size="1"
101
+ onClick={handleToggleOpen}
102
+ className={styles.toggleOpenButton}
103
+ >
104
+ {isOpen ? (
105
+ <ChevronDownFilledIcon />
106
+ ) : (
107
+ <ChevronRightFilledIcon />
108
+ )}
109
+ </IconButton>
110
+ {instrumentOptions && (
111
+ <DropdownMenu
112
+ showActiveTrigger={true}
113
+ trigger={
114
+ <IconButton
115
+ variant="ghost"
116
+ size="1"
117
+ className={classNames(
118
+ styles.instrumentIconButton,
119
+ styles.menuOptionsTrigger,
120
+ )}
121
+ >
122
+ {instrumentSelected.icon}
123
+ </IconButton>
124
+ }
125
+ options={instrumentOptions}
126
+ onValueChange={onInstrumentChange}
127
+ side="bottom"
128
+ align="start"
129
+ />
130
+ )}
131
+
132
+ <Tooltip content={title}>
133
+ <Text
134
+ size="2"
135
+ className={styles.name}
136
+ onClick={hasChildren ? handleToggleOpen : undefined}
137
+ >
138
+ {title}
139
+ </Text>
140
+ </Tooltip>
141
+ </Flex>
142
+
143
+ <Flex
144
+ direction="row"
145
+ gap="3"
146
+ align="center"
55
147
  onPointerDown={(e) => e.stopPropagation()}
56
148
  onMouseDown={(e) => e.stopPropagation()}
57
149
  onTouchStart={(e) => e.stopPropagation()}
58
150
  >
59
- <TrackHeaderOptions isOpen={isOpen} onToggleOpen={handleToggleOpen} />
60
- </div>
61
-
62
- <Tooltip content={title}>
63
- <Text
64
- size="2"
65
- className={styles.name}
66
- onClick={hasChildren ? handleToggleOpen : undefined}
67
- >
68
- {title}
69
- </Text>
70
- </Tooltip>
71
- </div>
151
+ <Flex gap="2px">
152
+ <TrackControlsToggle
153
+ type="record"
154
+ selected={isRecord}
155
+ onClick={onRecordChange}
156
+ />
157
+ <TrackControlsToggle
158
+ type={
159
+ isMuted ? 'mute' : isAutoMuted ? 'autoMute' : 'mute'
160
+ }
161
+ selected={isMuted}
162
+ onClick={onMutedChange}
163
+ />
164
+ <TrackControlsToggle
165
+ type="solo"
166
+ selected={isSolo}
167
+ onClick={onSoloChange}
168
+ />
169
+ </Flex>
170
+ </Flex>
72
171
 
73
- <div
74
- className={styles.menuOptions}
75
- onPointerDown={(e) => e.stopPropagation()}
76
- onMouseDown={(e) => e.stopPropagation()}
77
- onTouchStart={(e) => e.stopPropagation()}
78
- >
79
172
  {menuOptions && (
80
173
  <DropdownMenu
81
174
  trigger={
82
- <IconButton className={styles.menuOptionsTrigger} variant="ghost" color="gray" size="1">
83
- <DotsVerticalIcon width={16} height={16} />
175
+ <IconButton
176
+ variant="ghost"
177
+ size="1"
178
+ className={styles.menuOptionsTrigger}
179
+ >
180
+ <More2Icon
181
+ width={16}
182
+ height={16}
183
+ className={styles.menuOptionsIcon}
184
+ />
84
185
  </IconButton>
85
186
  }
86
187
  options={menuOptions}
87
188
  />
88
189
  )}
89
- </div>
190
+ </Flex>
90
191
  </div>
91
192
 
92
193
  <div
@@ -101,39 +202,23 @@ export const TrackHeader = memo(
101
202
  volume={volume}
102
203
  onChangeValue={onVolumeChange}
103
204
  />
104
- {showPan && <PanControl className={styles.pan} value={pan} onChange={onPanChange} minValue={-1} maxValue={1}/>}
205
+ {showPan && (
206
+ <PanControl
207
+ className={styles.pan}
208
+ value={pan}
209
+ onChange={onPanChange}
210
+ minValue={-1}
211
+ maxValue={1}
212
+ />
213
+ )}
105
214
  </>
106
215
  )}
107
216
  </div>
108
- </div>
109
-
110
- {showVolumeControls && (
111
- <div
112
- className={styles.right}
113
- onPointerDown={(e) => e.stopPropagation()}
114
- onMouseDown={(e) => e.stopPropagation()}
115
- onTouchStart={(e) => e.stopPropagation()}
116
- >
117
- <TrackControlButton
118
- className={styles.rightButton}
119
- variant="mute"
120
- isActive={isMuted}
121
- onChange={onMutedChange}
122
- />
123
- <TrackControlButton
124
- className={styles.rightButton}
125
- variant="solo"
126
- isActive={isSolo}
127
- onChange={onSoloChange}
128
- />
129
- </div>
130
- )}
217
+ </Flex>
131
218
  </div>
132
219
 
133
220
  {hasChildren && isOpen && (
134
- <div className={styles.group}>
135
- {children}
136
- </div>
221
+ <div className={styles.group}>{children}</div>
137
222
  )}
138
223
  </div>
139
224
  )
@@ -3,13 +3,9 @@
3
3
  display: flex;
4
4
  justify-content: space-between;
5
5
  box-sizing: border-box;
6
- box-shadow: 0 1px 0 0 var(--neutral-alpha-3);
6
+ box-shadow: 0 1px 0 0 var(--neutral-3);
7
+
7
8
 
8
- &:hover {
9
- .leftIcon {
10
- color: var(--neutral-12);
11
- }
12
- }
13
9
  }
14
10
 
15
11
  .name {
@@ -17,7 +13,7 @@
17
13
  min-width: 0;
18
14
  white-space: nowrap;
19
15
  overflow: hidden;
20
- background: linear-gradient(90deg, #fff 81%, #1d1d1d 100%);
16
+ background: linear-gradient(90deg, #fff 95%, #1d1d1d 100%);
21
17
  background-clip: text;
22
18
  -webkit-background-clip: text;
23
19
  -webkit-text-fill-color: transparent;
@@ -31,16 +27,49 @@
31
27
  min-width: 0;
32
28
  }
33
29
 
34
- .left {
30
+ /* .left {
35
31
  flex: 1;
36
32
  display: flex;
37
33
  align-items: center;
38
34
  min-width: 0;
35
+ } */
36
+
37
+ .instrumentIconButton {
38
+ margin-right: 4px !important;
39
+ border-radius: 4px;
39
40
  }
40
41
 
41
- .leftIcon {
42
- width: 24px;
43
- color: var(--neutral-8);
42
+ .headerActions {
43
+ min-width: 0;
44
+ width: 100%;
45
+ }
46
+
47
+ .trackContent{
48
+ /* background-color: ; */
49
+ flex: 1;
50
+ min-width: 0;
51
+ /* border: 1px solid var(--neutral-3); */
52
+ background-color: rgba(17, 17, 19);
53
+
54
+ &:hover {
55
+ .menuOptionsTrigger svg {
56
+ opacity: 1;
57
+ color: var(--neutral-11);
58
+ }
59
+
60
+ .instrumentIcon {
61
+ opacity: 1;
62
+ color: var(--neutral-alpha-11);
63
+ }
64
+ }
65
+ }
66
+
67
+ .trackContent.isActive {
68
+ background-color: var(--neutral-2);
69
+ }
70
+
71
+ .instrumentIcon {
72
+ color: var(--neutral-alpha-8);
44
73
  }
45
74
 
46
75
  .right {
@@ -82,26 +111,33 @@
82
111
  justify-content: center;
83
112
  }
84
113
 
85
- .menuOptionsTrigger:hover {
86
- color: var(--accent-a12) !important;
87
- background-color: transparent !important;
114
+
115
+
116
+ .menuOptionsTrigger {
117
+
118
+ svg {
119
+ opacity: 0.5;
120
+ }
121
+
122
+ &:hover {
123
+ svg {
124
+ opacity: 1;
125
+ }
126
+ }
127
+
128
+ &[data-state='open'],
129
+ &[data-highlighted] {
130
+ svg {
131
+ opacity: 1;
132
+ color: var(--neutral-11);
133
+ }
134
+ }
88
135
  }
89
136
 
90
- .menuOptionsTrigger[data-state=open] {
137
+ /* .menuOptionsTrigger[data-state=open] {
91
138
  color: var(--accent-a10) !important;
92
- }
139
+ } */
93
140
 
94
- .trackContent {
95
- flex: 1;
96
- min-width: 0;
97
- display: flex;
98
- padding-left: var(--space-1);
99
- padding-right: var(--space-3);
100
- padding-top: var(--space-3);
101
- padding-bottom: var(--space-3);
102
- flex-direction: column;
103
- justify-content: space-between;
104
- }
105
141
 
106
142
  /* Open */
107
143
 
@@ -118,26 +154,27 @@
118
154
  /* Not parent track (either grouped or not) */
119
155
 
120
156
  .track:not(.isParentTrack) {
121
- .leftIcon {
157
+ .toggleOpenButton {
122
158
  visibility: hidden;
123
159
  pointer-events: none;
124
160
  }
125
161
  }
126
162
 
127
163
  /* Child track */
128
-
164
+ .group {
165
+ background-color: rgba(17, 17, 19);
166
+ }
129
167
  .group > * {
130
168
  .track {
131
169
  margin-left: 28px;
132
170
  background-color: var(--neutral-alpha-2);
133
- border-left-style: solid;
134
- border-left-color: var(--neutral-alpha-3);
135
- border-left-width: 1px;
171
+ border-radius: none;
172
+ box-shadow: 0 1px 0 0 var(--neutral-alpha-4);
136
173
 
137
174
  .trackContent {
138
175
  padding-left: 0;
139
-
140
- .leftIcon {
176
+ background-color: var(--neutral-alpha-2);
177
+ .toggleOpenButton {
141
178
  display: none;
142
179
  }
143
180
 
@@ -145,7 +182,7 @@
145
182
  padding-left: var(--space-4);
146
183
  background: linear-gradient(
147
184
  90deg,
148
- var(--neutral-alpha-11) 81%,
185
+ var(--neutral-alpha-11) 95%,
149
186
  #1d1d1d 100%
150
187
  );
151
188
  background-clip: text;
@@ -161,7 +198,6 @@
161
198
  &:first-child .track {
162
199
  border-top-style: solid;
163
200
  border-top-color: var(--neutral-alpha-3);
164
- border-top-left-radius: 4px;
165
201
  border-top-width: 1px;
166
202
  }
167
203
 
@@ -192,3 +228,14 @@
192
228
  }
193
229
  }
194
230
  }
231
+
232
+
233
+ .toggleOpenButton {
234
+ background: transparent;
235
+ width: 20px;
236
+ height: 20px;
237
+ opacity: 0.5;
238
+ &:hover {
239
+ opacity: 1;
240
+ }
241
+ }
@@ -1,6 +1,6 @@
1
1
  import { TrackHeader } from './TrackHeader'
2
2
  import { useState } from 'react'
3
-
3
+ import { BassIcon, ElectricGuitarIcon, KeysIcon, DrumsIcon } from '../../icons'
4
4
  export default {
5
5
  title: 'Components/TrackHeader',
6
6
  component: TrackHeader,
@@ -92,6 +92,13 @@ const menuOptions = [
92
92
  { type: 'item', key: 'delete', label: 'Delete', onClick: () => console.log('Delete clicked') },
93
93
  ]
94
94
 
95
+ const instrumentOptions = [
96
+ { type: 'item', key: 'bass', label: 'Bass', icon: <BassIcon /> },
97
+ { type: 'item', key: 'guitar', label: 'Guitar', icon: <ElectricGuitarIcon /> },
98
+ { type: 'item', key: 'piano', label: 'Piano', icon: <KeysIcon /> },
99
+ { type: 'item', key: 'drums', label: 'Drums', icon: <DrumsIcon /> },
100
+
101
+ ]
95
102
  export const Default = {
96
103
  args: {
97
104
  title: 'Common Track',
@@ -109,13 +116,15 @@ export const Default = {
109
116
  onPanChange: () => { },
110
117
  onMutedChange: () => { },
111
118
  onSoloChange: () => { },
119
+ onInstrumentChange: () => { },
120
+ instrumentOptions,
121
+ instrumentSelected: instrumentOptions[0],
112
122
  },
113
123
  render: (args) => <TrackHeader {...args} />,
114
124
  }
115
125
 
116
126
  export const Group = {
117
127
  args: {
118
- isOpen: true,
119
128
  title: 'Group Track',
120
129
  showPan: false,
121
130
  showVolumeControls: true,
@@ -130,13 +139,13 @@ export const Group = {
130
139
  onPanChange: () => { },
131
140
  onMutedChange: () => { },
132
141
  onSoloChange: () => { },
133
- onOpenChange: () => { },
134
142
  },
135
143
  render: (args) => {
144
+ const [isOpen, setIsOpen] = useState(true)
136
145
  const [pan, setPan] = useState(-0.3)
137
146
  const [pan2, setPan2] = useState(-0.3)
138
147
  return (
139
- <TrackHeader {...args}>
148
+ <TrackHeader {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
140
149
  <TrackHeader
141
150
  title="Grouped Track"
142
151
  isGrouped
@@ -0,0 +1,17 @@
1
+ export const ChevronDownFilledIcon = ({ width = 9, height = 5, className, ...props }) => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width={width}
5
+ height={height}
6
+ viewBox="0 0 9 5"
7
+ fill="none"
8
+ className={className}
9
+ {...props}
10
+ >
11
+ <path
12
+ d="M3.58684 4.29289L0.147499 0.853553C-0.167484 0.538571 0.0555997 0 0.501052 0L8.08684 0C8.53229 0 8.75537 0.53857 8.44039 0.853553L5.00105 4.29289C4.61053 4.68342 3.97736 4.68342 3.58684 4.29289Z"
13
+ fill="currentColor" />
14
+ </svg>
15
+ )
16
+
17
+ ChevronDownFilledIcon.displayName = 'ChevronDownFilledIcon'
@@ -0,0 +1,17 @@
1
+ export const ChevronRightFilledIcon = ({ width = 5, height = 9, className, ...props }) => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width={width}
5
+ height={height}
6
+ viewBox="0 0 5 9"
7
+ fill="none"
8
+ className={className}
9
+ {...props}
10
+ >
11
+ <path
12
+ d="M4.29289 5.001L0.853553 8.44034C0.538571 8.75532 -3.3293e-08 8.53224 -5.27643e-08 8.08679L-3.8435e-07 0.501002C-4.03821e-07 0.0555496 0.53857 -0.167534 0.853552 0.147449L4.29289 3.58679C4.68342 3.97731 4.68342 4.61048 4.29289 5.001Z"
13
+ fill="currentColor" />
14
+ </svg>
15
+ )
16
+
17
+ ChevronRightFilledIcon.displayName = 'ChevronRightFilledIcon'
package/src/icons.jsx CHANGED
@@ -347,3 +347,5 @@ export { EmailIcon } from './icons/EmailIcon'
347
347
  export { EyeIcon } from './icons/EyeIcon'
348
348
  export { EyeOffIcon } from './icons/EyeOffIcon'
349
349
  export { Play1Icon } from './icons/Play1Icon'
350
+ export { ChevronRightFilledIcon } from './icons/ChevronRightFilledIcon'
351
+ export { ChevronDownFilledIcon } from './icons/ChevronDownFilledIcon'
package/src/index.jsx CHANGED
@@ -142,4 +142,5 @@ export { useForm } from './components/useForm/useForm'
142
142
  export { VoiceConversionForm } from './components/VoiceConversionForm/VoiceConversionForm'
143
143
  export { Waveform } from './components/VoiceConversionForm/Waveform/Waveform'
144
144
 
145
- export { EmptyState } from './components/EmptyState/EmptyState'
145
+ export { EmptyState } from './components/EmptyState/EmptyState'
146
+ export { TrackControlsToggle } from './components/TrackControlsToggle/TrackControlsToggle'
@@ -286,6 +286,11 @@
286
286
  background-color: transparent;
287
287
  }
288
288
 
289
+ .menuTrigger[data-state='open'].showActiveTrigger,
290
+ .menuTrigger[data-highlighted].showActiveTrigger {
291
+ background-color: var(--neutral-alpha-3);
292
+ }
293
+
289
294
  .menuSubTrigger[data-highlighted],
290
295
  .menuItem[data-highlighted],
291
296
  .menuSubTrigger[data-state='open'] {