chordia-ui 3.2.2 → 3.2.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/README.md +61 -0
- package/dist/index.cjs2.js +2 -2
- package/dist/index.cjs2.js.map +1 -1
- package/dist/index.es2.js +869 -811
- package/dist/index.es2.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/login/LoginPage.jsx +107 -5
- package/src/components/onboarding/ConnectData.jsx +89 -0
- package/src/components/onboarding/GettingStarted.jsx +520 -0
- package/src/components/onboarding/UploadEvaluate.jsx +255 -0
- package/src/components/onboarding/UploadInteraction.jsx +186 -0
- package/src/tokens/colors.css +13 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Upload, CircleUser, Compass, Link2 } from 'lucide-react';
|
|
3
|
+
|
|
4
|
+
const FF = 'var(--font-sans)';
|
|
5
|
+
|
|
6
|
+
// ─── Styles ───
|
|
7
|
+
|
|
8
|
+
const containerStyle = {
|
|
9
|
+
padding: '40px 48px',
|
|
10
|
+
fontFamily: FF,
|
|
11
|
+
minHeight: '100vh',
|
|
12
|
+
background: 'var(--grey-white)',
|
|
13
|
+
boxSizing: 'border-box',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const headingStyle = {
|
|
17
|
+
fontSize: 'var(--text-4xl)',
|
|
18
|
+
fontWeight: 'var(--font-bold)',
|
|
19
|
+
fontFamily: FF,
|
|
20
|
+
color: 'var(--text-ink)',
|
|
21
|
+
margin: 0,
|
|
22
|
+
letterSpacing: 'var(--tracking-tight)',
|
|
23
|
+
lineHeight: 'var(--leading-tight)',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const subtitleStyle = {
|
|
27
|
+
fontSize: 14,
|
|
28
|
+
fontStyle: 'normal',
|
|
29
|
+
fontWeight: 400,
|
|
30
|
+
lineHeight: '140%',
|
|
31
|
+
color: 'var(--color-text-secondary)',
|
|
32
|
+
margin: '8px 0 0',
|
|
33
|
+
fontFamily: FF,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const gridStyle = {
|
|
37
|
+
display: 'grid',
|
|
38
|
+
gridTemplateColumns: '1fr 1fr',
|
|
39
|
+
gap: 12,
|
|
40
|
+
marginTop: '36px',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const cardStyle = {
|
|
44
|
+
display: 'flex',
|
|
45
|
+
height: 160,
|
|
46
|
+
padding: 24,
|
|
47
|
+
flexDirection: 'column',
|
|
48
|
+
justifyContent: 'space-between',
|
|
49
|
+
alignItems: 'flex-start',
|
|
50
|
+
borderRadius: 12,
|
|
51
|
+
border: '1px solid var(--grey-absent)',
|
|
52
|
+
background: 'var(--grey-white)',
|
|
53
|
+
boxSizing: 'border-box',
|
|
54
|
+
transition: 'var(--transition)',
|
|
55
|
+
cursor: 'default',
|
|
56
|
+
gap: 8
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const cardHoverStyle = {
|
|
60
|
+
...cardStyle,
|
|
61
|
+
boxShadow: 'var(--shadow-sm)',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const iconWrapperStyle = {
|
|
65
|
+
width: 40,
|
|
66
|
+
height: 40,
|
|
67
|
+
borderRadius: 'var(--radius)',
|
|
68
|
+
background: 'var(--paper-secondary)',
|
|
69
|
+
display: 'flex',
|
|
70
|
+
alignItems: 'center',
|
|
71
|
+
justifyContent: 'center',
|
|
72
|
+
color: 'var(--text-base)',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const cardTitleStyle = {
|
|
76
|
+
color: 'var(--grey-strong)',
|
|
77
|
+
fontSize: 20,
|
|
78
|
+
fontStyle: 'normal',
|
|
79
|
+
fontWeight: 600,
|
|
80
|
+
lineHeight: 'normal',
|
|
81
|
+
fontFamily: FF,
|
|
82
|
+
margin: 0,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const cardDescStyle = {
|
|
86
|
+
fontSize: 13,
|
|
87
|
+
fontStyle: 'normal',
|
|
88
|
+
fontWeight: 400,
|
|
89
|
+
lineHeight: '140%',
|
|
90
|
+
color: 'var(--text-base)',
|
|
91
|
+
margin: 0,
|
|
92
|
+
fontFamily: FF,
|
|
93
|
+
flex: '1 0 0',
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const btnStyle = {
|
|
97
|
+
display: 'flex',
|
|
98
|
+
height: 28,
|
|
99
|
+
padding: 10,
|
|
100
|
+
justifyContent: 'center',
|
|
101
|
+
alignItems: 'center',
|
|
102
|
+
gap: 10,
|
|
103
|
+
borderRadius: 10,
|
|
104
|
+
background: 'var(--grey-strong)',
|
|
105
|
+
fontSize: 14,
|
|
106
|
+
fontStyle: 'normal',
|
|
107
|
+
fontWeight: 600,
|
|
108
|
+
lineHeight: 1,
|
|
109
|
+
fontFamily: FF,
|
|
110
|
+
color: 'var(--grey-white)',
|
|
111
|
+
border: 'none',
|
|
112
|
+
cursor: 'pointer',
|
|
113
|
+
transition: 'var(--transition-fast)',
|
|
114
|
+
outline: 'none',
|
|
115
|
+
boxSizing: 'border-box',
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const progressBarBg = {
|
|
119
|
+
flex: 1,
|
|
120
|
+
height: 8,
|
|
121
|
+
borderRadius: 4,
|
|
122
|
+
background: 'var(--border)',
|
|
123
|
+
overflow: 'hidden',
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const progressBarFill = (pct) => ({
|
|
127
|
+
width: `${pct}%`,
|
|
128
|
+
height: '100%',
|
|
129
|
+
borderRadius: 4,
|
|
130
|
+
background: 'var(--color-green)',
|
|
131
|
+
transition: 'width 0.4s ease-out',
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const recommendedBadge = {
|
|
135
|
+
display: 'inline-flex',
|
|
136
|
+
alignItems: 'center',
|
|
137
|
+
gap: 4,
|
|
138
|
+
fontSize: 'var(--text-xs)',
|
|
139
|
+
fontWeight: 'var(--font-semibold)',
|
|
140
|
+
color: 'var(--rail-compliance)',
|
|
141
|
+
fontFamily: FF,
|
|
142
|
+
marginLeft: 12,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// ─── Card Component ───
|
|
146
|
+
|
|
147
|
+
function OnboardingCard({ icon, title, description, buttonLabel, onAction, recommended, children }) {
|
|
148
|
+
const [hovered, setHovered] = useState(false);
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<div
|
|
152
|
+
style={hovered ? cardHoverStyle : cardStyle}
|
|
153
|
+
onMouseEnter={() => setHovered(true)}
|
|
154
|
+
onMouseLeave={() => setHovered(false)}
|
|
155
|
+
>
|
|
156
|
+
<div>
|
|
157
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
|
158
|
+
<div style={iconWrapperStyle}>{icon}</div>
|
|
159
|
+
<h3 style={cardTitleStyle}>{title}</h3>
|
|
160
|
+
</div>
|
|
161
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginLeft: 52, marginTop: 4 }}>
|
|
162
|
+
{description && <p style={cardDescStyle}>{description}</p>}
|
|
163
|
+
{children}
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
<div style={{ display: 'flex', alignItems: 'center', marginLeft: 52 }}>
|
|
167
|
+
<button
|
|
168
|
+
style={btnStyle}
|
|
169
|
+
onClick={onAction}
|
|
170
|
+
onMouseEnter={(e) => { e.currentTarget.style.opacity = '0.85'; }}
|
|
171
|
+
onMouseLeave={(e) => { e.currentTarget.style.opacity = '1'; }}
|
|
172
|
+
>
|
|
173
|
+
{buttonLabel}
|
|
174
|
+
</button>
|
|
175
|
+
{recommended && (
|
|
176
|
+
<span style={recommendedBadge}>
|
|
177
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" /></svg>
|
|
178
|
+
Recommended
|
|
179
|
+
</span>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ─── Main Component ───
|
|
187
|
+
|
|
188
|
+
const UploadEvaluate = ({
|
|
189
|
+
userName = 'Will',
|
|
190
|
+
stepsCompleted = 4,
|
|
191
|
+
totalSteps = 6,
|
|
192
|
+
onUpload,
|
|
193
|
+
onContinue,
|
|
194
|
+
onExplore,
|
|
195
|
+
onConnect,
|
|
196
|
+
}) => {
|
|
197
|
+
const progressPct = (stepsCompleted / totalSteps) * 100;
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div style={containerStyle}>
|
|
201
|
+
<h1 style={headingStyle}>Welcome {userName}</h1>
|
|
202
|
+
<p style={subtitleStyle}>Get started with your project or explore new features</p>
|
|
203
|
+
|
|
204
|
+
<div style={gridStyle}>
|
|
205
|
+
{/* Upload and Evaluate Audio */}
|
|
206
|
+
<OnboardingCard
|
|
207
|
+
icon={<Upload size={24} />}
|
|
208
|
+
title="Upload and Evaluate Audio"
|
|
209
|
+
description="Upload Audio Files to Run Evaluations: MP3, WMA or WAV (up to 50 files, max 325MB total)"
|
|
210
|
+
buttonLabel="Upload"
|
|
211
|
+
onAction={onUpload}
|
|
212
|
+
/>
|
|
213
|
+
|
|
214
|
+
{/* Getting started with Chordia */}
|
|
215
|
+
<OnboardingCard
|
|
216
|
+
icon={<CircleUser size={24} />}
|
|
217
|
+
title="Getting started with Chordia"
|
|
218
|
+
description="Complete these steps to get the most out of Chordia."
|
|
219
|
+
buttonLabel="Continue"
|
|
220
|
+
onAction={onContinue}
|
|
221
|
+
>
|
|
222
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%' }}>
|
|
223
|
+
<div style={progressBarBg}>
|
|
224
|
+
<div style={progressBarFill(progressPct)} />
|
|
225
|
+
</div>
|
|
226
|
+
<span style={{ fontSize: 12, color: 'var(--text-muted)', fontFamily: FF, whiteSpace: 'nowrap' }}>
|
|
227
|
+
<strong style={{ color: 'var(--text-base)', fontWeight: 600 }}>{stepsCompleted}</strong> of {totalSteps} steps completed
|
|
228
|
+
</span>
|
|
229
|
+
</div>
|
|
230
|
+
</OnboardingCard>
|
|
231
|
+
|
|
232
|
+
{/* Explore Demo Projects */}
|
|
233
|
+
<OnboardingCard
|
|
234
|
+
icon={<Compass size={24} />}
|
|
235
|
+
title="Explore Demo Projects"
|
|
236
|
+
description="Explore how Chordia Compass transforms real data into insights with plans, dashboards, and evaluations."
|
|
237
|
+
buttonLabel="Explore"
|
|
238
|
+
onAction={onExplore}
|
|
239
|
+
recommended
|
|
240
|
+
/>
|
|
241
|
+
|
|
242
|
+
{/* Connect Data Source */}
|
|
243
|
+
<OnboardingCard
|
|
244
|
+
icon={<Link2 size={24} />}
|
|
245
|
+
title="Connect Data Source"
|
|
246
|
+
description="Connect and integrate third-party tools with your external data sources."
|
|
247
|
+
buttonLabel="Connect"
|
|
248
|
+
onAction={onConnect}
|
|
249
|
+
/>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export default UploadEvaluate;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { useState, useRef } from 'react';
|
|
2
|
+
import { CloudUpload } from 'lucide-react';
|
|
3
|
+
|
|
4
|
+
const FF = 'var(--font-sans)';
|
|
5
|
+
|
|
6
|
+
// ─── Styles ───
|
|
7
|
+
|
|
8
|
+
const containerStyle = {
|
|
9
|
+
fontFamily: FF,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const sectionTitleStyle = {
|
|
13
|
+
fontSize: 20,
|
|
14
|
+
fontWeight: 600,
|
|
15
|
+
fontStyle: 'normal',
|
|
16
|
+
fontFamily: FF,
|
|
17
|
+
color: 'var(--grey-strong)',
|
|
18
|
+
margin: 0,
|
|
19
|
+
lineHeight: 'normal',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const sectionSubtitleStyle = {
|
|
23
|
+
fontSize: 13,
|
|
24
|
+
fontWeight: 400,
|
|
25
|
+
fontStyle: 'normal',
|
|
26
|
+
color: 'var(--color-text-secondary)',
|
|
27
|
+
fontFamily: FF,
|
|
28
|
+
margin: '4px 0 0',
|
|
29
|
+
lineHeight: '140%',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const dropzoneStyle = {
|
|
33
|
+
display: 'flex',
|
|
34
|
+
flexDirection: 'column',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
width: '100%',
|
|
38
|
+
minHeight: 320,
|
|
39
|
+
borderRadius: 16,
|
|
40
|
+
border: '2px dashed var(--color-input-border)',
|
|
41
|
+
background: 'var(--grey-white)',
|
|
42
|
+
boxSizing: 'border-box',
|
|
43
|
+
cursor: 'pointer',
|
|
44
|
+
transition: 'var(--transition-fast)',
|
|
45
|
+
marginTop: 24,
|
|
46
|
+
padding: '48px 24px',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const dropzoneHoverStyle = {
|
|
50
|
+
...dropzoneStyle,
|
|
51
|
+
borderColor: 'var(--color-green)',
|
|
52
|
+
background: 'var(--color-green-ring)',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const dropzoneIconWrap = {
|
|
56
|
+
width: 80,
|
|
57
|
+
height: 80,
|
|
58
|
+
borderRadius: 9999,
|
|
59
|
+
background: 'var(--focus-2)',
|
|
60
|
+
display: 'flex',
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
justifyContent: 'center',
|
|
63
|
+
flexShrink: 0,
|
|
64
|
+
marginBottom: 20,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const dropzoneTextStyle = {
|
|
68
|
+
fontSize: 18,
|
|
69
|
+
fontWeight: 600,
|
|
70
|
+
fontFamily: FF,
|
|
71
|
+
color: 'var(--grey-strong)',
|
|
72
|
+
textAlign: 'center',
|
|
73
|
+
lineHeight: '28px',
|
|
74
|
+
margin: 0,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const browseButtonStyle = {
|
|
78
|
+
display: 'flex',
|
|
79
|
+
height: 32,
|
|
80
|
+
padding: 16,
|
|
81
|
+
justifyContent: 'center',
|
|
82
|
+
alignItems: 'center',
|
|
83
|
+
gap: 10,
|
|
84
|
+
borderRadius: 10,
|
|
85
|
+
border: '1px solid var(--grey-absent)',
|
|
86
|
+
background: 'var(--grey-white)',
|
|
87
|
+
fontSize: 15,
|
|
88
|
+
fontWeight: 400,
|
|
89
|
+
fontFamily: FF,
|
|
90
|
+
color: 'var(--grey-strong)',
|
|
91
|
+
cursor: 'pointer',
|
|
92
|
+
transition: 'var(--transition-fast)',
|
|
93
|
+
outline: 'none',
|
|
94
|
+
marginTop: 16,
|
|
95
|
+
boxSizing: 'border-box',
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const dropzoneHintStyle = {
|
|
99
|
+
fontSize: 14,
|
|
100
|
+
fontWeight: 400,
|
|
101
|
+
fontFamily: FF,
|
|
102
|
+
color: 'var(--grey-muted)',
|
|
103
|
+
textAlign: 'center',
|
|
104
|
+
marginTop: 16,
|
|
105
|
+
lineHeight: '140%',
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// ─── Component ───
|
|
109
|
+
|
|
110
|
+
const UploadInteraction = ({ onFileSelect }) => {
|
|
111
|
+
const [dragOver, setDragOver] = useState(false);
|
|
112
|
+
const fileInputRef = useRef(null);
|
|
113
|
+
|
|
114
|
+
const handleDragOver = (e) => {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
setDragOver(true);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const handleDragLeave = () => {
|
|
120
|
+
setDragOver(false);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const handleDrop = (e) => {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
setDragOver(false);
|
|
126
|
+
const files = e.dataTransfer?.files;
|
|
127
|
+
if (files?.length) {
|
|
128
|
+
onFileSelect?.(files);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleBrowseClick = () => {
|
|
133
|
+
fileInputRef.current?.click();
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const handleFileChange = (e) => {
|
|
137
|
+
const files = e.target.files;
|
|
138
|
+
if (files?.length) {
|
|
139
|
+
onFileSelect?.(files);
|
|
140
|
+
}
|
|
141
|
+
e.target.value = '';
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<div style={containerStyle}>
|
|
146
|
+
<h2 style={sectionTitleStyle}>Evaluate Interaction</h2>
|
|
147
|
+
<p style={sectionSubtitleStyle}>
|
|
148
|
+
Upload another interaction to compare results and identify patterns across multiple evaluations.
|
|
149
|
+
</p>
|
|
150
|
+
|
|
151
|
+
<input
|
|
152
|
+
ref={fileInputRef}
|
|
153
|
+
type="file"
|
|
154
|
+
accept=".mp3,.wma,.wav"
|
|
155
|
+
multiple
|
|
156
|
+
style={{ display: 'none' }}
|
|
157
|
+
onChange={handleFileChange}
|
|
158
|
+
/>
|
|
159
|
+
|
|
160
|
+
<div
|
|
161
|
+
style={dragOver ? dropzoneHoverStyle : dropzoneStyle}
|
|
162
|
+
onDragOver={handleDragOver}
|
|
163
|
+
onDragLeave={handleDragLeave}
|
|
164
|
+
onDrop={handleDrop}
|
|
165
|
+
onClick={handleBrowseClick}
|
|
166
|
+
>
|
|
167
|
+
<div style={dropzoneIconWrap}>
|
|
168
|
+
<CloudUpload size={32} color="var(--grey-strong)" />
|
|
169
|
+
</div>
|
|
170
|
+
<p style={dropzoneTextStyle}>Drop your file here, or</p>
|
|
171
|
+
<button
|
|
172
|
+
type="button"
|
|
173
|
+
style={browseButtonStyle}
|
|
174
|
+
onClick={(e) => { e.stopPropagation(); handleBrowseClick(); }}
|
|
175
|
+
onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--hover-warm-subtle)'; }}
|
|
176
|
+
onMouseLeave={(e) => { e.currentTarget.style.background = 'var(--grey-white)'; }}
|
|
177
|
+
>
|
|
178
|
+
Browse files
|
|
179
|
+
</button>
|
|
180
|
+
<p style={dropzoneHintStyle}>Supports: MP3, WMA or WAV</p>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export default UploadInteraction;
|
package/src/tokens/colors.css
CHANGED
|
@@ -187,6 +187,19 @@
|
|
|
187
187
|
--color-error-ring: rgba(237, 128, 119, 0.12);
|
|
188
188
|
--color-error-bg: #F3F7F7;
|
|
189
189
|
|
|
190
|
+
/* ============================================
|
|
191
|
+
GREY SCALE (Figma Chordia Colors)
|
|
192
|
+
============================================ */
|
|
193
|
+
--grey-white: #FFFFFF;
|
|
194
|
+
--grey-absent: #D9D9D9;
|
|
195
|
+
--grey-muted: #BDBDBD;
|
|
196
|
+
--grey-strong: var(--color-text);
|
|
197
|
+
|
|
198
|
+
/* ============================================
|
|
199
|
+
FOCUS / WARM SURFACES
|
|
200
|
+
============================================ */
|
|
201
|
+
--focus-2: #FAF5E9;
|
|
202
|
+
|
|
190
203
|
/* ============================================
|
|
191
204
|
GRADIENTS
|
|
192
205
|
============================================ */
|