Import source: src/context/ToastContext

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:17:44 +03:30
parent 6994f509a5
commit 9754a60006
+48
View File
@@ -0,0 +1,48 @@
import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
export type ToastType = 'success' | 'error' | 'info';
interface Toast { id: number; message: string; type: ToastType }
interface ToastCtx { show: (message: string, type?: ToastType) => void }
const ToastContext = createContext<ToastCtx>({ show: () => {} });
export function ToastProvider({ children }: { children: ReactNode }) {
const [toasts, setToasts] = useState<Toast[]>([]);
const show = useCallback((message: string, type: ToastType = 'success') => {
const id = Date.now();
setToasts(t => [...t, { id, message, type }]);
setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 2800);
}, []);
const ICONS = {
success: <path d="M4 8l4 4 7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>,
error: <path d="M6 6l6 6m0-6L6 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>,
info: <><circle cx="9" cy="5" r="1" fill="currentColor"/><path d="M9 8v5" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></>,
};
const COLORS = {
success: { bg: 'rgba(34,197,94,0.12)', border: 'rgba(34,197,94,0.3)', icon: '#22c55e' },
error: { bg: 'rgba(239,68,68,0.12)', border: 'rgba(239,68,68,0.3)', icon: '#ef4444' },
info: { bg: 'rgba(124,111,224,0.12)',border: 'rgba(124,111,224,0.3)',icon: '#7C6FE0' },
};
return (
<ToastContext.Provider value={{ show }}>
{children}
<div className="fixed bottom-6 right-6 flex flex-col gap-2 z-50 pointer-events-none">
{toasts.map(t => {
const c = COLORS[t.type];
return (
<div key={t.id} className="flex items-center gap-2.5 px-4 py-3 rounded-[12px] text-[14px] font-medium pointer-events-auto"
style={{ background: 'var(--bg-card)', border: `1px solid ${c.border}`, color: 'var(--text-primary)', boxShadow: '0 8px 32px rgba(0,0,0,0.3)', animation: 'toast-in 0.25s ease both', backdropFilter: 'blur(12px)', minWidth: '220px' }}>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" style={{ color: c.icon, flexShrink: 0 }}>{ICONS[t.type]}</svg>
{t.message}
</div>
);
})}
</div>
</ToastContext.Provider>
);
}
export const useToast = () => useContext(ToastContext);