Getting Started
Components
- Agent Status
- Agent Template Card
- API Key Card
- Audio Player
- Bar Visualizer
- Channel Status Card
- Chat Composer
- Code Editor
- Condition Builder
- Confirm Dialog
- Conversation
- Conversation Bar
- Dataset Card
- Document Status Badge
- Extraction Strategy Select
- File Icon
- File Upload
- Indexing Progress
- Live Waveform
- Matrix
- Message
- Mic Selector
- Model Diff View
- Model Selector
- Model Type Filter
- Node Catalog
- Option Editor
- Orb
- Output Variables View
- Package Card
- Prompt Editor
- Provider Status Card
- Radio Card
- Resource Card
- Resource Sidebar
- Response
- Run Node List
- Scrub Bar
- Segment Card
- Shimmering Text
- Speech Input
- Token Trend Chart
- Tool Call Card
- Transcript Viewer
- Usage Stat Card
- Variable Binding Editor
- Variable Selector
- Voice Button
- Voice Picker
- Waveform
- Workflow Node Card
- Workspace Selector
"use client"
import { useState } from "react"
import type { ElevenLabs } from "@elevenlabs/elevenlabs-js"
import { VoicePicker } from "@/components/ui/voice-picker"
const voices: ElevenLabs.Voice[] = [
{
voiceId: "21m00Tcm4TlvDq8ikWAM",
name: "ZGI Guide",
category: "premade",
labels: {
accent: "american",
descriptive: "clear",
age: "young",
gender: "female",
language: "en",
use_case: "product_walkthrough",
},
description:
"Calm, precise product guide for onboarding and support flows.",
previewUrl:
"https://storage.googleapis.com/eleven-public-prod/premade/voices/21m00Tcm4TlvDq8ikWAM/b4928a68-c03b-411f-8533-3d5c299fd451.mp3",
},
{
voiceId: "29vD33N1CtxCmqQRPOHJ",
name: "ZGI Analyst",
category: "premade",
labels: {
accent: "american",
description: "measured",
age: "middle_aged",
gender: "male",
use_case: "analysis",
},
previewUrl:
"https://storage.googleapis.com/eleven-public-prod/premade/voices/29vD33N1CtxCmqQRPOHJ/b99fc51d-12d3-4312-b480-a8a45a7d51ef.mp3",
},
{
voiceId: "2EiwWnXFnvU5JabPnv8n",
name: "ZGI Operator",
category: "premade",
labels: {
accent: "american",
descriptive: "focused",
age: "middle_aged",
gender: "male",
language: "en",
use_case: "workflow_assistant",
},
description: "Focused voice for operational workflows and handoffs.",
previewUrl:
"https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3",
},
]
export function VoicePickerDemo() {
const [selectedVoice, setSelectedVoice] = useState<string>(
"21m00Tcm4TlvDq8ikWAM"
)
const [open, setOpen] = useState(false)
return (
<div className="w-full max-w-lg">
<VoicePicker
voices={voices}
value={selectedVoice}
onValueChange={(value) => {
setSelectedVoice(value)
// Keep dropdown open after selection
setOpen(true)
}}
open={open}
onOpenChange={setOpen}
placeholder="Select a voice..."
/>
</div>
)
}
Installation
pnpm dlx shadcn@latest add https://ui.zgi.ai/r/voice-picker.json
Usage
import { VoicePicker } from "@/components/ui/voice-picker"Basic Usage
import { ElevenLabs } from "@elevenlabs/elevenlabs-js"
const voices: ElevenLabs.Voice[] = [
{
voice_id: "21m00Tcm4TlvDq8ikWAM",
name: "ZGI Guide",
preview_url: "https://example.com/zgi-guide-preview.mp3",
// ... other voice properties
},
// ... more voices
]
const [selectedVoice, setSelectedVoice] = useState("")
<VoicePicker
voices={voices}
value={selectedVoice}
onValueChange={setSelectedVoice}
/>Controlled vs Uncontrolled
import { VoicePicker } from "@/components/ui/voice-picker"
export default ({ voices, selectedVoice, setSelectedVoice }) => (
<>
{/* Controlled */}
<VoicePicker
voices={voices}
value={selectedVoice}
onValueChange={setSelectedVoice}
/>
{/* Uncontrolled */}
<VoicePicker
voices={voices}
onValueChange={(voiceId) => console.log("Selected:", voiceId)}
/>
</>
)Control Open State
const [open, setOpen] = useState(false)
<VoicePicker
voices={voices}
open={open}
onOpenChange={setOpen}
value={selectedVoice}
onValueChange={setSelectedVoice}
/>Custom Placeholder
<VoicePicker
voices={voices}
placeholder="Choose your voice..."
value={selectedVoice}
onValueChange={setSelectedVoice}
/>Fetching Voices from a Provider API
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js"
const [voices, setVoices] = useState<ElevenLabs.Voice[]>([])
useEffect(() => {
const client = new ElevenLabsClient({
apiKey: process.env.ELEVENLABS_API_KEY,
})
client.voices.getAll().then((response) => {
setVoices(response.voices)
})
}, [])
<VoicePicker
voices={voices}
value={selectedVoice}
onValueChange={setSelectedVoice}
/>API Reference
VoicePicker
A searchable dropdown for selecting provider voices with audio preview and orb visualization.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| voices | ElevenLabs.Voice[] | - | Required. Array of provider voices |
| value | string | - | Selected voice ID (controlled) |
| onValueChange | (value: string) => void | - | Callback when selection changes |
| placeholder | string | "Select a voice..." | Placeholder text when no voice selected |
| className | string | - | Optional CSS classes for the trigger button |
| open | boolean | - | Control popover open state |
| onOpenChange | (open: boolean) => void | - | Callback when popover open state changes |
Features
- Search Functionality: Filter voices by name with built-in search
- Audio Preview: Play voice samples with play/pause controls
- Orb Visualization: Visual representation of each voice with the Orb component
- Keyboard Navigation: Full keyboard support for accessibility
- Controlled/Uncontrolled: Supports both controlled and uncontrolled patterns
- Voice Provider Integration: Works with voice API data that includes preview URLs
- Audio Player: Integrated audio playback with shared state management
Notes
- Built on top of Command, Popover, and AudioPlayer components
- Uses
@elevenlabs/elevenlabs-jstypes in the default provider example - Each voice displays with an Orb visualization and preview audio
- Audio playback is managed by AudioPlayerProvider for consistent state
- Search is case-insensitive and filters by voice name
- Supports both controlled (
value/onValueChange) and uncontrolled modes - Open state can be controlled externally via
open/onOpenChangeprops - Keyboard accessible with standard combobox patterns
- Preview URLs from voice objects are used for audio playback
Deploy and Scale Agents with ZGI
ZGI delivers the infrastructure and developer experience you need to ship reliable audio & agent applications at scale.
Talk to an expert