Voice widgetPro
A floating call widget for websites. The launcher opens a small panel that asks for consent once, then runs the call with the orb, rolling captions, mute and End, and the full transcript a tap away. Minimize mid call and the launcher carries it.
On this page
ProA clinic site with the widget in the corner. Agree once and the call runs in the panel; minimize it and the launcher carries the call.
Installation
Usage
import { VoiceWidget } from "@/components/ui/chatcn/pro/voice-widget"
<VoiceWidget
agentName="Fernhill Vets"
state={voice.state}
segments={voice.segments}
inputLevel={mic.getLevel}
outputLevel={agent.getLevel}
startedAt={voice.startedAt}
onStart={voice.start}
onEnd={voice.end}
/>Drop it anywhere on a page: position="fixed" floats it in the corner, contained floats it inside its positioned parent. The consent step shows before the first call only; pass your own copy to consent, a privacyHref, or false to skip it. Below 480 px of host width the panel becomes a sheet across the bottom. Any orb with the voice orb's props fills the panel through orb.
Examples
States
ProConsent, ready, connecting, speaking, transcript, muted, blocked mic, dropped, ended, minimized and a pixel orb.
Props
| Prop | Type | Notes |
|---|---|---|
state | "idle" | "connecting" | "listening" | "thinking" | "speaking" | "interrupted" | "muted" | "reconnecting" | "error" | "ended" | The call |
segments | TranscriptSegment[] | Feeds the captions and the transcript |
inputLevel, outputLevel | number | () => number | A getter animates without re-rendering |
startedAt, endedAt | number | Epoch ms, for the timer |
agentName, agentDetail | string, ReactNode | Header, launcher and captions; a line under the orb before a call |
userLabel | string | Default "You" |
launcherLabel | string | Default "Talk to us" |
open, defaultOpen, onOpenChange | boolean | The panel |
consent | ReactNode | false | Shown once before the first call. Default a recording and transcription notice |
privacyHref | string | Adds a privacy policy link to the consent step |
consented, defaultConsented, onConsentedChange | boolean | Persist it so returning visitors skip the step |
view, defaultView, onViewChange | "call" | "transcript" | Orb and captions, or the full transcript |
muted, defaultMuted, onMutedChange | boolean | Controlled or uncontrolled |
onStart, onEnd, onReconnect | () => void | Call actions |
onInterrupt | () => void | Tap the orb while the agent speaks to cut it off |
onSendTranscript | () => void | Adds "Email transcript" after the call |
micError, onRetryMicrophone | ChatcnMicrophoneError | The body says how to fix it and offers Try again |
errorMessage | ReactNode | Shown when the call drops. Say how to fix it |
orb | ComponentType | Any orb with the voice orb's props. Default VoiceOrb |
side | "end" | "start" | The corner, logical. Default end |
position | "fixed" | "contained" | Default fixed |
Keyboard
| Key | Action |
|---|---|
Enter, Space on the launcher | Open the panel and move focus to its main action |
Escape | Minimize. The call keeps going and focus returns to the launcher |
M | Mute or unmute, while focus is in the panel and not in a text field |
Tab | Moves through the panel; the closed panel is inert |
Accessibility
- The panel is a non modal dialog named by the agent, so the page stays usable during a call. Closed, it is inert and invisible to assistive tech.
- The launcher has
aria-expandedand reads its visible text: "Talk to us", or "On call 1:12" mid call, with End as its own labelled button. - State changes are announced politely; the ticking timer never is. Captions do not announce, the transcript does, so lines are read once.
- Every error says how to fix it: a blocked microphone gives the exact place to allow it, a dropped call offers Reconnect and keeps the transcript.
Motion
- The panel opens from the launcher's corner: opacity, scale from 0.96 and 8 px of rise over 220 ms, out in 160 ms. Opened or closed from the keyboard, it is instant.
- Views change with a 180 ms rise and fade. The launcher's level bars follow the voice on the frame clock and rest under reduced motion, where the panel only fades.