Skip to main content

max / makenotwork

1.3 KB · 37 lines History Blame Raw
1 // Toast notifications ported from mnw.js:44-68.
2
3 /** Maximum simultaneously-visible toasts. Beyond this the oldest drops first so
4 * a burst of HTMX errors can't bury the viewport. */
5 const TOAST_MAX_VISIBLE = 5;
6
7 interface ToastDetail {
8 message?: string;
9 type?: string;
10 }
11
12 /** Fire a toast. Rendered by the delegated listener installed by `initToasts`. */
13 export function showToast(message: string, type = 'error'): void {
14 document.body.dispatchEvent(new CustomEvent<ToastDetail>('showToast', { detail: { message, type } }));
15 }
16
17 /** Install the toast renderer (caps the stack, auto-dismisses). Call once at
18 * startup. Ported from mnw.js:47. */
19 export function initToasts(): void {
20 document.body.addEventListener('showToast', (evt) => {
21 const detail = (evt as CustomEvent<ToastDetail>).detail;
22 const container = document.getElementById('notifications');
23 if (!container) return;
24 while (container.childElementCount >= TOAST_MAX_VISIBLE) {
25 container.firstElementChild?.remove();
26 }
27 const toast = document.createElement('div');
28 toast.className = 'toast toast-' + (detail.type || 'info');
29 toast.textContent = detail.message || 'Action completed';
30 container.appendChild(toast);
31 setTimeout(() => {
32 toast.classList.add('fade-out');
33 setTimeout(() => toast.remove(), 300);
34 }, 3000);
35 });
36 }
37