Files
yaak-mountain-loop/src-web/lib/toast.tsx
Gregory Schier b4a1c418bb Run oxfmt across repo, add format script and docs
Add .oxfmtignore to skip generated bindings and wasm-pack output.
Add npm format script, update DEVELOPMENT.md for Vite+ toolchain,
and format all non-generated files with oxfmt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:15:49 -07:00

69 lines
1.6 KiB
TypeScript

import { atom } from "jotai";
import type { ToastInstance } from "../components/Toasts";
import { generateId } from "./generateId";
import { jotaiStore } from "./jotai";
export const toastsAtom = atom<ToastInstance[]>([]);
export function showToast({
id,
timeout = 5000,
...props
}: Omit<ToastInstance, "id" | "timeout" | "uniqueKey"> & {
id?: ToastInstance["id"];
timeout?: ToastInstance["timeout"];
}) {
id = id ?? generateId();
const uniqueKey = generateId();
const toasts = jotaiStore.get(toastsAtom);
const toastWithSameId = toasts.find((t) => t.id === id);
let delay = 0;
if (toastWithSameId) {
hideToast(toastWithSameId);
// Allow enough time for old toast to animate out
delay = 200;
}
setTimeout(() => {
const newToast: ToastInstance = { id, uniqueKey, timeout, ...props };
if (timeout != null) {
setTimeout(() => hideToast(newToast), timeout);
}
jotaiStore.set(toastsAtom, (prev) => [...prev, newToast]);
}, delay);
return id;
}
export function hideToast(toHide: ToastInstance) {
jotaiStore.set(toastsAtom, (all) => {
const t = all.find((t) => t.uniqueKey === toHide.uniqueKey);
t?.onClose?.();
return all.filter((t) => t.uniqueKey !== toHide.uniqueKey);
});
}
export function showErrorToast<T>({
id,
title,
message,
}: {
id: string;
title: string;
message: T;
}) {
return showToast({
id,
color: "danger",
timeout: null,
message: (
<div className="w-full">
<h2 className="text-lg font-bold mb-2">{title}</h2>
<div className="whitespace-pre-wrap break-words">{String(message)}</div>
</div>
),
});
}