diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx index 9df3af2..d5e65de 100644 --- a/src/components/Toast.tsx +++ b/src/components/Toast.tsx @@ -42,10 +42,8 @@ export const Toast: React.FC = ({ id, message, type, details, onClos }; const handleMouseLeave = () => { - // Set a timeout to mark as not hovered after 1 second - hoverTimeoutRef.current = setTimeout(() => { - onHoverChange?.(false); - }, 1000); + // Immediately mark as not hovered + onHoverChange?.(false); }; const handleClose = () => { diff --git a/src/components/ToastContext.tsx b/src/components/ToastContext.tsx index ed495b9..93c07ae 100644 --- a/src/components/ToastContext.tsx +++ b/src/components/ToastContext.tsx @@ -50,6 +50,11 @@ export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ childre }; const removeToast = (id: string) => { + // Clear any existing timeout for this toast + if (hoverTimeouts.current[id]) { + clearTimeout(hoverTimeouts.current[id]); + delete hoverTimeouts.current[id]; + } dispatch({ type: 'REMOVE_TOAST', payload: id }); }; @@ -59,36 +64,48 @@ export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ childre // Auto remove toasts after duration, but respect hover state useEffect(() => { - const timers = toasts.map(toast => { + // Create a copy of current timeouts to track which ones we need to clear + const currentTimeouts = { ...hoverTimeouts.current }; + + toasts.forEach(toast => { // Clear any existing timeout for this toast - if (hoverTimeouts.current[toast.id]) { - clearTimeout(hoverTimeouts.current[toast.id]); - delete hoverTimeouts.current[toast.id]; + if (currentTimeouts[toast.id]) { + clearTimeout(currentTimeouts[toast.id]); + delete currentTimeouts[toast.id]; } // If toast is hovered, don't set a timer if (toast.hovered) { - return null; + return; } // If duration is 0, it's persistent if (toast.duration === 0) { - return null; + return; } // Set timeout to remove toast const timeout = setTimeout(() => { removeToast(toast.id); }, toast.duration); - - return { id: toast.id, timeout }; + + hoverTimeouts.current[toast.id] = timeout; }); - // Cleanup function + // Clear any remaining timeouts for toasts that no longer exist + Object.entries(currentTimeouts).forEach(([id, timeout]) => { + clearTimeout(timeout); + delete hoverTimeouts.current[id]; + }); + + // Cleanup function for when component unmounts or toasts change return () => { - timers.forEach(timer => { - if (timer) clearTimeout(timer.timeout); + // Clear all active timeouts + Object.values(hoverTimeouts.current).forEach(timeout => { + clearTimeout(timeout); }); + // Reset the timeouts object + hoverTimeouts.current = {}; }; }, [toasts]);