Files
AI-Expert-Sidebar/frontend/src/components/Toast.tsx
T
2026-04-01 15:29:35 +08:00

50 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useCallback, useEffect, useRef, useState } from 'react';
export interface ToastItem {
id: number;
message: string;
type: 'success' | 'error' | 'info';
}
interface ToastProps { toasts: ToastItem[]; }
export function Toast({ toasts }: ToastProps) {
return (
<div className="fixed bottom-4 left-1/2 -translate-x-1/2 z-[100] flex flex-col gap-2 items-center pointer-events-none">
{toasts.map(t => (
<div key={t.id}
className={`px-4 py-2 rounded-xl text-[12px] font-medium shadow-xl border animate-toast-in
${t.type === 'success' ? 'bg-green-500/20 text-green-300 border-green-500/30' :
t.type === 'error' ? 'bg-red-500/20 text-red-300 border-red-500/30' :
'bg-white/10 text-white/70 border-white/15'}`}>
{t.type === 'success' ? '✓ ' : t.type === 'error' ? '✕ ' : ' '}{t.message}
</div>
))}
</div>
);
}
let _toastId = 0;
export function useToast() {
const [toasts, setToasts] = useState<ToastItem[]>([]);
const timerRef = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());
const showToast = useCallback((message: string, type: ToastItem['type'] = 'success', duration = 2500) => {
const id = ++_toastId;
setToasts(prev => [...prev, { id, message, type }]);
const timer = setTimeout(() => {
setToasts(prev => prev.filter(t => t.id !== id));
timerRef.current.delete(id);
}, duration);
timerRef.current.set(id, timer);
}, []);
useEffect(() => {
const timers = timerRef.current;
return () => { timers.forEach(t => clearTimeout(t)); };
}, []);
return { toasts, showToast };
}