Skip to content

Commit de7ce9b

Browse files
fix(shadcn): agents ui updates (#1273)
1 parent 1d35ce1 commit de7ce9b

10 files changed

Lines changed: 82 additions & 46 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Agents UI is a set of open source [Shadcn](https://ui.shadcn.com/) components fo
2929

3030
You can find more information in the [Agents UI API references](https://docs.livekit.io/reference/components/shadcn/) and in the [Agents UI README](packages/shadcn/README.md).
3131

32-
## Prerequisites {% #prerequisites %}
32+
## Prerequisites
3333

3434
Before installing Agents UI, make sure your environment meets the following requirements:
3535

docs/storybook/stories/agents-ui/AgentAudioVisualizerGrid.stories.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ export default {
1515
return <AgentAudioVisualizerGrid {...args} audioTrack={audioTrack} />;
1616
},
1717
args: {
18-
default: 'lg',
18+
size: 'lg',
1919
state: 'connecting',
2020
radius: 5,
2121
interval: 100,
22-
rowCount: 10,
23-
columnCount: 10,
22+
rowCount: 9,
23+
columnCount: 9,
2424
},
2525
argTypes: {
2626
size: {
@@ -63,6 +63,12 @@ export default {
6363
},
6464
};
6565

66+
export const Default: StoryObj<AgentAudioVisualizerGridProps> = {
67+
args: {
68+
69+
},
70+
};
71+
6672
export const Demo1: StoryObj<AgentAudioVisualizerGridProps> = {
6773
args: {
6874
className:

docs/storybook/stories/agents-ui/AgentAudioVisualizerWave.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default {
1818
size: 'xl',
1919
lineWidth: 2,
2020
state: 'connecting',
21-
smoothing: 0.1,
21+
blur: 0.1,
2222
color: '#1FD5F9',
2323
},
2424
argTypes: {
@@ -43,7 +43,7 @@ export default {
4343
lineWidth: {
4444
control: { type: 'range', min: 1, max: 20, step: 1 },
4545
},
46-
smoothing: {
46+
blur: {
4747
control: { type: 'range', min: 0, max: 10, step: 0.5 },
4848
},
4949
color: {

packages/shadcn/README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ Located in `components/agents-ui/`, these are the primary components for buildin
1919
| `AgentDisconnectButton` | Button to end the agent session |
2020
| `AgentChatTranscript` | Displays the conversation transcript including voice transcriptions |
2121
| `AgentChatIndicator` | Visual indicator for agent thinking/processing state |
22-
| `AgentAudioVisualizerBar` | Linear bar audio visualizer |
23-
| `AgentAudioVisualizerGrid` | Grid-based audio visualizer |
24-
| `AgentAudioVisualizerRadial` | Radial/circular audio visualizer |
22+
| `AgentAudioVisualizerBar` | Audio visualizer with horizontal set of animated bars |
23+
| `AgentAudioVisualizerRadial` | Audio visualizer with a radial set of animated bars |
24+
| `AgentAudioVisualizerWave` | Audio visualizer with an animated wave |
25+
| `AgentAudioVisualizerAura` | Audio visualizer with an animated aura ring |
2526
| `StartAudioButton` | Button to start audio when browser blocks autoplay |
2627

2728
## Prerequisites
@@ -176,6 +177,10 @@ DEST_PROP_TYPES_PATH=/path/to/destination/prop-types.json
176177
- `livekit-client` - LiveKit client SDK
177178
- `react` ^19.0.0
178179
- `react-dom` ^19.0.0
180+
- `tailwindcss` ^4
181+
- `shadcn` ^3.5.1
182+
- `motion` ^12.16.0
183+
- `ai` ^5.0.105
179184

180185
## Reporting issues
181186

packages/shadcn/components/agents-ui/agent-audio-visualizer-aura.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ export const AgentAudioVisualizerAuraVariants = cva(['aspect-square'], {
363363
export interface AgentAudioVisualizerAuraProps {
364364
/**
365365
* The size of the visualizer.
366-
* @defaultValue 'md'
366+
* @defaultValue 'lg'
367367
*/
368368
size?: 'icon' | 'sm' | 'md' | 'lg' | 'xl';
369369
/**
@@ -409,7 +409,7 @@ export interface AgentAudioVisualizerAuraProps {
409409
* ```
410410
*/
411411
export function AgentAudioVisualizerAura({
412-
size = 'md',
412+
size = 'lg',
413413
state = 'connecting',
414414
color = DEFAULT_COLOR,
415415
colorShift = 0.05,

packages/shadcn/components/agents-ui/agent-audio-visualizer-grid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ export const AgentAudioVisualizerGridVariants = cva(
5656
{
5757
variants: {
5858
size: {
59-
icon: ['gap-[2px] *:size-[4px]'],
59+
icon: ['gap-[2px] *:size-[2px]'],
6060
sm: ['gap-[4px] *:size-[4px]'],
6161
md: ['gap-[8px] *:size-[8px]'],
62-
lg: ['gap-[8px] *:size-[8px]'],
63-
xl: ['gap-[8px] *:size-[8px]'],
62+
lg: ['gap-[12px] *:size-[12px]'],
63+
xl: ['gap-[16px] *:size-[16px]'],
6464
},
6565
},
6666
defaultVariants: {

packages/shadcn/components/agents-ui/agent-audio-visualizer-radial.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ import { useAgentAudioVisualizerRadialAnimator } from '@/hooks/agents-ui/use-age
1414
export const AgentAudioVisualizerRadialVariants = cva(
1515
[
1616
'relative flex items-center justify-center',
17+
'[&_[data-lk-index]]:bg-current/10',
1718
'[&_[data-lk-index]]:absolute [&_[data-lk-index]]:top-1/2 [&_[data-lk-index]]:left-1/2 [&_[data-lk-index]]:origin-bottom [&_[data-lk-index]]:-translate-x-1/2',
18-
'[&_[data-lk-index]]:rounded-full [&_[data-lk-index]]:transition-colors [&_[data-lk-index]]:duration-150 [&_[data-lk-index]]:ease-linear [&_[data-lk-index]]:bg-transparent [&_[data-lk-index]]:data-[lk-highlighted=true]:bg-current',
19-
'has-data-[lk-state=connecting]:[&_[data-lk-index]]:duration-300 has-data-[lk-state=connecting]:[&_[data-lk-index]]:bg-current/10',
20-
'has-data-[lk-state=initializing]:[&_[data-lk-index]]:duration-300 has-data-[lk-state=initializing]:[&_[data-lk-index]]:bg-current/10',
21-
'has-data-[lk-state=listening]:[&_[data-lk-index]]:duration-300 has-data-[lk-state=listening]:[&_[data-lk-index]]:bg-current/10 has-data-[lk-state=listening]:[&_[data-lk-index]]:duration-300',
19+
'[&_[data-lk-index]]:rounded-full [&_[data-lk-index]]:transition-colors [&_[data-lk-index]]:duration-150 [&_[data-lk-index]]:ease-linear [&_[data-lk-index]]:data-[lk-highlighted=true]:bg-current',
20+
'has-data-[lk-state=connecting]:[&_[data-lk-index]]:duration-300',
21+
'has-data-[lk-state=initializing]:[&_[data-lk-index]]:duration-300',
22+
'has-data-[lk-state=listening]:[&_[data-lk-index]]:duration-300 has-data-[lk-state=listening]:[&_[data-lk-index]]:duration-300',
2223
'has-data-[lk-state=thinking]:animate-spin has-data-[lk-state=thinking]:[animation-duration:5s] has-data-[lk-state=thinking]:[&_[data-lk-index]]:bg-current',
2324
],
2425
{

packages/shadcn/components/agents-ui/agent-audio-visualizer-wave.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,10 @@ interface WaveShaderProps {
158158
*/
159159
lineWidth?: number;
160160
/**
161-
* Smoothing of the oscilloscope in pixels
161+
* Blur of the oscilloscope in pixels
162162
* @default 0.5
163163
*/
164-
smoothing?: number;
164+
blur?: number;
165165
}
166166

167167
function WaveShader({
@@ -171,7 +171,7 @@ function WaveShader({
171171
amplitude = 0.02,
172172
frequency = 20.0,
173173
lineWidth = 2.0,
174-
smoothing = 0.5,
174+
blur = 0.5,
175175
ref,
176176
className,
177177
...props
@@ -189,7 +189,7 @@ function WaveShader({
189189
uFrequency: { type: '1f', value: frequency },
190190
uMix: { type: '1f', value: mix },
191191
uLineWidth: { type: '1f', value: lineWidth },
192-
uSmoothing: { type: '1f', value: smoothing },
192+
uSmoothing: { type: '1f', value: blur },
193193
uColor: { type: '3fv', value: rgbColor },
194194
}}
195195
onError={(error) => {
@@ -209,22 +209,22 @@ WaveShader.displayName = 'WaveShader';
209209
export const AgentAudioVisualizerWaveVariants = cva(['aspect-square'], {
210210
variants: {
211211
size: {
212-
icon: 'h-[24px] gap-[2px]',
213-
sm: 'h-[56px] gap-[4px]',
214-
md: 'h-[112px] gap-[8px]',
215-
lg: 'h-[224px] gap-[16px]',
216-
xl: 'h-[448px] gap-[32px]',
212+
icon: 'h-[24px]',
213+
sm: 'h-[56px]',
214+
md: 'h-[112px]',
215+
lg: 'h-[224px]',
216+
xl: 'h-[448px]',
217217
},
218218
},
219219
defaultVariants: {
220-
size: 'md',
220+
size: 'lg',
221221
},
222222
});
223223

224224
export interface AgentAudioVisualizerWaveProps {
225225
/**
226226
* The size of the visualizer.
227-
* @defaultValue 'md'
227+
* @defaultValue 'lg'
228228
*/
229229
size?: 'icon' | 'sm' | 'md' | 'lg' | 'xl';
230230
/**
@@ -243,10 +243,10 @@ export interface AgentAudioVisualizerWaveProps {
243243
*/
244244
lineWidth?: number;
245245
/**
246-
* The smoothing of the wave in pixels.
246+
* The blur of the wave in pixels.
247247
* @defaultValue 0.5
248248
*/
249-
smoothing?: number;
249+
blur?: number;
250250
/**
251251
* The audio track to visualize. Can be a local/remote audio track or a track reference.
252252
*/
@@ -270,7 +270,7 @@ export interface AgentAudioVisualizerWaveProps {
270270
* state="speaking"
271271
* color="#1FD5F9"
272272
* lineWidth={2}
273-
* smoothing={0.5}
273+
* blur={0.5}
274274
* audioTrack={audioTrack}
275275
* />
276276
* ```
@@ -280,7 +280,7 @@ export function AgentAudioVisualizerWave({
280280
state = 'speaking',
281281
color,
282282
lineWidth,
283-
smoothing,
283+
blur,
284284
audioTrack,
285285
className,
286286
style,
@@ -315,7 +315,7 @@ export function AgentAudioVisualizerWave({
315315
amplitude={amplitude}
316316
frequency={frequency}
317317
lineWidth={_lineWidth}
318-
smoothing={smoothing}
318+
blur={blur}
319319
style={{ opacity, ...style }}
320320
className={cn(
321321
AgentAudioVisualizerWaveVariants({ size }),

packages/shadcn/components/agents-ui/agent-control-bar.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,16 @@ function AgentChatInput({ chatOpen, onSend = async () => {}, className }: AgentC
7171
const inputRef = useRef<HTMLTextAreaElement>(null);
7272
const [isSending, setIsSending] = useState(false);
7373
const [message, setMessage] = useState<string>('');
74+
const isDisabled = isSending || message.trim().length === 0;
7475

75-
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
76-
e.preventDefault();
76+
const handleSend = async () => {
77+
if (isDisabled) {
78+
return;
79+
}
7780

7881
try {
7982
setIsSending(true);
80-
await onSend(message);
83+
await onSend(message.trim());
8184
setMessage('');
8285
} catch (error) {
8386
console.error(error);
@@ -86,7 +89,17 @@ function AgentChatInput({ chatOpen, onSend = async () => {}, className }: AgentC
8689
}
8790
};
8891

89-
const isDisabled = isSending || message.trim().length === 0;
92+
const handleKeyDown = async (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
93+
if (e.key === 'Enter' && !e.shiftKey) {
94+
e.preventDefault();
95+
handleSend();
96+
}
97+
};
98+
99+
const handleButtonClick = async () => {
100+
if (isDisabled) return;
101+
await handleSend();
102+
};
90103

91104
useEffect(() => {
92105
if (chatOpen) return;
@@ -95,30 +108,31 @@ function AgentChatInput({ chatOpen, onSend = async () => {}, className }: AgentC
95108
}, [chatOpen]);
96109

97110
return (
98-
<form
99-
onSubmit={handleSubmit}
111+
<div
100112
className={cn('mb-3 flex grow items-end gap-2 rounded-md pl-1 text-sm', className)}
101113
>
102114
<textarea
103115
autoFocus
104116
ref={inputRef}
105117
value={message}
106-
disabled={!chatOpen}
118+
disabled={!chatOpen || isSending}
107119
placeholder="Type something..."
120+
onKeyDown={handleKeyDown}
108121
onChange={(e) => setMessage(e.target.value)}
109-
className="field-sizing-content max-h-16 min-h-8 flex-1 py-2 [scrollbar-width:thin] focus:outline-none disabled:cursor-not-allowed disabled:opacity-50"
122+
className="field-sizing-content max-h-16 min-h-8 flex-1 py-2 [scrollbar-width:thin] focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 resize-none"
110123
/>
111124
<Button
112125
size="icon"
113-
type="submit"
126+
type="button"
114127
disabled={isDisabled}
115128
variant={isDisabled ? 'secondary' : 'default'}
116129
title={isSending ? 'Sending...' : 'Send'}
130+
onClick={handleButtonClick}
117131
className="self-end disabled:cursor-not-allowed"
118132
>
119133
{isSending ? <Loader className="animate-spin" /> : <SendHorizontal />}
120134
</Button>
121-
</form>
135+
</div>
122136
);
123137
}
124138

packages/shadcn/components/agents-ui/agent-track-toggle.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ import {
1010
VideoIcon,
1111
VideoOffIcon,
1212
} from 'lucide-react';
13-
import { Toggle, toggleVariants } from '@/components/ui/toggle';
13+
import { Toggle } from '@/components/ui/toggle';
1414
import { cn } from '@/lib/utils';
1515

1616
export const agentTrackToggleVariants = cva(['size-9'], {
1717
variants: {
18+
size: {
19+
default: 'h-9 px-2 min-w-9',
20+
sm: 'h-8 px-1.5 min-w-8',
21+
lg: 'h-10 px-2.5 min-w-10',
22+
},
1823
variant: {
1924
default: [
2025
'data-[state=off]:bg-destructive/10 data-[state=off]:text-destructive',
@@ -58,8 +63,12 @@ function getSourceIcon(source: Track.Source, enabled: boolean, pending = false)
5863
/**
5964
* Props for the AgentTrackToggle component.
6065
*/
61-
export type AgentTrackToggleProps = VariantProps<typeof toggleVariants> &
66+
export type AgentTrackToggleProps = VariantProps<typeof agentTrackToggleVariants> &
6267
ComponentProps<'button'> & {
68+
/**
69+
* The size of the toggle.
70+
*/
71+
size?: 'sm' | 'default' | 'lg';
6372
/**
6473
* The variant of the toggle.
6574
* @defaultValue 'default'
@@ -129,6 +138,7 @@ export function AgentTrackToggle({
129138
onPressedChange={onPressedChange}
130139
className={cn(
131140
agentTrackToggleVariants({
141+
size,
132142
variant: variant ?? 'default',
133143
className,
134144
}),

0 commit comments

Comments
 (0)