44 lines
1.1 KiB
TypeScript
44 lines
1.1 KiB
TypeScript
import { writable } from 'svelte/store';
|
|
|
|
// Small global toast queue.
|
|
//
|
|
// Any part of the UI can drop a message and it appears in the corner for a
|
|
// couple of seconds, then quietly dismisses. Replaces the ad-hoc "flash"
|
|
// strings scattered across pages when the message doesn't need to live inline
|
|
// with a form.
|
|
|
|
export type ToastVariant = 'info' | 'success' | 'warning' | 'danger';
|
|
|
|
export interface Toast {
|
|
id: number;
|
|
message: string;
|
|
variant: ToastVariant;
|
|
ttl: number;
|
|
href?: string;
|
|
}
|
|
|
|
export const toasts = writable<Toast[]>([]);
|
|
|
|
let nextId = 1;
|
|
|
|
export function toast(
|
|
message: string,
|
|
opts: { variant?: ToastVariant; ttl?: number; href?: string } = {}
|
|
): void {
|
|
const t: Toast = {
|
|
id: nextId++,
|
|
message,
|
|
variant: opts.variant ?? 'info',
|
|
ttl: opts.ttl ?? 3500,
|
|
href: opts.href
|
|
};
|
|
toasts.update((arr) => [...arr, t]);
|
|
if (t.ttl > 0) {
|
|
setTimeout(() => dismiss(t.id), t.ttl);
|
|
}
|
|
}
|
|
|
|
export function dismiss(id: number): void {
|
|
toasts.update((arr) => arr.filter((t) => t.id !== id));
|
|
}
|