diff --git a/frontend/src/components/ChatInputBar.vue b/frontend/src/components/ChatInputBar.vue index 3527969..8779219 100644 --- a/frontend/src/components/ChatInputBar.vue +++ b/frontend/src/components/ChatInputBar.vue @@ -114,15 +114,17 @@ const transcribingVoice = ref(false) const recorder = useVoiceRecorder() const silenceDetector = useSilenceDetector() -// Live mic pulse. `silenceDetector.amplitude` is 0..1 RMS; we floor at 0.1 -// so the button still breathes on silence and cap the scale growth so loud -// input doesn't punch through the input bar. -const micStyle = computed(() => { - if (!recorder.recording.value) return {} - const pulse = 0.1 + Math.min(silenceDetector.amplitude.value, 1) * 0.9 +// Live mic halo. A solid red disc sits behind the mic button and scales +// with `silenceDetector.amplitude` (0..1 RMS, already amplified for +// visibility). The button itself stays put so the mic icon is always +// legible on top. 0.2 baseline breathes on silence; loud speech drives +// the disc out to ~2.6× the button size with a softer radial fade. +const micGlowStyle = computed(() => { + if (!recorder.recording.value) return { display: 'none' } + const pulse = 0.2 + Math.min(silenceDetector.amplitude.value, 1) * 0.8 return { - transform: `scale(${1 + pulse * 0.18})`, - boxShadow: `0 0 ${6 + pulse * 14}px ${2 + pulse * 4}px rgba(239, 68, 68, ${0.2 + pulse * 0.3})`, + transform: `translate(-50%, -50%) scale(${1 + pulse * 1.6})`, + opacity: String(0.45 + pulse * 0.4), } }) @@ -242,24 +244,25 @@ defineExpose({ focus, prefill }) class="input-textarea" > - - + +