- Toast component now uses useRef to store onClose callback - Prevents timer from resetting on parent re-renders - Fixes issue where toasts wouldn't dismiss after adding items
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useRef } from 'react'
|
|
import { CheckCircle, XCircle, AlertCircle, X } from 'lucide-react'
|
|
|
|
export type ToastType = 'success' | 'error' | 'info'
|
|
|
|
interface ToastProps {
|
|
message: string
|
|
type: ToastType
|
|
onClose: () => void
|
|
duration?: number
|
|
}
|
|
|
|
export default function Toast({ message, type, onClose, duration = 3000 }: ToastProps) {
|
|
const onCloseRef = useRef(onClose)
|
|
|
|
// Keep the ref updated
|
|
useEffect(() => {
|
|
onCloseRef.current = onClose
|
|
}, [onClose])
|
|
|
|
useEffect(() => {
|
|
if (duration > 0) {
|
|
console.log(`[Toast] Setting timer for ${duration}ms`)
|
|
const timer = setTimeout(() => {
|
|
console.log('[Toast] Auto-dismissing')
|
|
onCloseRef.current()
|
|
}, duration)
|
|
return () => {
|
|
console.log('[Toast] Clearing timer')
|
|
clearTimeout(timer)
|
|
}
|
|
}
|
|
}, [duration])
|
|
|
|
const icons = {
|
|
success: <CheckCircle size={20} className="flex-shrink-0" />,
|
|
error: <XCircle size={20} className="flex-shrink-0" />,
|
|
info: <AlertCircle size={20} className="flex-shrink-0" />,
|
|
}
|
|
|
|
const styles = {
|
|
success: 'bg-green-50 border-green-200 text-green-800',
|
|
error: 'bg-red-50 border-red-200 text-red-800',
|
|
info: 'bg-blue-50 border-blue-200 text-blue-800',
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`flex items-center gap-3 px-4 py-3 rounded-lg border shadow-lg ${styles[type]} animate-slide-in-right`}
|
|
role="alert"
|
|
>
|
|
{icons[type]}
|
|
<p className="flex-1 text-sm font-medium">{message}</p>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-current opacity-70 hover:opacity-100 transition-opacity tap-target-sm"
|
|
aria-label="Close notification"
|
|
>
|
|
<X size={18} />
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|