Files
Lyra/web/src/app/_ui/toast.tsx
T
Jonathan 92d1345503 feat(web): favicon + toast feedback (polish)
Add a vinyl-record favicon (icon.svg) — fixes the favicon.ico 404 console
error. Lightweight toast system (ToastHost + toast()) fired on request, wanted
add, search, follow, and want actions so submits give explicit feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 15:44:24 +02:00

39 lines
1.1 KiB
TypeScript

"use client";
import { useEffect, useRef, useState } from "react";
/** Fire a transient toast from anywhere: `toast("Queued")`. */
export function toast(message: string) {
if (typeof window !== "undefined") {
window.dispatchEvent(new CustomEvent("lyra-toast", { detail: message }));
}
}
/** Renders toasts fired via `toast()`. Mounted once in the root layout. */
export function ToastHost() {
const [items, setItems] = useState<{ id: number; text: string }[]>([]);
const nextId = useRef(0);
useEffect(() => {
function onToast(e: Event) {
const text = (e as CustomEvent<string>).detail;
const id = ++nextId.current;
setItems((xs) => [...xs, { id, text }]);
setTimeout(() => setItems((xs) => xs.filter((x) => x.id !== id)), 2600);
}
window.addEventListener("lyra-toast", onToast);
return () => window.removeEventListener("lyra-toast", onToast);
}, []);
if (items.length === 0) return null;
return (
<div className="toast-host" role="status" aria-live="polite">
{items.map((t) => (
<div key={t.id} className="toast">
{t.text}
</div>
))}
</div>
);
}