38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import React from 'react';
|
|
import { createPortal } from 'react-dom';
|
|
import { CheckCircle, AlertTriangle, Info, X } from 'lucide-react';
|
|
import { useToast } from '../contexts/ToastContext.tsx';
|
|
|
|
const icons = {
|
|
success: <CheckCircle className="text-green-500" size={20} />,
|
|
error: <AlertTriangle className="text-red-500" size={20} />,
|
|
info: <Info className="text-blue-500" size={20} />,
|
|
};
|
|
|
|
const toastColors = {
|
|
success: 'bg-green-50 border-green-200',
|
|
error: 'bg-red-50 border-red-200',
|
|
info: 'bg-blue-50 border-blue-200',
|
|
};
|
|
|
|
export const ToastContainer: React.FC = () => {
|
|
const { toasts } = useToast();
|
|
const portalElement = document.getElementById('toast-container');
|
|
|
|
if (!portalElement) return null;
|
|
|
|
return createPortal(
|
|
<div className="fixed top-6 right-6 z-[100] space-y-3">
|
|
{toasts.map((toast) => (
|
|
<div
|
|
key={toast.id}
|
|
className={`w-80 p-4 rounded-xl shadow-lg flex items-start gap-3 border animate-in slide-in-from-top-4 ${toastColors[toast.type]}`}
|
|
>
|
|
<div className="flex-shrink-0 mt-0.5">{icons[toast.type]}</div>
|
|
<p className="flex-1 text-sm text-gray-800 font-bold uppercase">{toast.message}</p>
|
|
</div>
|
|
))}
|
|
</div>,
|
|
portalElement
|
|
);
|
|
}; |