73 lines
2.6 KiB
TypeScript
73 lines
2.6 KiB
TypeScript
'use client'
|
|
import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react';
|
|
import React, { useState, useEffect } from 'react';
|
|
|
|
interface Toast {
|
|
id: string;
|
|
message: string;
|
|
type?: 'success' | 'error' | 'info';
|
|
isExiting?: boolean;
|
|
}
|
|
|
|
let addToast: (toast: Toast) => void;
|
|
|
|
const ToastContainer: React.FC = () => {
|
|
const [toasts, setToasts] = useState<Toast[]>([]);
|
|
|
|
// ثبت toast جدید
|
|
const showToast = (toast: Toast) => {
|
|
setToasts((prev) => [...prev, toast]);
|
|
|
|
// حذف خودکار بعد از ۳ ثانیه
|
|
setTimeout(() => {
|
|
setToasts((prev) => prev.map(t =>
|
|
t.id === toast.id ? { ...t, isExiting: true } : t
|
|
));
|
|
|
|
// حذف از DOM بعد از اتمام انیمیشن
|
|
setTimeout(() => {
|
|
setToasts((prev) => prev.filter((t) => t.id !== toast.id));
|
|
}, 300); // مدت زمان انیمیشن خروج
|
|
}, 3000);
|
|
};
|
|
|
|
// تخصیص تابع نمایش toast به متغیر سراسری
|
|
useEffect(() => {
|
|
addToast = showToast;
|
|
}, []);
|
|
|
|
return (
|
|
<div className="fixed top-4 text-sm right-0 left-0 mx-auto w-fit z-50 flex flex-col gap-2">
|
|
{toasts.map((toast) => (
|
|
<div
|
|
key={toast.id}
|
|
className={`px-4 flex items-center gap-2 backdrop-blur-2xl h-16 min-w-[300px] rounded-2xl shadow-md
|
|
${toast.isExiting ? 'animate-slide-out-right' : 'animate-slide-in-right'} ${toast.type === 'success'
|
|
? 'bg-white/70 text-black'
|
|
: toast.type === 'error'
|
|
? 'bg-white/70 text-black'
|
|
: 'bg-white/70 text-black'
|
|
}`}
|
|
style={{
|
|
animationFillMode: 'forwards',
|
|
animationDuration: '0.3s',
|
|
animationTimingFunction: 'ease-out'
|
|
}}
|
|
>
|
|
{
|
|
toast.type === 'success' ? <TickCircle className='size-5' color='green' /> :
|
|
toast.type === 'error' ? <CloseCircle className='size-5' color='red' /> :
|
|
<InfoCircle className='size-5' color='blue' />
|
|
}
|
|
{toast.message}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const toast = (message?: string, type: 'success' | 'error' | 'info' = 'info') => {
|
|
addToast({ id: Date.now().toString(), message: message || '', type });
|
|
};
|
|
|
|
export default ToastContainer; |