For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Ask AIPlaygroundLoginFree API Key
HomeAPI ReferenceVoice AgentSpeech-to-TextText-to-SpeechIntelligenceSelf-Hosted Deployments
HomeAPI ReferenceVoice AgentSpeech-to-TextText-to-SpeechIntelligenceSelf-Hosted Deployments
  • Get Started
    • Overview
    • Build a Voice Agent
    • Feature Overview
    • Template Apps
  • Configure
    • Overview
    • STT Models
    • LLM Models
    • TTS Models
    • Media Inputs & Outputs
    • Prompting Voice Agents
    • Multilingual Voice Agents
    • Maintaining Context
    • Reusable Agent Configurations
  • Build
      • Overview
      • JavaScript SDK
      • React Hooks & Provider
      • React UI Components
      • Widget Embedding Guide
    • Multi-Agent Architecture
  • Connect
  • Controls
  • Optimize
    • Voice Agent TTS Controls
    • Message Flow
    • Audio & Playback
    • Audio Preprocessing & Barge-In
    • Adaptive Echo Cancellation
  • Resources
    • SDKs
    • UI Components
    • API Reference
LogoLogo
Ask AIPlaygroundLoginFree API Key
On this page
  • Installation
  • Live Preview
  • Usage
  • Display Components
  • AgentStatus
  • AgentConversation
  • Response
  • Input Components
  • AgentTextInput
  • Control Components
  • AgentStartButton
  • AgentMicrophoneButton
  • AgentSpeakerButton
  • VoiceButton
  • Visualization Components
  • Orb
  • BarVisualizer
  • LiveWaveform
  • Utility Components
  • MicSelector
  • Theming
  • Design tokens
  • Color scheme
  • Custom theme example
  • Styling with Data Attributes
  • Data Attribute Reference
BuildBrowser Agent

React UI Components

Pre-built, themeable React components for voice agent interfaces — conversation views, audio-reactive visualizers, and control buttons.

Was this page helpful?
Previous

Widget Embedding Guide

Add a voice agent to any website with a single script tag. Six layout modes, full theming, voice activity detection, and zero build step required.
Next
Built with

These components require an AgentProvider ancestor. See React Hooks for provider setup. For the core JavaScript SDK, see JavaScript.

Installation

$npm install @deepgram/ui

Import the stylesheet in your app’s entry point:

1import "@deepgram/ui/styles.css";

@deepgram/ui re-exports all hooks from @deepgram/react and all types from @deepgram/agents. You can import everything from a single package.

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.

Usage

A complete voice agent interface in under 30 lines:

1import {
2 AgentProvider,
3 AgentConversation,
4 AgentTextInput,
5 AgentStartButton,
6 AgentMicrophoneButton,
7 AgentSpeakerButton,
8 Orb,
9} from "@deepgram/ui";
10import "@deepgram/ui/styles.css";
11
12function App() {
13 return (
14 <AgentProvider
15 config={{
16 auth: { tokenFactory: () => fetch("/api/token").then((r) => r.text()) },
17 agent: "YOUR_AGENT_ID",
18 }}
19 >
20 <div data-dg-agent>
21 <Orb size={120} />
22 <AgentConversation />
23 <AgentTextInput />
24 <div>
25 <AgentStartButton />
26 <AgentMicrophoneButton />
27 <AgentSpeakerButton />
28 </div>
29 </div>
30 </AgentProvider>
31 );
32}

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

AgentStatus

Renders the current connection state as a text label. Updates automatically as the session connects, disconnects, or reconnects.

Connected

1<AgentStatus />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
labelsPartial<Record<string, string>>See belowOverride the display text for each state.

Default labels: "Not started", "Connecting...", "Connected", "Reconnecting...", "Disconnected".

1<AgentStatus
2 labels={{
3 idle: "Ready",
4 connecting: "Connecting...",
5 connected: "Live",
6 disconnected: "Offline",
7 }}
8/>

Data attributes: data-agent-status, data-state (current state value).

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.

1<AgentConversation />

Props:

PropTypeDefaultDescription
classNamestring—CSS class for the container.
itemClassNamestring—CSS class applied to each message.
renderMessage(entry: ConversationEntry) => ReactNode—Custom render function for messages.
emptyStateReactNode—Content shown when conversation is empty.
autoScrollbooleantrueScroll to latest message automatically.
1<AgentConversation
2 emptyState={<p>Say something to start the conversation.</p>}
3 renderMessage={(entry) => (
4 <div className={entry.role === "user" ? "user-msg" : "agent-msg"}>
5 {entry.content}
6 </div>
7 )}
8/>

Data attributes: data-agent-conversation on the container, data-role="user" or data-role="assistant" on each message.

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
1<Response>{markdownString}</Response>

Props:

PropTypeDefaultDescription
childrenstring—Markdown string to render.
classNamestring—Additional CSS class.

Data attributes: data-agent-response.

Input Components

AgentTextInput

Text input field for sending messages to the agent. Submits on Enter (Shift+Enter for newline).

1<AgentTextInput />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
placeholderstring"Type a message..."Input placeholder text.
disabledbooleanfalseDisable the input.
onSend(text: string) => void—Callback when a message is sent.
submitButtonReactNode—Custom send button element.

Data attributes: data-agent-text-input.

Control Components

AgentStartButton

Connect/disconnect toggle button. Reflects the current session state automatically.

1<AgentStartButton />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
startLabelReactNode"Start"Label when idle.
connectingLabelReactNode"Connecting..."Label while connecting.
stopLabelReactNode"Stop"Label when connected.
reconnectingLabelReactNode"Reconnecting..."Label while reconnecting.
onClick() => void—Optional click handler override.

Data attributes: data-agent-start-button, data-state (current state value).

AgentMicrophoneButton

Microphone mute/unmute toggle. Renders SVG mic icons by default.

1<AgentMicrophoneButton />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
activeLabelReactNodeMic iconContent when microphone is active.
mutedLabelReactNodeMic-off iconContent when muted.
disabledLabelReactNode—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

Speaker mute/unmute toggle. Renders SVG speaker icons by default.

1<AgentSpeakerButton />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
activeLabelReactNodeSpeaker iconContent when speaker is active.
mutedLabelReactNodeSpeaker-off iconContent when muted.
onClick() => void—Optional click handler override.

Data attributes: data-agent-speaker-button, data-state ("active" or "muted").

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.

1<VoiceButton />

Props:

PropTypeDefaultDescription
classNamestring—Additional CSS class.
labelsPartial<Record<VoiceButtonState, ReactNode>>See belowText 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:

1[data-voice-state="listening"] {
2 border-color: var(--dg-va-primary);
3}
4[data-voice-state="speaking"] {
5 background: var(--dg-va-primary);
6 animation: pulse 1.5s infinite;
7}

Data attributes: data-agent-voice-button, data-voice-state ("idle", "connecting", "listening", "speaking", "error").

Visualization Components

Orb

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
1<Orb size={200} />

Props:

PropTypeDefaultDescription
sizenumber200Diameter in pixels.
colors[string, string]Deepgram greensTwo 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).
inputVolumenumber—Direct mic volume value (0—1) for manual control.
outputVolumenumber—Direct output volume value (0—1) for manual control.
classNamestring—Additional CSS class.

Automatic mode (default inside AgentProvider):

1<Orb />

The orb reads getInputVolume() and getOutputVolume() every animation frame with zero re-renders.

Manual mode — push volume values directly:

1<Orb inputVolume={0.5} outputVolume={0.3} state="talking" />

Custom volume sources:

1<Orb
2 getInputVolume={myMicAnalyser}
3 getOutputVolume={myPlayerAnalyser}
4/>

Custom colors:

1<Orb colors={["#6366f1", "#ec4899"]} />

Data attributes: data-agent-orb, data-orb-state ("idle", "listening", "talking").

BarVisualizer

Real-time frequency bar visualization. Renders vertical bars on a canvas that react to audio input or output.

1<BarVisualizer source="output" barCount={16} />

Props:

PropTypeDefaultDescription
source"input" | "output""output"Microphone or agent audio.
barCountnumber16Number of frequency bars.
classNamestring—Additional CSS class.

Data attributes: data-agent-bar-visualizer.

LiveWaveform

Smooth oscillating waveform driven by a volume source. Blends two sine waves for an organic feel.

1import { useAgentMicrophone } from "@deepgram/ui";
2
3function MyWaveform() {
4 const { getInputVolume } = useAgentMicrophone();
5 return <LiveWaveform getVolume={getInputVolume} />;
6}

Props:

PropTypeDefaultDescription
getVolume(() => number) | (() => number)[]—Volume source(s) returning 0—1. When multiple are provided, the max value is used per frame.
activebooleantrueWhether the waveform animates. Renders a flat line when false.
colorstring--dg-va-primaryLine color.
lineWidthnumber2Stroke width in pixels.
classNamestring—Additional CSS class.

Data attributes: data-agent-live-waveform.

Utility Components

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.

1const [deviceId, setDeviceId] = useState("");
2<MicSelector value={deviceId} onValueChange={setDeviceId} />

Props:

PropTypeDefaultDescription
valuestring—Currently selected device ID (controlled).
onValueChange(deviceId: string) => void—Callback when the user selects a device.
classNamestring—Additional CSS class.
disabledbooleanfalseDisable the selector.

Data attributes: data-agent-mic-selector.

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.

1<div data-dg-agent>
2 <AgentConversation />
3 <AgentTextInput />
4</div>

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.

1[data-dg-agent] {
2 /* Brand */
3 --color-primary: #13ef93;
4 --color-primary-foreground: #000000;
5
6 /* Surfaces */
7 --color-background: #ffffff;
8 --color-foreground: #111827;
9 --color-card: #f3f4f6;
10 --color-card-foreground: #111827;
11 --color-popover: #ffffff;
12 --color-popover-foreground: #111827;
13 --color-muted: #f3f4f6;
14 --color-muted-foreground: #6b7280;
15 --color-accent: #f9fafb;
16 --color-accent-foreground: #111827;
17 --color-input: #f3f4f6;
18 --color-border: rgba(0, 0, 0, 0.1);
19 --color-ring: #13ef93;
20 --color-secondary: #f3f4f6;
21 --color-secondary-foreground: #111827;
22 --color-destructive: #dc2626;
23 --color-destructive-foreground:#ffffff;
24
25 /* Typography & shape */
26 --font-sans: system-ui, -apple-system, sans-serif;
27 --radius: 1rem;
28
29 /* Widget layout (panel + FAB sizing) */
30 --dg-va-panel-w: min(440px, 100vw);
31 --dg-va-fab-size: 56px;
32 --dg-va-padding: 16px;
33
34 /* Derived from --color-primary by default — override only if you need a different relationship */
35 --primary-hover: color-mix(in srgb, var(--color-primary) 85%, #000);
36 --primary-active: color-mix(in srgb, var(--color-primary) 70%, #000);
37 --msg-user-bg: color-mix(in srgb, var(--color-primary) 12%, transparent);
38 --msg-user-border: color-mix(in srgb, var(--color-primary) 30%, transparent);
39}

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.

1<div data-dg-agent data-dg-scheme="dark">
2 {/* Always renders in dark mode */}
3</div>
BehaviourSelector
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

A teal-on-midnight palette called Aurora, applied entirely through CSS custom properties on the host element. Same components, completely different feel.

1[data-dg-agent].aurora-theme {
2 /* Brand */
3 --color-primary: #5eead4;
4 --color-primary-foreground: #042f2e;
5 --color-ring: #5eead4;
6
7 /* Surfaces */
8 --color-background: #0a0e1a;
9 --color-foreground: #e6edf6;
10 --color-card: #121829;
11 --color-card-foreground: #e6edf6;
12 --color-popover: #121829;
13 --color-popover-foreground: #e6edf6;
14 --color-muted: #1a2236;
15 --color-muted-foreground: #94a3b8;
16 --color-accent: #182238;
17 --color-accent-foreground: #5eead4;
18 --color-input: #0d1322;
19 --color-border: rgba(94, 234, 212, 0.14);
20 --color-secondary: #1a2236;
21 --color-secondary-foreground: #5eead4;
22
23 /* Derived (override the color-mix defaults for a softer glow) */
24 --primary-hover: #2dd4bf;
25 --primary-active: #14b8a6;
26 --msg-user-bg: rgba(94, 234, 212, 0.10);
27 --msg-user-border: rgba(94, 234, 212, 0.28);
28
29 /* Slightly tighter corners than the default 1rem */
30 --radius: 14px;
31}

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

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.

1/* Target the conversation container */
2[data-agent-conversation] {
3 max-height: 400px;
4}
5
6/* Target user messages */
7[data-agent-conversation] [data-role="user"] {
8 text-align: right;
9}
10
11/* Target agent messages */
12[data-agent-conversation] [data-role="assistant"] {
13 font-style: italic;
14}
15
16/* Target the text input */
17[data-agent-text-input] {
18 font-size: 16px;
19}
20
21/* Target the orb by state */
22[data-agent-orb][data-orb-state="talking"] {
23 filter: brightness(1.2);
24}

Data Attribute Reference

ComponentAttributeValues
Containerdata-dg-agent—
Color schemedata-dg-scheme"light", "dark"
AgentStatusdata-agent-status, data-state"idle", "connecting", "connected", "reconnecting", "disconnected"
AgentConversationdata-agent-conversation—
Messagesdata-role"user", "assistant"
AgentTextInputdata-agent-text-input—
AgentStartButtondata-agent-start-button, data-state"idle", "connecting", "connected", "reconnecting", "disconnected"
AgentMicrophoneButtondata-agent-mic-button, data-state"active", "muted", "inactive", "disabled"
AgentSpeakerButtondata-agent-speaker-button, data-state"active", "muted"
VoiceButtondata-agent-voice-button, data-voice-state"idle", "connecting", "listening", "speaking", "error"
Orbdata-agent-orb, data-orb-state"idle", "listening", "talking"
BarVisualizerdata-agent-bar-visualizer—
LiveWaveformdata-agent-live-waveform—
MicSelectordata-agent-mic-selector—
Responsedata-agent-response—