Skip to content

Toast

import { Toaster, toast } from '@delightstack/components';

The Toaster component is mounted once in your root layout. The toast function is called anywhere to create notifications.

import type { ToastOptions } from '@delightstack/components';

Place <Toaster /> once in your root layout, then call toast() from anywhere.

View code
<script>
import { Toaster, toast } from '@delightstack/components';
import { Button } from '@delightstack/components';
</script>
<Button onclick={() => toast.success('Changes saved successfully!')}>Success Toast</Button>
<Button error onclick={() => toast.error('Something went wrong!')}>Error Toast</Button>
<Button outline onclick={() => toast.warning('You have unsaved changes')}>Warning Toast</Button>
<Button onclick={() => toast('This is an info notification')}>Info Toast</Button>
<Toaster />
View code
<script>
import { toast } from '@delightstack/components';
</script>
<button onclick={() => toast('A general notification')}>Default</button>
<button onclick={() => toast.success('File uploaded successfully')}>Success</button>
<button onclick={() => toast.error('Failed to save changes')}>Error</button>
<button onclick={() => toast.warning('You have unsaved changes')}>Warning</button>

Toasts with an action automatically get 2 seconds of extra display time.

View code
<script>
import { toast } from '@delightstack/components';
function handleDelete() {
toast('Item deleted', {
action: {
label: 'Undo',
onclick: () => toast.success('Item restored!'),
},
});
}
</script>
<button onclick={handleDelete}>Delete Item</button>

Track async operations with automatic loading, success, and error states.

View code
<script>
import { toast } from '@delightstack/components';
async function handleUpload() {
toast.promise(uploadFile(), {
loading: 'Uploading...',
success: 'Upload complete!',
error: (err) => `Upload failed: ${err.message}`,
});
}
</script>
<button onclick={handleUpload}>Upload</button>

The success and error messages can be functions that receive the result or error.

View code
<script>
import { toast } from '@delightstack/components';
function handleSave() {
const promise = new Promise((resolve) =>
setTimeout(() => resolve({ filename: 'report.pdf' }), 2000)
);
toast.promise(promise, {
loading: 'Saving...',
success: (result) => `Saved ${result.filename}`,
error: (err) => `Failed: ${err.message}`,
});
}
</script>
<button onclick={handleSave}>Save File</button>

Set persistent: true to prevent auto-dismiss. The toast stays until manually dismissed.

View code
<script>
import { toast } from '@delightstack/components';
</script>
<button onclick={() => toast.warning('Session expiring soon', { persistent: true })}>
Show Persistent Warning
</button>
View code
<script>
import { toast } from '@delightstack/components';
</script>
<button onclick={() => toast('Quick notice', { duration: 2000 })}>
2 Second Toast
</button>
<button onclick={() => toast('Longer notice', { duration: 8000 })}>
8 Second Toast
</button>
View code
<script>
import { toast } from '@delightstack/components';
function showAndDismiss() {
const id = toast('This will be dismissed in 2 seconds');
setTimeout(() => toast.dismiss(id), 2000);
}
</script>
<button onclick={showAndDismiss}>Show then Dismiss</button>
<button onclick={() => toast.dismiss()}>Clear All Toasts</button>

The <Toaster /> component accepts these configuration props.

PropTypeDefaultDescription
positionPosition'bottom-right'Screen position for the toast stack
max_visiblenumber3Toasts shown before older ones stack behind
gapnumber14Spacing between toasts when the stack is expanded (px)
widthnumber356Toast width (px)
durationnumber4000Default auto-dismiss duration (ms)
rich_colorsbooleanfalseUse saturated, variant-colored backgrounds
idstringautoElement ID
classstring''Additional CSS classes

Toasts collapse into a stack (like sonner) and fan out into a list on hover. Hovering also pauses auto-dismiss. Toasts can be swiped away with the pointer.

Options passed to toast(), toast.success(), toast.error(), toast.warning(), toast.info(), and toast.loading().

OptionTypeDefaultDescription
descriptionstring-Secondary line shown beneath the title
durationnumber4000Auto-dismiss time in ms
dismissiblebooleantrueShow close button (on hover)
successbooleanfalseSuccess variant
warningbooleanfalseWarning variant
errorbooleanfalseError variant
infobooleanfalseInfo variant
action{ label: string; onclick: () => void }-Action button in the toast
persistentbooleanfalseNever auto-dismiss
idstringauto-generatedCustom toast ID
type Position =
| 'top-left' | 'top-center' | 'top-right'
| 'bottom-left' | 'bottom-center' | 'bottom-right';
interface ToastOptions {
duration?: number;
dismissible?: boolean;
success?: boolean;
warning?: boolean;
error?: boolean;
action?: { label: string; onclick: () => void };
persistent?: boolean;
progress?: boolean;
id?: string;
}

Show a default toast. Returns the toast ID.

Show a success toast with a checkmark icon.

Show an error toast with an X icon.

Show a warning toast with an alert icon.

toast.promise<T>(promise, messages, options?): Promise<T>

Section titled “toast.promise<T>(promise, messages, options?): Promise<T>”

Track a promise through loading, success, and error states. Returns the original promise.

Dismiss a specific toast by ID, or all toasts if no ID is provided.

  • Uses role="status" for default and success toasts (polite announcement)
  • Uses role="alert" for warning and error toasts (assertive announcement)
  • Each toast is an aria-live region so screen readers announce new toasts
  • Close button has aria-label="Dismiss notification"
  • Action button is keyboard-focusable
  • Escape key dismisses the most recent toast
  • Focus does not move to toasts automatically (non-intrusive)
  • Supports swipe-to-dismiss on touch devices
  • Hover over the toast stack pauses all countdown timers
  • Respects prefers-reduced-motion (disables slide/scale animations, uses opacity-only transitions)