Nebula Orb
3D sphere with simplex-noise displacement and fresnel. The “voice mode”.
Idle
State
Speed
Size
Color
From
To
WebGL (R3F + GLSL)gpu
WebGL (R3F + GLSL)
3D sphere with simplex-noise displacement and fresnel. The “voice mode”.
3D sphere with simplex-noise displacement and fresnel. The “voice mode”.
Every orb implements the same contract, so they are interchangeable: swap the import and keep the props.
| Prop | Type | Default | Description |
|---|---|---|---|
| state | 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error' | 'disabled' | 'idle' | Assistant lifecycle state driving the animation. error and disabled are optional extensions. |
| size | number | 160-184 (per orb) | Diameter of the orb in pixels, also exposed as the --orb-size CSS variable. |
| speed | number | 1 | Animation speed multiplier, also exposed as the --orb-speed CSS variable. |
| colorFrom | string | per-orb gradient start | Gradient start color (any CSS color), exposed as --orb-color-from. |
| colorTo | string | per-orb gradient end | Gradient end color (any CSS color), exposed as --orb-color-to. |
| levelRef | RefObject<number> | undefined | Live audio amplitude in 0..1 read every frame without re-render; a negative value falls back to the procedural animation. |
| label | string | 'Assistant orb' | Accessible name announced by screen readers via aria-label. |
| className | string | undefined | Extra class names merged onto the root element. |
| ref | Ref<HTMLDivElement> | undefined | React 19 ref to the root element for measuring, animating or scrolling into view. |
Copy the component files from the playground above, then render the orb with its default configuration. First install three @react-three/fiber.
import { NebulaOrb } from '@/registry/orbe/nebula-orb/nebula-orb';
export const Assistant = () => (
<NebulaOrb
state="idle"
size={184}
speed={1}
colorFrom="#8b5cf6"
colorTo="#22d3ee"
/>
);
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 { NebulaOrb } from '@/registry/orbe/nebula-orb/nebula-orb';
export const Assistant = () => {
const [state, setState] = useState<OrbState>('idle');
const { levelRef } = useAudioLevel(state === 'listening');
return <NebulaOrb state={state} levelRef={levelRef} />;
};