Skip to content

Commit 01d2b5b

Browse files
Herzog design feedback (#21)
1 parent 974e786 commit 01d2b5b

File tree

13 files changed

+190
-117
lines changed

13 files changed

+190
-117
lines changed

app-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export const APP_CONFIG_DEFAULTS: AppConfig = {
55
pageTitle: 'Voice Assistant',
66
pageDescription: 'A voice assistant built with LiveKit',
77

8-
suportsChatInput: false,
9-
suportsVideoInput: false,
10-
suportsScreenShare: false,
8+
suportsChatInput: true,
9+
suportsVideoInput: true,
10+
suportsScreenShare: true,
1111

1212
logo: '/lk-logo.svg',
1313
accent: '#002cf2',

app/globals.css

Lines changed: 99 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,33 @@
44
@custom-variant dark (&:is(.dark *));
55

66
:root {
7+
--fg0: #000000;
8+
--fg1: #3b3b3b;
9+
--fg2: #4d4d4d;
10+
--fg3: #636363;
11+
--fg4: #707070;
12+
--fgSerious: #db1b06;
13+
--fgSuccess: #006430;
14+
--fgModerate: #a65006;
15+
--fgAccent: #002cf2;
16+
17+
--bg1: #f9f9f6;
18+
--bg2: #f3f3f1;
19+
--bg3: #e2e2df;
20+
--bgSerious: #fae6e6;
21+
--bgSerious2: #ffcdc7;
22+
--bgSuccess: #d1fadf;
23+
--bgModerate: #faedd1;
24+
--bgAccent: #b3ccff;
25+
--bgAccentPrimary: #e2ebfd;
26+
27+
--separator1: #ffcdc7;
28+
--separator2: #bdbdbb;
29+
--separatorSerious: #ffcdc7;
30+
--separatorSuccess: #94dcb5;
31+
--separatorModerate: #fbd7a0;
32+
--separatorAccent: #b3ccff;
33+
734
--radius: 0.625rem;
835
--background: oklch(1 0 0);
936
--foreground: oklch(0.145 0 0);
@@ -15,7 +42,7 @@
1542
--primary-foreground: oklch(0.985 0 0);
1643
--secondary: oklch(0.97 0 0);
1744
--secondary-foreground: oklch(0.205 0 0);
18-
--muted: oklch(0.97 0 0);
45+
--muted: #f3f3f1;
1946
--muted-foreground: oklch(0.556 0 0);
2047
--accent: oklch(0.97 0 0);
2148
--accent-foreground: oklch(0.205 0 0);
@@ -35,17 +62,36 @@
3562
--sidebar-accent-foreground: oklch(0.205 0 0);
3663
--sidebar-border: oklch(0.922 0 0);
3764
--sidebar-ring: oklch(0.708 0 0);
38-
39-
--button: #f1f1ef;
40-
--button-border: #dbdbd8;
41-
--button-foreground: #3b3b3b;
42-
43-
--destructive: #fcf1f1;
44-
--destructive-border: #fdc2bc;
45-
--destructive-foreground: #a54135;
4665
}
4766

4867
.dark {
68+
--fg0: #ffffff;
69+
--fg1: #cccccc;
70+
--fg2: #b2b2b2;
71+
--fg3: #999999;
72+
--fg4: #666666;
73+
--fgSerious: #ff7566;
74+
--fgSuccess: #3bc981;
75+
--fgModerate: #ffb752;
76+
--fgAccent: #6e9dfe;
77+
78+
--bg1: #070707;
79+
--bg2: #131313;
80+
--bg3: #202020;
81+
--bgSerious: #1f0e0b;
82+
--bgSerious2: #5a1c16;
83+
--bgSuccess: #001905;
84+
--bgModerate: #1a0e04;
85+
--bgAccent: #090c17;
86+
--bgAccentPrimary: #0c1640;
87+
88+
--separator1: #202020;
89+
--separator2: #30302f;
90+
--separatorSerious: #5a1c16;
91+
--separatorSuccess: #003213;
92+
--separatorModerate: #3f2208;
93+
--separatorAccent: #0c1640;
94+
4995
--background: oklch(0.145 0 0);
5096
--foreground: oklch(0.985 0 0);
5197
--card: oklch(0.205 0 0);
@@ -56,7 +102,7 @@
56102
--primary-foreground: oklch(0.205 0 0);
57103
--secondary: oklch(0.269 0 0);
58104
--secondary-foreground: oklch(0.985 0 0);
59-
--muted: oklch(0.269 0 0);
105+
--muted: #131313;
60106
--muted-foreground: oklch(0.708 0 0);
61107
--accent: oklch(0.371 0 0);
62108
--accent-foreground: oklch(0.985 0 0);
@@ -76,25 +122,20 @@
76122
--sidebar-accent-foreground: oklch(0.985 0 0);
77123
--sidebar-border: oklch(1 0 0 / 10%);
78124
--sidebar-ring: oklch(0.439 0 0);
79-
80-
--button: #131313;
81-
--button-border: #202020;
82-
--button-foreground: #cccccc;
83-
84-
--destructive: #1f0e0b;
85-
--destructive-border: #4c1f19;
86-
--destructive-foreground: #ff6352;
87125
}
88126

89127
@theme inline {
128+
--color-fg1: var(--fg1);
129+
90130
--color-background: var(--background);
91131
--color-foreground: var(--foreground);
92132
--color-card: var(--card);
93133
--color-card-foreground: var(--card-foreground);
94134
--color-popover: var(--popover);
95135
--color-popover-foreground: var(--popover-foreground);
96-
--color-primary: var(--primary);
97-
--color-primary-foreground: var(--primary-foreground);
136+
--color-primary: var(--bgAccentPrimary);
137+
--color-primary-hover: var(--bgAccent);
138+
--color-primary-foreground: var(--fgAccent);
98139
--color-secondary: var(--secondary);
99140
--color-secondary-foreground: var(--secondary-foreground);
100141
--color-muted: var(--muted);
@@ -119,13 +160,17 @@
119160
--color-sidebar-border: var(--sidebar-border);
120161
--color-sidebar-ring: var(--sidebar-ring);
121162

122-
--color-button: var(--button);
123-
--color-button-border: var(--button-border);
124-
--color-button-foreground: var(--button-foreground);
163+
--color-button: var(--bg2);
164+
--color-button-hover: var(--bg3);
165+
--color-button-foreground: var(--fg1);
166+
--color-button-primary: var(--bg2);
167+
--color-button-primary-foreground: var(--fgSerious);
168+
--color-button-secondary: var(--bgAccentPrimary);
169+
--color-button-secondary-foreground: var(--fgAccent);
125170

126-
--color-destructive: var(--destructive);
127-
--color-destructive-border: var(--destructive-border);
128-
--color-destructive-foreground: var(--destructive-foreground);
171+
--color-destructive: var(--bgSerious);
172+
--color-destructive-hover: var(--bgSerious2);
173+
--color-destructive-foreground: var(--fgSerious);
129174
}
130175

131176
@layer base {
@@ -138,18 +183,39 @@
138183
}
139184

140185
@layer utils {
141-
.animate-text-gradient {
142-
animation: slide-text-gradient 5s linear infinite;
186+
.animate-text-shimmer {
187+
animation-delay: 0.5s;
188+
animation-duration: 3s;
189+
animation-iteration-count: infinite;
190+
animation-name: text-shimmer;
191+
background: var(--muted-foreground)
192+
gradient(
193+
linear,
194+
100% 0,
195+
0 0,
196+
from(var(--muted-foreground)),
197+
color-stop(0.5, var(--secondary-foreground)),
198+
to(var(--muted-foreground))
199+
);
200+
background: var(--muted-foreground) -webkit-gradient(
201+
linear,
202+
100% 0,
203+
0 0,
204+
from(var(--muted-foreground)),
205+
color-stop(0.5, var(--secondary-foreground)),
206+
to(var(--muted-foreground))
207+
);
208+
background-repeat: no-repeat;
209+
background-size: 50% 200%;
210+
display: inline-block;
143211
}
144212

145-
@keyframes slide-text-gradient {
213+
@keyframes text-shimmer {
146214
0% {
147-
width: 300px;
148-
background-position-x: 0;
215+
background-position: -100% 0;
149216
}
150217
100% {
151-
width: 300px;
152-
background-position-x: 300px;
218+
background-position: 250% 0;
153219
}
154220
}
155221
}

components/app.tsx

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -68,28 +68,6 @@ export function App({ appConfig }: AppProps) {
6868

6969
return (
7070
<>
71-
<header className="fixed top-0 left-0 z-50 hidden w-full flex-row justify-between p-6 md:flex">
72-
<a
73-
target="_blank"
74-
rel="noopener noreferrer"
75-
href="https://livekit.io"
76-
className="scale-100 transition-transform duration-300 hover:scale-110"
77-
>
78-
<img src="/lk-logo.svg" alt="LiveKit Logo" className="size-6" />
79-
</a>
80-
<span className="text-foreground font-mono text-xs font-bold tracking-wider uppercase">
81-
Built with{' '}
82-
<a
83-
target="_blank"
84-
rel="noopener noreferrer"
85-
href="https://github.com/livekit/agents"
86-
className="underline underline-offset-4"
87-
>
88-
LiveKit Agents
89-
</a>
90-
</span>
91-
</header>
92-
9371
<RoomContext.Provider value={room}>
9472
<motion.div
9573
key="session-view"

components/livekit/agent-control-bar/agent-control-bar.tsx

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function AgentControlBar({
6767
<div
6868
aria-label="Voice assistant controls"
6969
className={cn(
70-
'bg-background flex flex-col rounded-md border p-3 drop-shadow-xl/3',
70+
'bg-background flex flex-col rounded-[31px] p-3 shadow-[0_0_4px_rgba(0,0,0,0.05)] drop-shadow-md/3',
7171
className
7272
)}
7373
{...props}
@@ -88,58 +88,80 @@ export function AgentControlBar({
8888
)}
8989

9090
<div className="flex flex-row justify-between gap-1">
91-
<div className="flex w-full gap-1">
91+
<div className="flex gap-1">
9292
{visibleControls.microphone && (
9393
<div className="flex items-center gap-0">
9494
<TrackToggle
95-
className="peer relative w-auto md:rounded-r-none md:border-r-0"
95+
variant="primary"
9696
source={Track.Source.Microphone}
97+
className="peer/track group/track relative w-auto pr-3 pl-3 md:rounded-r-none md:border-r-0 md:pr-1"
9798
>
9899
<BarVisualizer
99-
className="flex h-full w-auto items-center justify-center gap-0.5"
100+
barCount={5}
100101
trackRef={micTrackRef}
101-
barCount={12}
102102
options={{ minHeight: 5 }}
103+
className="flex h-full w-auto items-center justify-center gap-0.5"
103104
>
104-
<span className="data-lk-highlighted:bg-foreground data-lk-muted:bg-muted h-full w-0.5 origin-center rounded-2xl"></span>
105+
<span
106+
className={cn([
107+
'h-full w-0.5 origin-center rounded-2xl',
108+
'group-data-[state=on]/track:bg-fg1 group-data-[state=off]/track:bg-destructive-foreground',
109+
'data-lk-muted:bg-muted',
110+
])}
111+
></span>
105112
</BarVisualizer>
106113
</TrackToggle>
107114
<DeviceSelect
108-
className="peer-data-[state=on]:border-button-foreground hidden rounded-l-none border-l-0 md:block"
109115
size="sm"
110116
kind="audioinput"
111-
onActiveDeviceChange={handleDeviceChange}
112117
onError={handleError}
118+
onActiveDeviceChange={handleDeviceChange}
119+
className={cn([
120+
'peer-data-[state=off]/track:text-destructive-foreground',
121+
'hover:text-fg1 focus:text-fg1',
122+
'hover:peer-data-[state=off]/track:text-destructive-foreground focus:peer-data-[state=off]/track:text-destructive-foreground',
123+
'hidden rounded-l-none md:block',
124+
])}
113125
/>
114126
</div>
115127
)}
116128

117129
{capabilities.suportsVideoInput && visibleControls.camera && (
118130
<div className="flex items-center gap-0">
119131
<TrackToggle
120-
className="peer relative w-auto md:rounded-r-none md:border-r-0"
132+
variant="primary"
121133
source={Track.Source.Camera}
134+
className="peer/track relative w-auto pr-3 pl-3 md:rounded-r-none md:border-r-0 md:pr-1"
122135
/>
123136
<DeviceSelect
124-
className="peer-data-[state=on]:border-button-foreground hidden rounded-l-none border-l-0 md:block"
125137
size="sm"
126138
kind="videoinput"
127-
onActiveDeviceChange={handleDeviceChange}
128139
onError={handleError}
140+
onActiveDeviceChange={handleDeviceChange}
141+
className={cn([
142+
'peer-data-[state=off]/track:text-destructive-foreground',
143+
'hover:text-fg1 focus:text-fg1',
144+
'hover:peer-data-[state=off]/track:text-destructive-foreground focus:peer-data-[state=off]/track:text-destructive-foreground',
145+
'hidden rounded-l-none md:block',
146+
])}
129147
/>
130148
</div>
131149
)}
132150

133151
{capabilities.suportsScreenShare && visibleControls.screenShare && (
134152
<div className="flex items-center gap-0">
135-
<TrackToggle className="relative w-auto" source={Track.Source.ScreenShare} />
153+
<TrackToggle
154+
variant="secondary"
155+
className="relative w-auto"
156+
source={Track.Source.ScreenShare}
157+
/>
136158
</div>
137159
)}
138160

139161
{visibleControls.chat && (
140162
<Toggle
163+
variant="secondary"
141164
aria-label="Toggle chat"
142-
variant="outline"
143165
pressed={chatOpen}
144166
onPressedChange={setChatOpen}
145167
className="aspect-square h-full"

components/livekit/chat/chat-input.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ export function ChatInput({ onSend, className, disabled, ...props }: ChatInputPr
3737
disabled={disabled}
3838
/>
3939
<Button
40-
type="submit"
4140
size="sm"
42-
variant={isDisabled ? 'secondary' : 'default'}
41+
type="submit"
42+
variant={isDisabled ? 'secondary' : 'primary'}
4343
disabled={isDisabled}
4444
className="font-mono"
4545
>

components/livekit/device-select.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ type DeviceSelectProps = React.ComponentProps<typeof SelectTrigger> & {
2424
};
2525

2626
const selectVariants = cva(
27-
'w-full rounded-md border px-3 py-2 text-sm cursor-pointer disabled:not-allowed',
27+
[
28+
'w-full rounded-full pl-1 pr-3 py-2 text-sm cursor-pointer',
29+
'disabled:not-allowed hover:bg-button-hover focus:bg-button-hover',
30+
],
2831
{
2932
variants: {
3033
size: {

components/livekit/track-toggle.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,16 @@ function getSourceIcon(source: Track.Source, enabled: boolean) {
2626
}
2727
}
2828

29-
export function TrackToggle(props: TrackToggleProps) {
30-
const { enabled, pending, toggle } = useTrackToggle({
31-
source: props.source,
32-
});
33-
const variant = props.variant || 'outline';
34-
const icon = getSourceIcon(props.source, enabled);
29+
export function TrackToggle({ source, ...props }: TrackToggleProps) {
30+
const { enabled, pending, toggle } = useTrackToggle({ source });
31+
const icon = getSourceIcon(source, enabled);
32+
3533
return (
3634
<Toggle
37-
variant={variant}
38-
aria-label={`Toggle ${props.source}`}
39-
onPressedChange={() => {
40-
console.log('toggle change');
41-
toggle();
42-
}}
35+
pressed={enabled}
4336
disabled={pending}
37+
aria-label={`Toggle ${source}`}
38+
onPressedChange={toggle}
4439
{...props}
4540
>
4641
{icon}

0 commit comments

Comments
 (0)