Voice UI

VoiceOrb and PhoneMic — animated voice state indicators and the full-screen phone-style microphone interface.

Overview

Luna has two voice UI components. VoiceOrb is a compact animated indicator that can be embedded anywhere. PhoneMic is the full-screen voice interaction view shown when the user activates phone mode.

ComponentFileUse case
VoiceOrbcomponents/Voice/VoiceOrb.tsxEmbedded in ChatWindow; also used in the dashboard header.
PhoneMiccomponents/Voice/PhoneMic.tsxFull-screen voice interface triggered from the sidebar.

VoiceOrb

An animated dual-ring orb that reflects the current voice pipeline state. Outer and inner rings rotate at speeds keyed to the state; a pulse scale animation gives visual feedback during speaking.

props
interface VoiceOrbProps {
  size?:      number      // diameter in px — default 36
  showLabel?: boolean     // show status subtitle below the orb
  onToggle?:  () => void  // override the default voice-toggle action
}
usage
import { VoiceOrb } from './components/Voice/VoiceOrb'

// Compact mode in the chat header
<VoiceOrb size={28} />

// Larger with subtitle label
<VoiceOrb size={56} showLabel />

State sync

VoiceOrb opens a persistent SSE connection to GET /api/voice/eventsand updates its state whenever the backend sends a voice_state event. It polls GET /api/voice/state on mount to set the initial state.

Voice states

StateLabelVisual
idlevoice offStatic — no rotation, no pulse.
listeningsleepingStatic — wake-word detection mode.
followuplistening...Slow outer rotation, gentle pulse.
activelistening...Fast rotation, strong pulse.
processingthinking...Medium rotation, rhythmic pulse.
speakingspeaking...Rapid rotation, large pulse (scale 1.22).

The backend controls state transitions. The frontend only reflects what it receives via SSE — it never sets voice state directly.

PhoneMic

A full-screen voice interaction view styled like a phone call UI. Shows a large VoiceOrb, the current transcript, Luna's response, and controls to end the call. Activated from the sidebar by switching to the voice view.

Key interactions:

  • Tap the orb to toggle listening on/off.
  • Luna's streamed text response appears below the orb in real-time.
  • A waveform animation plays during speech.
  • End-call button returns to the chat view and stops the voice pipeline.
usage
import { PhoneMic } from './components/Voice/PhoneMic'

// Shown when activeView === 'voice' in the store
{activeView === 'voice' && <PhoneMic />}

Voice endpoints

EndpointMethodDescription
/api/voice/stateGETCurrent voice state string.
/api/voice/eventsGET (SSE)State change stream — sends voice_state events.
/api/voice/togglePOSTToggle voice pipeline on/off.
/api/voice/streamPOSTSubmit audio data for processing.