Toast
A succinct message displayed temporarily to provide feedback about an action. Supports multiple variants, promise tracking, custom rendering, and global usage outside React.
#Installation
npx @dinachi/cli@latest add toast#Usage
import {
Toast,
ToastProvider,
ToastPortal,
ToastViewport,
ToastRoot,
ToastContent,
ToastTitle,
ToastDescription,
ToastAction,
ToastClose,
ToastPositioner,
ToastArrow,
ToastList,
useToastManager,
createToastManager,
} from '@/components/ui/toast'#Examples
#Toast Manager
The useToastManager hook (inside React) and createToastManager factory (outside React) return the same manager object.
#Methods
#add(options)
Create a toast. Returns the toast ID.
const id = manager.add({ title: 'Saved', type: 'success' });#update(id, options)
Modify an existing toast in-place — title, description, type, timeout, or action. This is what powers progress toasts, multi-step flows, and retry patterns.
manager.update(id, {
title: 'Upload complete',
type: 'success',
timeout: 5000,
});#close(id?)
Dismiss a specific toast by ID, or dismiss all toasts when called with no arguments.
manager.close(id); // close one toast
manager.close(); // close all toasts#promise(promise, options)
Track a promise with automatic loading, success, and error states. Each state accepts full toast options or a function that receives the resolved value / error.
manager.promise(
fetch('/api/save', { method: 'POST' }),
{
loading: { title: 'Saving...', description: 'Please wait.' },
success: (data) => ({ title: 'Saved', description: 'Changes applied.' }),
error: (err) => ({ title: 'Error', description: err.message }),
}
);#subscribe(listener)
Observe toast state changes from external systems. Returns an unsubscribe function.
const unsubscribe = manager.subscribe(() => {
console.log('Toasts changed:', manager.toasts);
});#Toast Options
All methods that create or modify a toast accept these options:
{
title: ReactNode,
description: ReactNode,
type: 'success' | 'error' | 'warning' | 'loading' | string,
timeout: number, // ms — use 0 to disable auto-dismiss
priority: 'low' | 'high',
actionProps: ButtonHTMLAttributes,
data: Record<string, unknown>, // custom data for renderToast
onClose: () => void,
onRemove: () => void,
}#Global Toast Manager
The CLI creates lib/toast.ts with a shared manager instance. Connect it to your React tree once, then use it from anywhere.
Create the shared instance:
// lib/toast.ts — created by the CLI
import { createToastManager } from '@/components/ui/toast';
export const toastManager = createToastManager();// providers.tsx
import { Toast } from '@/components/ui/toast';
import { toastManager } from '@/lib/toast';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<Toast toastManager={toastManager}>
{children}
</Toast>
);
}// api-client.ts
import { toastManager } from '@/lib/toast';
export async function apiCall() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error('Request failed');
return res.json();
} catch (err) {
toastManager.add({ title: err.message, type: 'error' });
throw err;
}
}#Custom Rendering
Pass renderToast to ToastList or the Toast convenience wrapper to control toast layout. The default layout is used as a fallback when renderToast is not provided.
<ToastList
renderToast={(toast) => (
<ToastContent>
<div className="flex items-start gap-3">
<MyIcon type={toast.type} />
<div>
<ToastTitle>{toast.title}</ToastTitle>
<ToastDescription>{toast.description}</ToastDescription>
</div>
</div>
<ToastClose />
</ToastContent>
)}
/>Custom data is accessible via toast.data. Pass it when creating the toast:
manager.add({
title: 'New message',
data: { avatarUrl: '/img/user.png', sender: 'Alice' },
});Then read it in your render function:
// In renderToast:
<img src={toast.data?.avatarUrl} alt={toast.data?.sender} />#API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| Toast.limit | number | 3 | Maximum number of visible toasts |
| Toast.timeout | number | 5000 | Auto-dismiss timeout in milliseconds. Use 0 to prevent auto-dismiss. |
| Toast.toastManager | ToastManager | — | External toast manager created via createToastManager() for global usage |
| Toast.renderToast | (toast: ToastObject) => ReactNode | — | Custom render function for toasts. Receives the toast object and returns JSX. Falls back to the default layout when not provided. |
| ToastRoot.variant | 'default' | 'destructive' | 'success' | 'warning' | 'loading' | 'default' | The visual style variant of the toast |
| ToastRoot.toast | ToastObject | — | The toast data object from the manager (required) |
| ToastRoot.swipeDirection | Array<'up' | 'down' | 'left' | 'right'> | ['down', 'right'] | The directions in which the toast can be swiped to dismiss |
| ToastList.renderToast | (toast: ToastObject) => ReactNode | — | Custom render function for toasts. Same as Toast.renderToast but applied directly to ToastList. |
| ToastClose.children | ReactNode | — | Custom close icon. Renders an XIcon from lucide-react by default. |
| ToastPositioner.toast | ToastObject | — | The toast data object (required). Positions the toast relative to an anchor element. |
| ToastPositioner.anchor | Element | null | — | The element to anchor the toast to. |
| ToastPositioner.side | 'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start' | 'top' | Which side of the anchor to position the toast on. |
| ToastPositioner.align | 'start' | 'center' | 'end' | 'center' | Alignment along the anchor edge. |
| ToastPositioner.sideOffset | number | 0 | Distance in pixels from the anchor. |
| ToastArrow.className | string | — | Additional classes for the decorative arrow. Styled with directional data-side attributes. |
| manager.add() | (options: { title?, description?, type?, timeout?, actionProps?, data?, priority? }) => string | — | Creates a toast notification and returns its ID |
| manager.update() | (id: string, updates) => void | — | Updates an existing toast's title, description, type, timeout, or actionProps |
| manager.close() | (id?: string) => void | — | Closes a toast by its ID, or dismisses all toasts when called with no arguments |
| manager.promise() | (promise, { loading, success, error }) => Promise | — | Binds a promise to a toast that auto-transitions through loading, success, and error states |
| manager.subscribe() | (listener: () => void) => () => void | — | Observes toast state changes. Returns an unsubscribe function. |