/**
* VoiceStatusIndicator Component
*
* Reusable visual indicator for voice mode states with icons, animations,
* and optional status text labels.
*
* @example
* ```tsx
* // Basic usage - icon only
*
*
* // With label
*
*
* // Different size
*
* ```
*/
import React from 'react';
import type { BrowserVoiceStatus } from '@/hooks/useBrowserVoice';
import { useI18n } from '@/lib/i18n';
import { Icon } from "@/components/icon/Icon";
import type { IconName } from "@/components/icon/icons";
export interface VoiceStatusIndicatorProps {
/** Current voice status */
status: BrowserVoiceStatus;
/** Show text label next to icon */
showLabel?: boolean;
/** Size of the indicator */
size?: 'sm' | 'md' | 'lg';
/** Optional className for styling */
className?: string;
/** Whether conversation mode is active (shows indicator dot when idle) */
conversationMode?: boolean;
}
const sizeClasses = {
sm: {
icon: 'w-4 h-4',
container: 'gap-1.5',
},
md: {
icon: 'w-5 h-5',
container: 'gap-2',
},
lg: {
icon: 'w-6 h-6',
container: 'gap-2.5',
},
};
const statusConfig: Record<
BrowserVoiceStatus,
{
icon: IconName;
color: string;
labelKey:
| 'voice.status.idle'
| 'voice.status.listening'
| 'voice.status.processing'
| 'voice.status.speaking'
| 'voice.status.error';
animation?: string;
}
> = {
idle: {
icon: "mic-off",
color: 'text-muted-foreground',
labelKey: 'voice.status.idle',
},
listening: {
icon: "mic",
color: 'text-primary',
labelKey: 'voice.status.listening',
animation: 'animate-pulse',
},
processing: {
icon: "loader-4",
color: 'text-primary',
labelKey: 'voice.status.processing',
animation: 'animate-spin',
},
speaking: {
icon: "volume-up",
color: 'text-green-500',
labelKey: 'voice.status.speaking',
},
error: {
icon: "alert",
color: 'text-destructive',
labelKey: 'voice.status.error',
},
};
/**
* VoiceStatusIndicator - Visual indicator for voice mode states
*/
export function VoiceStatusIndicator({
status,
showLabel = false,
size = 'md',
className = '',
conversationMode = false,
}: VoiceStatusIndicatorProps) {
const { t } = useI18n();
const config = statusConfig[status];
const statusIconName = config.icon;
const sizeClass = sizeClasses[size];
const containerClass = showLabel ? sizeClass.container : '';
return (
{/* Conversation mode indicator dot - only when idle and conversation mode is on */}
{conversationMode && status === 'idle' && (
)}
{showLabel && (
{t(config.labelKey)}
)}
);
}
export default VoiceStatusIndicator;