import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; import Icon from "./components/Icon"; /** * Kurze Rückmeldungen als Overlay am unteren Rand. * * Vorher standen sie als Hinweisleiste mitten in der Seite – dadurch sprang * beim Speichern das ganze Layout ein Stück nach unten. Ein Overlay liegt über * dem Inhalt und verschiebt nichts. * * Bewusst nur für *Erfolgsmeldungen*: Fehler bleiben als Leiste an ihrer Stelle * stehen. Eine Fehlermeldung, die nach fünf Sekunden verschwindet, ist genau * dann weg, wenn man sie noch braucht. * * const toast = useToast(); * toast("Gespeichert."); */ const ToastContext = createContext(() => {}); const DAUER = 5000; export function ToastProvider({ children }) { const [meldungen, setMeldungen] = useState([]); const uhren = useRef(new Map()); const entfernen = useCallback((id) => { setMeldungen((alt) => alt.filter((m) => m.id !== id)); const uhr = uhren.current.get(id); if (uhr) { clearTimeout(uhr); uhren.current.delete(id); } }, []); const zeigen = useCallback((text, art = "ok") => { if (!text) return; const id = `${Date.now()}-${Math.random()}`; setMeldungen((alt) => [...alt, { id, text, art }]); uhren.current.set(id, setTimeout(() => entfernen(id), DAUER)); }, [entfernen]); // Beim Verlassen der Seite laufende Uhren abräumen. useEffect(() => { const laufend = uhren.current; return () => laufend.forEach((uhr) => clearTimeout(uhr)); }, []); return ( {children} {/* aria-live: Bildschirmleser sagen die Meldung an, ohne den Fokus zu stehlen. */}
{meldungen.map((m) => (
{m.text}
))}
); } export function useToast() { return useContext(ToastContext); }