VoiceOrbs

Canvas · zero deps

Siri Wave Line

Overlapping fluorescent sine waves that flatten at rest and surge with the voice.

Rendering cost: redraws every frame, moderate cpu.

Preview

Idle

The demo cycles the five states. The mic makes the orb react to your voice while listening or speaking.

State

Customize

Color · Default
Size · 168px
Speed · 1×

A dot marks each default.

Get the code

The prompt bundles every file plus your current settings, set up for Generic.

Zero dependencies: copy the files and it just works.

Props

Every orb implements the same contract, so they are interchangeable: swap the import and keep the props.

state
'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error' | 'disabled'
Default: 'idle'
Assistant lifecycle state driving the animation. error and disabled are optional extensions.
size
number
Default: 168 (184 for Nebula Orb)
Diameter of the orb in pixels, also exposed as the --orb-size CSS variable.
speed
number
Default: 1
Animation speed multiplier, also exposed as the --orb-speed CSS variable.
colorFrom
string
Default: per-orb gradient start
Gradient start color (any CSS color), exposed as --orb-color-from.
colorTo
string
Default: per-orb gradient end
Gradient end color (any CSS color), exposed as --orb-color-to.
levelRef
RefObject<number>
Default: undefined
Live audio amplitude in 0..1 read every frame without re-render; a negative value falls back to the procedural animation.
label
string
Default: 'Assistant orb'
Accessible name announced by screen readers via aria-label.
className
string
Default: undefined
Extra class names merged onto the root element.
ref
Ref<HTMLDivElement>
Default: undefined
React 19 ref to the root element for measuring, animating or scrolling into view.

Wire it to audio

Drive state from your assistant lifecycle and pass a levelRef with the live amplitude. The bundled useAudioLevel hook opens the microphone and writes a 0..1 level into the ref every frame without re-rendering; while the value is negative the orb falls back to its procedural animation.

'use client';
import { useState } from 'react';
import type { OrbState } from '@/registry/lib/orb-state';
import { useAudioLevel } from '@/registry/lib/use-audio-level';
import { SiriWaveLine } from '@/registry/orbe/siri-wave-line/siri-wave-line';
export const Assistant = () => {
const [state, setState] = useState<OrbState>('idle');
const { levelRef } = useAudioLevel(state === 'listening');
return <SiriWaveLine state={state} levelRef={levelRef} />;
};

Using Vapi, ElevenLabs, LiveKit or OpenAI Realtime? The recipes map each provider to state and levelRef.