VoiceOrbs

Pure CSS · zero deps

Edge Glow

Siri-style ambient frame: a masked conic-gradient glow that wraps your own content instead of sitting in the middle.

Edge Glow

Siri-style ambient frame: a masked conic-gradient glow that wraps your own content instead of sitting in the middle.

Idle
State
Speed
Size
Color
From
To
Pure CSScompositor onlyZero deps

Props

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

PropTypeDefaultDescription
state'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error' | 'disabled''idle'Assistant lifecycle state driving the animation. error and disabled are optional extensions.
sizenumber160-184 (per orb)Diameter of the orb in pixels, also exposed as the --orb-size CSS variable.
speednumber1Animation speed multiplier, also exposed as the --orb-speed CSS variable.
colorFromstringper-orb gradient startGradient start color (any CSS color), exposed as --orb-color-from.
colorTostringper-orb gradient endGradient end color (any CSS color), exposed as --orb-color-to.
levelRefRefObject<number>undefinedLive audio amplitude in 0..1 read every frame without re-render; a negative value falls back to the procedural animation.
labelstring'Assistant orb'Accessible name announced by screen readers via aria-label.
classNamestringundefinedExtra class names merged onto the root element.
refRef<HTMLDivElement>undefinedReact 19 ref to the root element for measuring, animating or scrolling into view.

Usage

Copy the component files from the playground above, then render the orb with its default configuration.

import { EdgeGlow } from '@/registry/orbe/edge-glow/edge-glow';

export const Assistant = () => (
  <EdgeGlow
    state="idle"
    size={168}
    speed={1}
    colorFrom="#f472b6"
    colorTo="#60a5fa"
  />
);

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 { EdgeGlow } from '@/registry/orbe/edge-glow/edge-glow';

export const Assistant = () => {
  const [state, setState] = useState<OrbState>('idle');
  const { levelRef } = useAudioLevel(state === 'listening');

  return <EdgeGlow state={state} levelRef={levelRef} />;
};