first commit
This commit is contained in:
65
client/src/components/Toast.tsx
Normal file
65
client/src/components/Toast.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
type ToastType = 'success' | 'error' | 'info' | 'like';
|
||||
|
||||
interface Toast {
|
||||
id: number;
|
||||
message: string;
|
||||
type: ToastType;
|
||||
}
|
||||
|
||||
interface ToastContextType {
|
||||
toast: (message: string, type?: ToastType) => void;
|
||||
}
|
||||
|
||||
const ToastContext = createContext<ToastContextType>(null!);
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
const iconMap: Record<ToastType, string> = {
|
||||
success: '✓',
|
||||
error: '✕',
|
||||
info: '·',
|
||||
like: '♥',
|
||||
};
|
||||
|
||||
export function ToastProvider({ children }: { children: ReactNode }) {
|
||||
const [toasts, setToasts] = useState<Toast[]>([]);
|
||||
|
||||
const addToast = useCallback((message: string, type: ToastType = 'info') => {
|
||||
const id = nextId++;
|
||||
setToasts((prev) => [...prev, { id, message, type }]);
|
||||
setTimeout(() => {
|
||||
setToasts((prev) => prev.filter((t) => t.id !== id));
|
||||
}, 2200);
|
||||
}, []);
|
||||
|
||||
const remove = (id: number) => {
|
||||
setToasts((prev) => prev.filter((t) => t.id !== id));
|
||||
};
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={{ toast: addToast }}>
|
||||
{children}
|
||||
<div className="fixed bottom-4 right-4 z-[100] flex flex-col gap-1.5">
|
||||
{toasts.map((t) => (
|
||||
<div
|
||||
key={t.id}
|
||||
className="animate-slide-up flex items-center gap-2 bg-foreground text-background px-3 py-2 text-sm shadow-lg"
|
||||
>
|
||||
<span className="opacity-70">{iconMap[t.type]}</span>
|
||||
<span>{t.message}</span>
|
||||
<button onClick={() => remove(t.id)} className="ml-2 opacity-50 hover:opacity-100">
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useToast() {
|
||||
return useContext(ToastContext);
|
||||
}
|
||||
Reference in New Issue
Block a user