Xzero UI
Pro library

Voice orbPro

A voice mode orb that listens, thinks, and speaks, with a live transcript and call controls.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/voice-orb
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/voice-orb

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { useEffect, useState } from "react";
import { VoiceControls, VoiceOrb, VoiceTranscript, useMicLevel } from "@/components/xzero/voice-orb/voice-orb";
import type { VoiceOrbState } from "@/components/xzero/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

VoiceOrb

A luminous fluid sphere in the accent colour, drawn with WebGL, that morphs between idle, listening, thinking, and speaking and reacts to live audio levels. Idle breathes, listening ripples outward with the microphone, thinking orbits a band of light around its rim, and speaking brightens with the voice. Pauses offscreen, falls back to a canvas gradient without WebGL, and draws still frames under reduced motion.

PropTypeDefaultDescription
state (required)"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.
mutedbooleanfalseCalms and desaturates the orb while listening and ignores the input level.
sizenumber208Rendered width and height in px. The sphere fills about 60% of it; the rest holds its light and ripples. Colours follow --accent, or --voice-orb-tint and --voice-orb-tint-2 on any ancestor.
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.

PropTypeDefaultDescription
enabled (required)boolean–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.

PropTypeDefaultDescription
text (required)string–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.

PropTypeDefaultDescription
active (required)boolean–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.

Keyboard interactions

KeysAction
Enter / SpaceStarts the session, toggles mute, or ends the call from the focused control.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in audio and video

Guidance for AI tools

Voice orb: A voice mode orb that listens, thinks, and speaks, with a live transcript and call controls. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components