summaryrefslogtreecommitdiff
path: root/frontend/src/components/document/Toast.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/document/Toast.tsx')
-rw-r--r--frontend/src/components/document/Toast.tsx97
1 files changed, 0 insertions, 97 deletions
diff --git a/frontend/src/components/document/Toast.tsx b/frontend/src/components/document/Toast.tsx
deleted file mode 100644
index 653db8f..0000000
--- a/frontend/src/components/document/Toast.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useRef,
- useState,
- type ReactNode,
-} from 'react';
-import './Toast.css';
-
-// -- Types -------------------------------------------------------------------
-
-export type ToastType = 'success' | 'error' | 'info';
-
-interface ToastItem {
- id: number;
- message: string;
- type: ToastType;
-}
-
-interface ToastContextValue {
- addToast: (message: string, type?: ToastType) => void;
-}
-
-// -- Context -----------------------------------------------------------------
-
-const ToastContext = createContext<ToastContextValue | null>(null);
-
-export function useToast(): ToastContextValue {
- const ctx = useContext(ToastContext);
- if (!ctx) throw new Error('useToast must be used within a ToastProvider');
- return ctx;
-}
-
-// -- Provider ----------------------------------------------------------------
-
-const DISMISS_MS = 3000;
-
-export function ToastProvider({ children }: { children: ReactNode }) {
- const [toasts, setToasts] = useState<ToastItem[]>([]);
- const nextId = useRef(0);
-
- const addToast = useCallback((message: string, type: ToastType = 'info') => {
- const id = nextId.current++;
- setToasts((prev) => [...prev, { id, message, type }]);
- }, []);
-
- const removeToast = useCallback((id: number) => {
- setToasts((prev) => prev.filter((t) => t.id !== id));
- }, []);
-
- return (
- <ToastContext.Provider value={{ addToast }}>
- {children}
- <div className="toast-container">
- {toasts.map((t) => (
- <ToastItem key={t.id} toast={t} onDismiss={removeToast} />
- ))}
- </div>
- </ToastContext.Provider>
- );
-}
-
-// -- Single toast ------------------------------------------------------------
-
-function ToastItem({
- toast,
- onDismiss,
-}: {
- toast: ToastItem;
- onDismiss: (id: number) => void;
-}) {
- const [exiting, setExiting] = useState(false);
-
- useEffect(() => {
- const timer = setTimeout(() => setExiting(true), DISMISS_MS - 300);
- const remove = setTimeout(() => onDismiss(toast.id), DISMISS_MS);
- return () => {
- clearTimeout(timer);
- clearTimeout(remove);
- };
- }, [toast.id, onDismiss]);
-
- const icon =
- toast.type === 'success' ? '\u2713' : toast.type === 'error' ? '\u2717' : '\u2139';
-
- return (
- <div
- className={`toast-item toast-${toast.type} ${exiting ? 'toast-exit' : 'toast-enter'}`}
- role="status"
- >
- <span className="toast-icon">{icon}</span>
- <span className="toast-message">{toast.message}</span>
- </div>
- );
-}