spb/autoscholar
Public
1"use client";2import { createContext, type ReactNode, useCallback, useContext, useState } from "react";34type Toast = { id: number; kind: "info" | "error" | "success"; text: string };5const Ctx = createContext<{ push: (kind: Toast["kind"], text: string) => void }>({ push: () => {} });67export function ToastProvider({ children }: { children: ReactNode }) {8 const [items, setItems] = useState<Toast[]>([]);9 const push = useCallback((kind: Toast["kind"], text: string) => {10 const id = Date.now() + Math.random();11 setItems((x) => [...x, { id, kind, text }]);12 setTimeout(() => setItems((x) => x.filter((t) => t.id !== id)), 6000);13 }, []);14 return (15 <Ctx.Provider value={{ push }}>16 {children}17 <div18 aria-live="polite"19 aria-atomic="false"20 className="pointer-events-none fixed inset-x-0 bottom-4 z-50 flex flex-col items-center gap-2 px-4"21 >22 {items.map((t) => (23 <div24 key={t.id}25 role={t.kind === "error" ? "alert" : "status"}26 className="surface pointer-events-auto max-w-lg px-4 py-2 text-sm shadow-lg"27 style={{28 borderColor:29 t.kind === "error"30 ? "var(--color-danger-500)"31 : t.kind === "success"32 ? "var(--color-ok-500)"33 : "var(--line-strong)",34 }}35 >36 {t.text}37 </div>38 ))}39 </div>40 </Ctx.Provider>41 );42}43export const useToast = () => useContext(Ctx);44