Voice orbPro
A voice mode orb that listens, thinks, and speaks, with a live transcript and call controls.
Ready
Tap the orb and ask about your calendar.
Uses your microphone level only, if you allow it.
- A voice mode for an assistant where the user needs to see whether it is listening, thinking, or speaking.
- Hands-free or call-like flows that need start, mute, a running clock, and end in one compact control.
- Live captions under a speaking agent, via VoiceTranscript.
- Use voice-recorder when the user records a clip to send or save.
- Use chat-thread with text-stream for typed chat where no audio is involved.
- Use progress or skeleton for a generic loading state; the orb implies a voice session.
Installation
Pro source and install commands unlock with a Pro plan.
import { useEffect, useState } from "react";import { VoiceControls, VoiceOrb, VoiceTranscript, useMicLevel } from "@/registry/components/voice-orb/voice-orb";import type { VoiceOrbState } from "@/registry/components/voice-orb/voice-orb"; export function VoiceMode() { const [active, setActive] = useState(false); const [muted, setMuted] = useState(false); const [state, setState] = useState<VoiceOrbState>("idle"); const [elapsed, setElapsed] = useState(0); const mic = useMicLevel(active && !muted); useEffect(() => { if (!active) return; const timer = window.setInterval(() => setElapsed(value => value + 1), 1000); return () => window.clearInterval(timer); }, [active]); return ( <div style={{ display: "grid", justifyItems: "center", gap: 24 }}> <VoiceOrb state={state} inputLevel={mic.level} muted={muted} /> <VoiceTranscript text="How can I help?" turn={1} complete /> <VoiceControls active={active} muted={muted} elapsed={elapsed} onStart={() => { setActive(true); setState("listening"); }} onMuteChange={setMuted} onEnd={() => { setActive(false); setState("idle"); setElapsed(0); }} /> </div> );}API reference
4 parts. The first is the root.
VoiceOrb
A canvas orb that morphs between idle, listening, thinking, and speaking, driven by live audio levels.
stateRequired"idle" | "listening" | "thinking" | "speaking"–Current voice state. Every shape parameter springs toward the new state, so changes blend mid-motion.inputLevelMotionValue<number>–Microphone level from 0 to 1, read every frame while listening, such as useMicLevel().level. Simulated when omitted.outputLevelMotionValue<number>–Voice level from 0 to 1 while speaking. A deterministic speech envelope is used when omitted.mutedbooleanfalseStills the listening ripple and ignores the input level.sizenumber208Rendered width and height in px.labelstring–Accessible description. Defaults to a sentence about the state, or "Muted" while listening muted.classNamestring–Extra class on the canvas.useMicLevel
Hook that reads the microphone level as a motion value while enabled. Returns { level, source }. Falls back to a simulated voice when the microphone is denied or missing. Nothing is recorded.
enabledRequiredboolean–Asks for the microphone when it turns true and stops every track when it turns false.VoiceTranscript
One line of live transcript. Words settle in from a soft blur, two lines are kept, and a new turn crossfades in.
textRequiredstring–Transcript text so far. Words are split on whitespace.turnstring | number0Change it when a new turn begins so the old line crossfades out.speaker"user" | "assistant" | "system""assistant"Assistant reads in the foreground color, the person in secondary, system smaller and muted.completebooleanfalseSet when the turn is finished to announce it to screen readers.classNamestring–Extra class on the wrapper.VoiceControls
Call controls in one pill: a start button at rest, and mute, a running clock, and end once the session is live.
activeRequiredboolean–Whether a session is live.mutedbooleanfalsePressed state of the mute button.elapsednumber0Seconds since the session began, shown as m:ss with tabular numerals.onStart() => void–Called by the start button.onMuteChange(muted: boolean) => void–Called with the next muted value.onEnd() => void–Called by the end button.startLabelReactNode"Start voice chat"Content of the start button.classNamestring–Extra class on the pill.- EnterorSpace
- Starts the session, toggles mute, or ends the call from the focused control.
- The orb is a canvas with role="img" and an aria-label that follows the state (Listening, Thinking, Speaking, Muted).
- VoiceTranscript hides the animated words and announces only the completed turn through a polite live region.
- The mute button uses aria-pressed and switches its label between Mute and Unmute microphone; the clock is role="timer" with a spoken minutes and seconds label.
- Focus moves to mute when a session starts and back to start when it ends, so keyboard users never lose their place.
- Nine shape parameters (breath, wobble, swirl, tint, ring, and more) follow the state on a hand-rolled spring each frame, so state changes interrupt cleanly.
- Listening swells with the input level and draws two ripple rings; speaking pulses with the output level; thinking contracts into a slow swirl.
- The controls pill springs its width to fit while the start button and live controls crossfade with a small scale and blur.
- Reduced motion stops the rAF loop and draws one still frame per state; transcript and controls fall back to short opacity fades.
- The orb has a fixed pixel size from the size prop; pick a smaller value such as 144 on narrow screens.
- The transcript caps at 30rem wide and two lines tall, with a top fade mask so older lines lift away.
- Hover styles on the controls apply only on hover-capable fine pointers; buttons are 40px round for touch.
- One requestAnimationFrame loop per orb draws a 96-point blob and gradients on a canvas capped at 2x device pixel ratio.
- An IntersectionObserver and visibilitychange stop the loop while offscreen or in a background tab; a MutationObserver rereads theme colors.
- useMicLevel runs its own rAF loop over a 1024-sample AnalyserNode and closes the AudioContext when disabled.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for a voice assistant surface. Feed useMicLevel().level to inputLevel while listening and your TTS analyser level to outputLevel while speaking.
- The orb only visualises; map your session events to the four states yourself (idle, listening, thinking, speaking).
- The body uses --foreground; the inner light uses the brand gradient (--arc-gradient-from and --arc-gradient-to, falling back to --accent). Set --voice-orb-tint and optionally --voice-orb-tint-2 on a parent to recolor it; with only --voice-orb-tint set, both lights use it.
- For recording and saving audio clips use voice-recorder instead; this component never records.
The full library index for assistants is at /llms.txt.