Toast Queue
Signal-backed notification queue composed with the existing ToastProvider, Toast, ToastTitle, ToastDescription, and ToastClose components.
#Preview
Notification Queue
Notifications are rendered through the shared ToastProvider portal.
Source queue
0 trackedEvent log
1"use client"23import { createSignal, createMemo, createEffect, onCleanup } from '@barefootjs/client'4import {5 ToastProvider,6 Toast,7 ToastTitle,8 ToastDescription,9 ToastClose,10} from '@ui/components/ui/toast'1112type QueueToast = {13 id: number14 variant: 'success' | 'error' | 'warning' | 'info'15 title: string16 description: string17 duration: number18 status: 'visible' | 'exiting'19}2021const removeTimers = new Map<number, ReturnType<typeof setTimeout>>()2223export function ToastQueueDemo() {24 const [toasts, setToasts] = createSignal<QueueToast[]>([])25 const activeCount = createMemo(() => toasts().filter(t => t.status !== 'exiting').length)2627 const dismissToast = (id: number) => {28 setToasts(prev => prev.map(t => t.id === id ? { ...t, status: 'exiting' } : t))29 }3031 createEffect(() => {32 const current = toasts()33 current.forEach(toast => {34 if (toast.status !== 'exiting' || removeTimers.has(toast.id)) return35 removeTimers.set(toast.id, setTimeout(() => {36 removeTimers.delete(toast.id)37 setToasts(prev => prev.filter(t => t.id !== toast.id))38 }, 340))39 })40 })4142 createEffect(() => {43 onCleanup(() => removeTimers.forEach(timer => clearTimeout(timer)))44 })4546 return (47 <div>48 <button onClick={() => setToasts(prev => [makeToast(), ...prev])}>49 Add batch50 </button>51 <span>{activeCount()} active toasts</span>5253 <ToastProvider position="bottom-right">54 {toasts().map(toast => (55 <Toast56 key={toast.id}57 variant={toast.variant}58 open={toast.status !== 'exiting'}59 duration={toast.duration}60 onOpenChange={open => {61 if (!open) dismissToast(toast.id)62 }}63 >64 <div className="flex-1">65 <ToastTitle>{toast.title}</ToastTitle>66 <ToastDescription>{toast.description}</ToastDescription>67 </div>68 <ToastClose />69 </Toast>70 ))}71 </ToastProvider>72 </div>73 )74}#Features
Toast Component Composition
The queue renders each notification with the existing Toast subcomponents instead of hand-written toast markup, so variants, roles, close behavior, and animation classes stay aligned with the UI registry.
Owner-Scope Tracking
ToastProvider owns the portal into document.body, preserving the signal ownership chain after the provider node is moved outside the component tree.
Per-Toast Cleanup
Toast handles auto-dismiss through its duration prop, while the queue tracks exit-removal timers and clears them through onCleanup.
Stack Ordering + Exit Animation
The signal-backed queue keeps newest notifications first, and the provider's flex stack handles variable-height toast spacing. Manual dismiss changes the item status to exiting, then removes it after the animation delay.