> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developers.deepgram.com/docs/browser-agent-react-ui/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.deepgram.com/_mcp/server. # 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. > **Info** > > These components require an `AgentProvider` ancestor. See [React Hooks](/docs/browser-agent-react) for provider setup. For the core JavaScript SDK, see [JavaScript](/docs/browser-agent-javascript). ## Installation ```shell npm install @deepgram/ui ``` Import the stylesheet in your app's entry point: ```tsx import "@deepgram/ui/styles.css"; ``` > **Note** > > `@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: ```tsx import { AgentProvider, AgentConversation, AgentTextInput, AgentStartButton, AgentMicrophoneButton, AgentSpeakerButton, Orb, } from "@deepgram/ui"; import "@deepgram/ui/styles.css"; function App() { return ( fetch("/api/token").then((r) => r.text()) }, agent: "YOUR_AGENT_ID", }} >
); } ``` Replace `YOUR_AGENT_ID` with a [Reusable Agent Configuration](/docs/reusable-agent-configurations) UUID, or pass an inline agent config object instead. See [Agent Configuration](/docs/browser-agent-overview#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 ```tsx ``` **Props:** | Prop | Type | Default | Description | | ----------- | --------------------------------- | --------- | ----------------------------------------- | | `className` | `string` | — | Additional CSS class. | | `labels` | `Partial>` | See below | Override the display text for each state. | Default labels: `"Not started"`, `"Connecting..."`, `"Connected"`, `"Reconnecting..."`, `"Disconnected"`. ```tsx ``` **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. ```tsx ``` **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. | ```tsx Say something to start the conversation.

} renderMessage={(entry) => (
{entry.content}
)} /> ``` **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 ```tsx {markdownString} ``` **Props:** | Prop | Type | Default | Description | | ----------- | -------- | ------- | -------------------------- | | `children` | `string` | — | Markdown string to render. | | `className` | `string` | — | 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). Send ```tsx ``` **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 ### AgentStartButton Connect/disconnect toggle button. Reflects the current session state automatically. Start ```tsx ``` **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 Microphone mute/unmute toggle. Renders SVG mic icons by default. ```tsx ``` **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 Speaker mute/unmute toggle. Renders SVG speaker icons by default. ```tsx ``` **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 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. ```tsx ``` **Props:** | Prop | Type | Default | Description | | ----------- | ---------------------------------------------- | --------- | -------------------------------- | | `className` | `string` | — | Additional CSS class. | | `labels` | `Partial>` | 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: ```css [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 ### 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 ```tsx ``` **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`): ```tsx ``` The orb reads `getInputVolume()` and `getOutputVolume()` every animation frame with zero re-renders. **Manual mode** — push volume values directly: ```tsx ``` **Custom volume sources:** ```tsx ``` **Custom colors:** ```tsx ``` **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. ```tsx ``` **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 Smooth oscillating waveform driven by a volume source. Blends two sine waves for an organic feel. ```tsx import { useAgentMicrophone } from "@deepgram/ui"; function MyWaveform() { const { getInputVolume } = useAgentMicrophone(); return ; } ``` **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 ### 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. ```tsx const [deviceId, setDeviceId] = useState(""); ``` **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 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. ```tsx
``` ### 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. ```css [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 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`. ```tsx
{/* Always renders in dark mode */}
``` | 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 A teal-on-midnight palette called **Aurora**, applied entirely through CSS custom properties on the host element. Same components, completely different feel. ```css [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 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. ```css /* 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 | 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` | — | > Pre-built, themeable React components for voice agent interfaces — conversation views, audio-reactive visualizers, and control buttons.