Spaces:
Running
Running
| import { X } from "lucide-react"; | |
| import { motion } from "motion/react"; | |
| import type { VoiceState } from "../../../hooks/useVoiceSession"; | |
| interface VoiceStatusBarProps { | |
| voiceState: VoiceState; | |
| onStop: () => void; | |
| } | |
| const STATE_LABELS: Record<VoiceState, string> = { | |
| IDLE: "", | |
| CONNECTING: "Connecting...", | |
| LISTENING: "Listening...", | |
| PROCESSING: "Processing...", | |
| SPEAKING: "Agent is speaking", | |
| ERROR: "Connection error", | |
| }; | |
| const STATE_COLORS: Record<VoiceState, string> = { | |
| IDLE: "", | |
| CONNECTING: "bg-brand-green/10 text-brand-green border-brand-green/20", | |
| LISTENING: "bg-brand-green/10 text-brand-green border-brand-green/20", | |
| PROCESSING: "bg-brand-amber/10 text-brand-amber border-brand-amber/20", | |
| SPEAKING: "bg-brand-cyan/10 text-brand-cyan border-brand-cyan/20", | |
| ERROR: "bg-red-50 text-red-500 border-red-200", | |
| }; | |
| export default function VoiceStatusBar({ voiceState, onStop }: VoiceStatusBarProps) { | |
| return ( | |
| <motion.div | |
| initial={{ opacity: 0, y: 6 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: 6 }} | |
| transition={{ duration: 0.2 }} | |
| className={`flex items-center justify-between gap-2 px-3 py-1.5 rounded-xl border text-xs font-medium ${STATE_COLORS[voiceState]}`} | |
| > | |
| <div className="flex items-center gap-2"> | |
| <span className="relative flex h-2 w-2"> | |
| <span | |
| className={`animate-ping absolute inline-flex h-full w-full rounded-full opacity-75 ${ | |
| voiceState === "LISTENING" | |
| ? "bg-brand-green" | |
| : voiceState === "SPEAKING" | |
| ? "bg-brand-cyan" | |
| : voiceState === "PROCESSING" | |
| ? "bg-brand-amber" | |
| : "bg-neutral-400" | |
| }`} | |
| /> | |
| <span | |
| className={`relative inline-flex rounded-full h-2 w-2 ${ | |
| voiceState === "LISTENING" | |
| ? "bg-brand-green" | |
| : voiceState === "SPEAKING" | |
| ? "bg-brand-cyan" | |
| : voiceState === "PROCESSING" | |
| ? "bg-brand-amber" | |
| : "bg-neutral-400" | |
| }`} | |
| /> | |
| </span> | |
| <span>{STATE_LABELS[voiceState]}</span> | |
| </div> | |
| <button | |
| onClick={onStop} | |
| className="p-0.5 rounded hover:bg-black/10 transition-colors" | |
| aria-label="End voice session" | |
| > | |
| <X className="h-3.5 w-3.5" /> | |
| </button> | |
| </motion.div> | |
| ); | |
| } | |