Download frontend/src/components/shared/Toast.tsx from berohan/studyrag: direct link, hf CLI and curl.
- Browser
- Download file 1.89 kB
-
https://huggingface.co/spaces/berohan/studyrag/resolve/main/frontend/src/components/shared/Toast.tsx
- Command line
-
hf download hf://spaces/berohan/studyrag/frontend/src/components/shared/Toast.tsx
-
curl -L -o Toast.tsx https://huggingface.co/spaces/berohan/studyrag/resolve/main/frontend/src/components/shared/Toast.tsx
1.89 kB
| import { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react' | |
| import type { ReactNode } from 'react' | |
| import './toast.css' | |
| export type ToastType = 'success' | 'error' | 'info' | |
| interface ToastItem { | |
| id: string | |
| message: string | |
| type: ToastType | |
| visible: boolean | |
| } | |
| interface ToastContextValue { | |
| showToast: (message: string, type?: ToastType, duration?: number) => void | |
| } | |
| const ToastContext = createContext<ToastContextValue | undefined>(undefined) | |
| export function ToastProvider({ children }: { children: ReactNode }) { | |
| const [toasts, setToasts] = useState<ToastItem[]>([]) | |
| const counterRef = useRef(0) | |
| const showToast = useCallback((message: string, type: ToastType = 'info', duration = 4000) => { | |
| const id = `toast_${Date.now()}_${counterRef.current++}` | |
| setToasts((prev) => [...prev, { id, message, type, visible: false }]) | |
| // Trigger enter animation on next frame. | |
| requestAnimationFrame(() => { | |
| setToasts((prev) => prev.map((t) => (t.id === id ? { ...t, visible: true } : t))) | |
| }) | |
| setTimeout(() => { | |
| setToasts((prev) => prev.map((t) => (t.id === id ? { ...t, visible: false } : t))) | |
| setTimeout(() => { | |
| setToasts((prev) => prev.filter((t) => t.id !== id)) | |
| }, 300) | |
| }, duration) | |
| }, []) | |
| const value = useMemo(() => ({ showToast }), [showToast]) | |
| return ( | |
| <ToastContext.Provider value={value}> | |
| {children} | |
| <div className="toast-container" aria-live="polite"> | |
| {toasts.map((t) => ( | |
| <div key={t.id} className={`toast toast-${t.type}${t.visible ? ' show' : ''}`}> | |
| {t.message} | |
| </div> | |
| ))} | |
| </div> | |
| </ToastContext.Provider> | |
| ) | |
| } | |
| export function useToast(): ToastContextValue { | |
| const ctx = useContext(ToastContext) | |
| if (!ctx) { | |
| throw new Error('useToast must be used within a ToastProvider') | |
| } | |
| return ctx | |
| } | |