Skip to content
Kura UI

Agent Orb

beta

Glassy liquid sphere for voice agents, drawn in a shader: breathes when idle, reacts to mic and voice levels, swirls while thinking.

@kura-ui/react/agent-orbCopy page for agents.mdregistry.json

Idle orb

minimal
Voice agent idle

States, palettes and audio

Every state and preset, driven by a simulated speech analyser.

full
Speaking

All five states

idle, listening, thinking, speaking and error side by side.

state
Voice agent idle
idle
Listening
listening
Thinking
thinking
Speaking
speaking
Voice agent error
error

Voice session card

A scripted call with captions, ShimmerText while thinking and IconButton controls.

composition
Listening

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/agent-orb.json

Copies the source into components/kura/agent-orb with its dependencies (kura-theme, kura-merge-refs, kura-shader-color, shader-canvas, use-audio-analyser, use-reduced-motion, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • The central visual of a voice agent or call screen: idle, listening, thinking, speaking, error.
  • Showing that an assistant is hearing the user (mic level) or talking back (TTS level).
  • A 'talk to the agent' entry point inside a button or a card.
  • An ambient, branded presence for an AI assistant in an empty state.

Reach for something else when

  • Precise audio feedback such as a recording meter or waveform — use audio-waveform or voice-dictation.
  • Text chat 'thinking' feedback inside a message list — use thinking-indicator or shimmer-text.
  • A full-bleed background — use mesh-gradient or aurora.
  • More than one per view: the orb is the accent element; repeat it and it stops meaning anything.

Props

PropTypeDefaultDescription
state"idle" | "listening" | "thinking" | "speaking" | "error""idle"What the agent is doing. idle breathes slowly, listening ripples with the input level, thinking swirls, speaking pulses with the output level, error turns red and calms down.
colors"jade" | "ocean" | "amber" | "graphite" | readonly [string, string, string, string]"jade"A palette preset, or four CSS colours `[deep, mid, bright, glint]` (OKLCH, hex, `var(--token)`…). jade is the Kura signal colour.
analyserAudioAnalyser—From `useAudioAnalyser`. Its level drives the orb while listening or speaking. Read every frame on the GPU loop — no React re-renders.
inputLevelnumber—Microphone level 0–1 used while `listening`. Overrides `analyser`.
outputLevelnumber—Agent voice level 0–1 used while `speaking`. Overrides `analyser`.
labelstring—Accessible text for the state. Default: Voice agent idle / Listening / Thinking / Speaking / Voice agent error.
announcebooleantrueRender the label in a polite live region. Set false when several orbs are on screen or a parent already announces the state.
maxDprnumber2Device-pixel-ratio cap.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. AgentOrbSquare root (`aspect-square`); size it with a width class. `data-state` mirrors `state`.data-slot="agent-orb"
  2. ShaderCanvasThe WebGL sphere and its halo (aria-hidden). The sphere fills ~70% of the box.data-slot="agent-orb-canvas"
  3. FallbackCSS gradient sphere used when WebGL2 is unavailable; it still spins while thinking.data-slot="agent-orb-fallback"

Accessibility

  • Role: status
  • The canvas is decorative (aria-hidden). The state is exposed as visually hidden text in a role=status live region, announced politely when it changes.
  • Audio levels are never announced. Pass `label` to describe custom situations (e.g. “Muted”).
  • If the orb is inside a button, give the button its own aria-label and set `announce={false}` to avoid double announcements.
  • Reduced motion: No breathing, swirl, flow or audio reaction: a still frame per state. State changes cross-fade colour and brightness over ~0.4s, then rendering stops.

Notes for agents

  • Give it a width (`className="size-48"` or `w-full max-w-64`); it is square. The sphere fills ~70% so the halo has room — do not clip it with overflow-hidden.
  • For real audio: `const mic = useAudioAnalyser({ source: micStream })` for listening and a second analyser on the TTS <audio> element for speaking; switch `analyser` with the state. For demos use `useAudioAnalyser({ simulate: "speech" })`.
  • `inputLevel`/`outputLevel` are fine for levels you already have (e.g. from a WebRTC SDK) at ≤ 30 updates/s; the shader smooths them.
  • Changing `state` never restarts the animation: uniforms ease toward the new state, so you can flip states as fast as your agent emits events.
  • Only one orb per view should be animated; for lists of agents use a static avatar.