"use client"; import { useEffect, useMemo, useRef, useState, type KeyboardEvent } from "react"; import { Send, Mic, MicOff, Sparkles } from "lucide-react"; import { t, type SupportedLanguage } from "@/lib/i18n"; interface HeroInputProps { language: SupportedLanguage; onSend: (value: string) => void; onStartVoice?: () => void; onStopVoice?: () => void; voiceEnabled?: boolean; isListening?: boolean; /** Dynamic suggestion chips rendered under the input (empty = hide). */ suggestions?: string[]; /** Variant — the home hero uses a larger, more prominent size. */ size?: "default" | "hero"; /** Autofocus on mount (chat view). */ autoFocus?: boolean; /** * Freeze the rotating empathetic placeholders and show a single * neutral one ("Type your health question…") instead. Use this once * the conversation has started — otherwise the placeholder rotation * appears directly underneath the "Analyzing symptoms…" typing * indicator and reads like a canned bot reply. */ staticPlaceholder?: boolean; } /** * The single most important element of the app: the input. * - Large, generous rounded container with a soft brand glow on focus. * - Rotating empathetic placeholders so the field never feels empty. * - Multi-line textarea that auto-grows up to 5 rows. * - Inline primary send button + optional voice mic. * - Suggestion chips appear below for zero-friction entry. */ export function HeroInput({ language, onSend, onStartVoice, onStopVoice, voiceEnabled = true, isListening = false, suggestions = [], size = "default", autoFocus = false, staticPlaceholder = false, }: HeroInputProps) { const [value, setValue] = useState(""); const taRef = useRef(null); // Rotating empathetic placeholders for the empty-home / welcome screen. const rotating = useMemo( () => [ t("ask_placeholder_rotate_1", language), t("ask_placeholder_rotate_2", language), t("ask_placeholder_rotate_3", language), t("ask_placeholder_rotate_4", language), t("ask_placeholder_rotate_5", language), ], [language], ); const [rotIdx, setRotIdx] = useState(0); useEffect(() => { if (staticPlaceholder) return; // chat-mode: keep one neutral hint if (value) return; // freeze rotation while the user is typing const id = setInterval(() => setRotIdx((i) => (i + 1) % rotating.length), 3200); return () => clearInterval(id); }, [value, rotating.length, staticPlaceholder]); // Once the conversation has started, switch to a single neutral hint // so the textarea below the typing indicator never reads like a bot // suggestion. const placeholderText = staticPlaceholder ? t("ask_placeholder", language) : rotating[rotIdx]; // Auto-grow textarea. useEffect(() => { const el = taRef.current; if (!el) return; el.style.height = "0px"; const max = size === "hero" ? 180 : 160; el.style.height = `${Math.min(el.scrollHeight, max)}px`; }, [value, size]); useEffect(() => { if (autoFocus) taRef.current?.focus(); }, [autoFocus]); const handleKey = (e: KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); submit(); } }; const submit = () => { const v = value.trim(); if (!v) return; onSend(v); setValue(""); }; const isHero = size === "hero"; return (
{/* The glowing container */}
{/* Soft gradient halo behind the card */}