React UI Components
API reference for @deepgram/ui — composable components for building voice agent UIs with Deepgram. Includes orb visualizer, waveforms, frequency bars, conversation display, and CSS custom property theming.
Installation
Section titled “Installation”npm install @deepgram/uiImport the stylesheet in your app's entry point:
import "@deepgram/ui/styles.css";Live Preview
Section titled “Live Preview”The embedded widget below uses the components documented on this page — conversation panel, start button, microphone toggle, speaker toggle, text input, and the orb visualizer.
A complete voice agent interface in under 30 lines:
import {
AgentProvider,
AgentConversation,
AgentTextInput,
AgentStartButton,
AgentMicrophoneButton,
AgentSpeakerButton,
Orb,
} from "@deepgram/ui";
import "@deepgram/ui/styles.css";
function App() {
return (
<AgentProvider
config={{
auth: { tokenFactory: () => fetch("/api/token").then((r) => r.text()) },
agent: "YOUR_AGENT_ID",
}}
>
<div data-dg-agent>
<Orb size={120} />
<AgentConversation />
<AgentTextInput />
<div>
<AgentStartButton />
<AgentMicrophoneButton />
<AgentSpeakerButton />
</div>
</div>
</AgentProvider>
);
}Replace YOUR_AGENT_ID with a Reusable Agent Configuration UUID, or pass an inline agent config object instead. See Agent Configuration for both patterns.
Every component is optional. Use one or all, and mix them with your own components inside the provider.
Display Components
Section titled “Display Components”AgentStatus
Section titled “AgentStatus”Renders the current connection state as a text label. Updates automatically as the session connects, disconnects, or reconnects.
Connected
<AgentStatus />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
labels |
Partial<Record<string, string>> |
See below | Override the display text for each state. |
Default labels: "Not started", "Connecting...", "Connected", "Reconnecting...", "Disconnected".
<AgentStatus
labels={{
idle: "Ready",
connecting: "Connecting...",
connected: "Live",
disconnected: "Offline",
}}
/>Data attributes: data-agent-status, data-state (current state value).
AgentConversation
Section titled “AgentConversation”Scrollable conversation history showing user and agent messages.
What time is my next meeting?
You have a 1:1 with Sarah at 3:30 PM.
<AgentConversation />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | CSS class for the container. |
itemClassName |
string |
— | CSS class applied to each message. |
renderMessage |
(entry: ConversationEntry) => ReactNode |
— | Custom render function for messages. |
emptyState |
ReactNode |
— | Content shown when conversation is empty. |
autoScroll |
boolean |
true |
Scroll to latest message automatically. |
<AgentConversation
emptyState={<p>Say something to start the conversation.</p>}
renderMessage={(entry) => (
<div className={entry.role === "user" ? "user-msg" : "agent-msg"}>
{entry.content}
</div>
)}
/>Data attributes: data-agent-conversation on the container, data-role="user" or data-role="assistant" on each message.
Response
Section titled “Response”Lightweight markdown renderer for agent text. Handles bold, italic, inline code, code blocks, lists, headings, links, and horizontal rules. Supports streaming — update the children string as tokens arrive.
Voice agents combine speech-to-text, an LLM, and text-to-speech in a single connection.
- Low-latency conversation
- Natural prosody
<Response>{markdownString}</Response>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
children |
string |
— | Markdown string to render. |
className |
string |
— | Additional CSS class. |
Data attributes: data-agent-response.
Input Components
Section titled “Input Components”AgentTextInput
Section titled “AgentTextInput”Text input field for sending messages to the agent. Submits on Enter (Shift+Enter for newline).
Send
<AgentTextInput />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
placeholder |
string |
"Type a message..." |
Input placeholder text. |
disabled |
boolean |
false |
Disable the input. |
onSend |
(text: string) => void |
— | Callback when a message is sent. |
submitButton |
ReactNode |
— | Custom send button element. |
Data attributes: data-agent-text-input.
Control Components
Section titled “Control Components”AgentStartButton
Section titled “AgentStartButton”Connect/disconnect toggle button. Reflects the current session state automatically.
Start
<AgentStartButton />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
startLabel |
ReactNode |
"Start" |
Label when idle. |
connectingLabel |
ReactNode |
"Connecting..." |
Label while connecting. |
stopLabel |
ReactNode |
"Stop" |
Label when connected. |
reconnectingLabel |
ReactNode |
"Reconnecting..." |
Label while reconnecting. |
onClick |
() => void |
— | Optional click handler override. |
Data attributes: data-agent-start-button, data-state (current state value).
AgentMicrophoneButton
Section titled “AgentMicrophoneButton”Microphone mute/unmute toggle. Renders SVG mic icons by default.
<AgentMicrophoneButton />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
activeLabel |
ReactNode |
Mic icon | Content when microphone is active. |
mutedLabel |
ReactNode |
Mic-off icon | Content when muted. |
disabledLabel |
ReactNode |
— | Content when microphone is unavailable. Returns null if omitted. |
onClick |
() => void |
— | Optional click handler override. |
Data attributes: data-agent-mic-button, data-state ("active", "muted", "inactive", or "disabled").
AgentSpeakerButton
Section titled “AgentSpeakerButton”Speaker mute/unmute toggle. Renders SVG speaker icons by default.
<AgentSpeakerButton />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
activeLabel |
ReactNode |
Speaker icon | Content when speaker is active. |
mutedLabel |
ReactNode |
Speaker-off icon | Content when muted. |
onClick |
() => void |
— | Optional click handler override. |
Data attributes: data-agent-speaker-button, data-state ("active" or "muted").
VoiceButton
Section titled “VoiceButton”All-in-one button that combines connection and mode state into a single control. The appearance changes across five lifecycle states: idle, connecting, listening, speaking, and error.
<VoiceButton />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
className |
string |
— | Additional CSS class. |
labels |
Partial<Record<VoiceButtonState, ReactNode>> |
See below | Text for each state. |
onClick |
() => void |
— | Optional click handler override. |
Default labels: "Start conversation", "Connecting...", "Listening...", "Agent speaking", "Error".
Style each state with the data-voice-state attribute:
[data-voice-state="listening"] {
border-color: var(--dg-va-primary);
}
[data-voice-state="speaking"] {
background: var(--dg-va-primary);
animation: pulse 1.5s infinite;
}Data attributes: data-agent-voice-button, data-voice-state ("idle", "connecting", "listening", "speaking", "error").
Visualization Components
Section titled “Visualization Components”Deepgram's animated hoop visualization. Canvas 2D rendering of four crescent arcs with gradient colors — lightweight and works everywhere without WebGL. Audio-reactive: the orb responds to actual microphone input and agent playback volume in real time.
Three visual states:
- idle — deflated crescent, slow rocking, minimal animation
- listening — full circle, gentle pulse, mic-reactive radius flutter
- talking — crescent mouth, fast rotation, volume-modulated mouth movement
<Orb size={200} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
size |
number |
200 |
Diameter in pixels. |
colors |
[string, string] |
Deepgram greens | Two gradient colors. |
state |
"idle" | "listening" | "talking" |
"idle" |
Visual state. |
getInputVolume |
() => number |
— | Getter sampled per frame for mic volume (0--1). |
getOutputVolume |
() => number |
— | Getter sampled per frame for output volume (0--1). |
inputVolume |
number |
— | Direct mic volume value (0--1) for manual control. |
outputVolume |
number |
— | Direct output volume value (0--1) for manual control. |
className |
string |
— | Additional CSS class. |
Automatic mode (default inside AgentProvider):
<Orb />The orb reads getInputVolume() and getOutputVolume() every animation frame with zero re-renders.
Manual mode — push volume values directly:
<Orb inputVolume={0.5} outputVolume={0.3} state="talking" />Custom volume sources:
<Orb
getInputVolume={myMicAnalyser}
getOutputVolume={myPlayerAnalyser}
/>Custom colors:
<Orb colors={["#6366f1", "#ec4899"]} />Data attributes: data-agent-orb, data-orb-state ("idle", "listening", "talking").
BarVisualizer
Section titled “BarVisualizer”Real-time frequency bar visualization. Renders vertical bars on a canvas that react to audio input or output.
<BarVisualizer source="output" barCount={16} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
source |
"input" | "output" |
"output" |
Microphone or agent audio. |
barCount |
number |
16 |
Number of frequency bars. |
className |
string |
— | Additional CSS class. |
Data attributes: data-agent-bar-visualizer.
LiveWaveform
Section titled “LiveWaveform”Smooth oscillating waveform driven by a volume source. Blends two sine waves for an organic feel.
import { useAgentMicrophone } from "@deepgram/ui";
function MyWaveform() {
const { getInputVolume } = useAgentMicrophone();
return <LiveWaveform getVolume={getInputVolume} />;
}Props:
| Prop | Type | Default | Description |
|---|---|---|---|
getVolume |
(() => number) | (() => number)[] |
— | Volume source(s) returning 0--1. When multiple are provided, the max value is used per frame. |
active |
boolean |
true |
Whether the waveform animates. Renders a flat line when false. |
color |
string |
--dg-va-primary |
Line color. |
lineWidth |
number |
2 |
Stroke width in pixels. |
className |
string |
— | Additional CSS class. |
Data attributes: data-agent-live-waveform.
Utility Components
Section titled “Utility Components”MicSelector
Section titled “MicSelector”Dropdown for selecting the audio input device. Enumerates available microphones, requests permission on first open, and updates automatically when devices are plugged in or removed.
const [deviceId, setDeviceId] = useState("");
<MicSelector value={deviceId} onValueChange={setDeviceId} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
— | Currently selected device ID (controlled). |
onValueChange |
(deviceId: string) => void |
— | Callback when the user selects a device. |
className |
string |
— | Additional CSS class. |
disabled |
boolean |
false |
Disable the selector. |
Data attributes: data-agent-mic-selector.
Theming
Section titled “Theming”All components use CSS custom properties scoped to [data-dg-agent]. Add this attribute to your container element to apply the theme. Because these are standard CSS custom properties, they work with any CSS framework — Tailwind, CSS Modules, or plain stylesheets.
<div data-dg-agent>
<AgentConversation />
<AgentTextInput />
</div>Design tokens
Section titled “Design tokens”Tokens follow the shadcn --color-* naming convention generated by Tailwind v4's @theme. The package ships sensible light defaults; dark values are applied automatically when [data-dg-scheme="dark"] is set or when the user's system prefers dark mode. Override any token on a [data-dg-agent] ancestor to retheme.
[data-dg-agent] {
/* Brand */
--color-primary: #13ef93;
--color-primary-foreground: #000000;
/* Surfaces */
--color-background: #ffffff;
--color-foreground: #111827;
--color-card: #f3f4f6;
--color-card-foreground: #111827;
--color-popover: #ffffff;
--color-popover-foreground: #111827;
--color-muted: #f3f4f6;
--color-muted-foreground: #6b7280;
--color-accent: #f9fafb;
--color-accent-foreground: #111827;
--color-input: #f3f4f6;
--color-border: rgba(0, 0, 0, 0.1);
--color-ring: #13ef93;
--color-secondary: #f3f4f6;
--color-secondary-foreground: #111827;
--color-destructive: #dc2626;
--color-destructive-foreground:#ffffff;
/* Typography & shape */
--font-sans: system-ui, -apple-system, sans-serif;
--radius: 1rem;
/* Widget layout (panel + FAB sizing) */
--dg-va-panel-w: min(440px, 100vw);
--dg-va-fab-size: 56px;
--dg-va-padding: 16px;
/* Derived from --color-primary by default — override only if you need a different relationship */
--primary-hover: color-mix(in srgb, var(--color-primary) 85%, #000);
--primary-active: color-mix(in srgb, var(--color-primary) 70%, #000);
--msg-user-bg: color-mix(in srgb, var(--color-primary) 12%, transparent);
--msg-user-border: color-mix(in srgb, var(--color-primary) 30%, transparent);
}Color scheme
Section titled “Color scheme”Light/dark switching is driven by the data-dg-scheme attribute on the same element that has data-dg-agent. Without an explicit value, the components follow the user's prefers-color-scheme.
<div data-dg-agent data-dg-scheme="dark">
{/* Always renders in dark mode */}
</div>| Behaviour | Selector |
|---|---|
| Force dark | [data-dg-agent][data-dg-scheme="dark"] |
| Force light | [data-dg-agent][data-dg-scheme="light"] |
| Follow system (default) | no attribute, prefers-color-scheme: dark triggers dark |
If your app uses Tailwind's dark: variant or next-themes, write a small effect that mirrors that state onto data-dg-scheme. The package does not infer it from a .dark ancestor class.
Custom theme example
Section titled “Custom theme example”A teal-on-midnight palette called Aurora, applied entirely through CSS custom properties on the host element. Same components, completely different feel.
[data-dg-agent].aurora-theme {
/* Brand */
--color-primary: #5eead4;
--color-primary-foreground: #042f2e;
--color-ring: #5eead4;
/* Surfaces */
--color-background: #0a0e1a;
--color-foreground: #e6edf6;
--color-card: #121829;
--color-card-foreground: #e6edf6;
--color-popover: #121829;
--color-popover-foreground: #e6edf6;
--color-muted: #1a2236;
--color-muted-foreground: #94a3b8;
--color-accent: #182238;
--color-accent-foreground: #5eead4;
--color-input: #0d1322;
--color-border: rgba(94, 234, 212, 0.14);
--color-secondary: #1a2236;
--color-secondary-foreground: #5eead4;
/* Derived (override the color-mix defaults for a softer glow) */
--primary-hover: #2dd4bf;
--primary-active: #14b8a6;
--msg-user-bg: rgba(94, 234, 212, 0.10);
--msg-user-border: rgba(94, 234, 212, 0.28);
/* Slightly tighter corners than the default 1rem */
--radius: 14px;
}Apply the class to your [data-dg-agent] container (or extend the override to the element itself) and every component inside picks up the new palette. The same pattern works for any palette — swap the values, keep the keys.
Styling with Data Attributes
Section titled “Styling with Data Attributes”Components use data-agent-* attribute selectors instead of class names. This prevents collisions with your application's CSS framework — no specificity battles with Tailwind utilities or CSS Modules hashes.
/* Target the conversation container */
[data-agent-conversation] {
max-height: 400px;
}
/* Target user messages */
[data-agent-conversation] [data-role="user"] {
text-align: right;
}
/* Target agent messages */
[data-agent-conversation] [data-role="assistant"] {
font-style: italic;
}
/* Target the text input */
[data-agent-text-input] {
font-size: 16px;
}
/* Target the orb by state */
[data-agent-orb][data-orb-state="talking"] {
filter: brightness(1.2);
}Data Attribute Reference
Section titled “Data Attribute Reference”| Component | Attribute | Values |
|---|---|---|
| Container | data-dg-agent |
— |
| Color scheme | data-dg-scheme |
"light", "dark" |
| AgentStatus | data-agent-status, data-state |
"idle", "connecting", "connected", "reconnecting", "disconnected" |
| AgentConversation | data-agent-conversation |
— |
| Messages | data-role |
"user", "assistant" |
| AgentTextInput | data-agent-text-input |
— |
| AgentStartButton | data-agent-start-button, data-state |
"idle", "connecting", "connected", "reconnecting", "disconnected" |
| AgentMicrophoneButton | data-agent-mic-button, data-state |
"active", "muted", "inactive", "disabled" |
| AgentSpeakerButton | data-agent-speaker-button, data-state |
"active", "muted" |
| VoiceButton | data-agent-voice-button, data-voice-state |
"idle", "connecting", "listening", "speaking", "error" |
| Orb | data-agent-orb, data-orb-state |
"idle", "listening", "talking" |
| BarVisualizer | data-agent-bar-visualizer |
— |
| LiveWaveform | data-agent-live-waveform |
— |
| MicSelector | data-agent-mic-selector |
— |
| Response | data-agent-response |
— |