"use client"; import { useEffect, useRef, useState } from "react"; type ToastState = "idle" | "sending" | "ok" | "error"; type Props = { state: ToastState; successTitle?: string; successMessage?: string; onDismiss?: () => void; }; /** * Inline toast that appears below the submit button. * - Slides up + fades in when visible * - Auto-dismisses after 6 s on success * - Shows a close button for manual dismiss */ export default function SubmitToast({ state, successTitle = "Submitted successfully", successMessage = "Your submission has been received.", onDismiss, }: Props) { const [visible, setVisible] = useState(false); const [mounted, setMounted] = useState(false); const timerRef = useRef | null>(null); const isActive = state === "ok" || state === "error"; // Mount → trigger CSS enter transition useEffect(() => { if (isActive) { setMounted(true); // Tiny delay so the browser registers the initial state before animating requestAnimationFrame(() => { requestAnimationFrame(() => setVisible(true)); }); // Auto-dismiss success after 6 s if (state === "ok") { timerRef.current = setTimeout(() => handleDismiss(), 6000); } } else { // Slide out then unmount setVisible(false); timerRef.current = setTimeout(() => setMounted(false), 400); } return () => { if (timerRef.current) clearTimeout(timerRef.current); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [isActive, state]); const handleDismiss = () => { if (timerRef.current) clearTimeout(timerRef.current); setVisible(false); setTimeout(() => { setMounted(false); onDismiss?.(); }, 400); }; if (!mounted) return null; const isSuccess = state === "ok"; return (
{/* Icon */} {isSuccess ? "check_circle" : "error"} {/* Text */}

{isSuccess ? successTitle : "Submission failed"}

{isSuccess ? successMessage : "Please check your connection and try again."}

{/* Close button */}
); }