# Toast **Category**: react **URL**: https://heroui.com/en/docs/react/components/toast **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/en/react/components/(overlays)/toast.mdx > Display temporary notifications and messages to users with automatic dismissal and customizable placement *** ## Usage ```tsx import { Toast, toast } from '@heroui/react'; ``` ```tsx "use client"; import {Persons} from "@gravity-ui/icons"; import {Button, toast} from "@heroui/react"; export function Default() { return (
); } ``` ## Anatomy ```tsx ``` ## Examples ### Variants ```tsx "use client"; import {HardDrive, Persons} from "@gravity-ui/icons"; import {Button, toast} from "@heroui/react"; export function Variants() { return (
); } ``` ### Placements ```tsx "use client"; import type {ToastVariants} from "@heroui/react"; import {Button, Toast, ToastQueue} from "@heroui/react"; type Placement = NonNullable; const placements = ["top start", "top", "top end", "bottom start", "bottom", "bottom end"] as const; // Create a separate queue for each placement const placementQueues = Object.fromEntries( placements.map((p) => [p, new ToastQueue({maxVisibleToasts: 3})]), ) as Record; export function Placements() { const showToast = (placement: Placement) => { placementQueues[placement].add({ description: "Event has been created", title: "Event created", variant: "default", }); }; return (
{/* Render a ToastProvider for each placement */} {placements.map((p) => ( ))}
{placements.map((p) => ( ))}
); } ``` ### Expanded Stack ```tsx "use client"; import {Button, Toast, ToastQueue} from "@heroui/react"; const queue = new ToastQueue(); export function Expanded() { return (
); } ``` ### Simple Toasts ```tsx "use client"; import {Button, toast} from "@heroui/react"; export function Simple() { return (
); } ``` ### Custom Indicators ```tsx "use client"; import {Star} from "@gravity-ui/icons"; import {Button, toast} from "@heroui/react"; export function CustomIndicator() { return (
); } ``` ### Custom Toast Rendering ```tsx "use client"; import type {ToastContentValue} from "@heroui/react"; import { Button, Toast, ToastContent, ToastDescription, ToastIndicator, ToastQueue, ToastTitle, } from "@heroui/react"; export function CustomToast() { const customQueue = new ToastQueue(); return (
{({toast: toastItem}) => { const content = toastItem.content as ToastContentValue; return (
{content.title ? ( {content.title} ) : null} {content.description ? ( {content.description} ) : null}
); }}
); } ``` ### Promise & Loading ```tsx "use client"; import {Button, toast} from "@heroui/react"; const uploadFile = (): Promise<{filename: string; size: number}> => { return new Promise<{filename: string; size: number}>((resolve) => { setTimeout(() => resolve({filename: "document.pdf", size: 1024}), 2000); }); }; const createEvent = (): Promise => { return new Promise((_, reject) => { setTimeout(() => reject(new Error("Network error. Please try again.")), 2000); }); }; const saveData = (): Promise<{count: number}> => { return new Promise<{count: number}>((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.5) { resolve({count: 42}); } else { reject(new Error("Failed to save data")); } }, 2000); }); }; const fetchUser = (): Promise<{name: string; email: string}> => { return new Promise<{name: string; email: string}>((resolve) => { setTimeout(() => resolve({email: "john@example.com", name: "John Doe"}), 2000); }); }; export function PromiseDemo() { return (
{/* Promise API Section */}

Using toast.promise()

Automatically handles loading, success, and error states

{/* Manual Loading Section */}

Manual Loading State

Manually control loading state with isLoading prop

); } ``` ### Callbacks ```tsx "use client"; import {Button, toast} from "@heroui/react"; import React from "react"; export function Callbacks() { const [closedHistory, setClosedHistory] = React.useState>( [], ); const addToHistory = (message: string) => { const time = new Date().toLocaleTimeString(); setClosedHistory((prev) => [{message, time}, ...prev].slice(0, 5)); }; return (
{/* Toast Buttons */}
{/* Closed History Panel */}

Closed History

{closedHistory.length > 0 && ( )}
{closedHistory.length === 0 ? (

No toasts closed yet. Try closing one above!

) : ( closedHistory.map((item, index) => (
{item.message} ({item.time})
)) )}
); } ``` ### Custom Queues ```tsx "use client"; import {Button, Toast, ToastQueue} from "@heroui/react"; export function CustomQueue() { const notificationQueue = new ToastQueue({maxVisibleToasts: 2}); const errorQueue = new ToastQueue({maxVisibleToasts: 3}); const successQueue = new ToastQueue({maxVisibleToasts: 1}); return (
{/* Notification Queue */}
{/* Error Queue */}
{/* Success Queue */}
); } ``` ### Setup Render the provider in the root of your app. ```tsx import { Toast, Button, toast } from '@heroui/react'; function App() { return (
); } ``` ## Customization ### Tailwind CSS ```tsx "use client"; import type {ToastContentValue} from "@heroui/react"; import { Button, Toast, ToastContent, ToastDescription, ToastIndicator, ToastQueue, ToastTitle, } from "@heroui/react"; export function CustomStyles() { const queue = new ToastQueue(); return (
{({toast: toastItem}) => { const content = toastItem.content as ToastContentValue; return (
{content.title ? ( {content.title} ) : null} {content.description ? ( {content.description} ) : null}
); }}
); } ``` ### Global CSS To customize the Toast component classes, you can use the `@layer components` directive. [Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .toast { @apply rounded-xl shadow-lg; } .toast__content { @apply gap-2; } } ``` ## Styling Reference HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Toast component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/toast.css)): #### Base Classes [!toc] - `.toast` - Base toast container - `.toast-region` - Toast region container - `.toast__content` - Content wrapper for title and description - `.toast__indicator` - Icon/indicator container - `.toast__title` - Toast title text - `.toast__description` - Toast description text - `.toast__action` - Action button container - `.toast__close-button` - Close button container #### Variant Classes [!toc] - `.toast--default` - Default gray variant - `.toast--accent` - Accent blue variant - `.toast--success` - Success green variant - `.toast--warning` - Warning yellow/orange variant - `.toast--danger` - Danger red variant ### Interactive States The component supports various states: - **Frontmost**: `[data-frontmost]` - Applied to the topmost visible toast - **Index**: `[data-index]` - Applied based on toast position in stack - **Placement**: `[data-placement="*"]` - Applied based on toast region placement - **Entering**: `[data-entering]` - Applied on first paint of a new toast - **Exiting**: `[data-exiting]` - Applied while a closing toast plays its exit transition - **Expanded**: `[data-expanded]` - Applied to every toast while the stack is expanded - **Hidden**: `[data-hidden]` - Applied to toasts beyond `maxVisibleToasts` ## API Reference ### Toast.Provider | Prop | Type | Default | Description | |------|------|---------|-------------| | `placement` | `"top start" \| "top" \| "top end" \| "bottom start" \| "bottom" \| "bottom end"` | `"bottom"` | Placement of the toast region | | `gap` | `number` | `12` | The gap between toasts in pixels | | `isExpanded` | `boolean` | `false` | Force the stack into its expanded layout (does not pause timers) | | `maxVisibleToasts` | `number` | `3` | Maximum number of toasts to display at once | | `hotkey` | `string[]` | `["altKey", "KeyT"]` | Hotkey that moves focus to the toast region and expands the stack. Modifiers match `KeyboardEvent` boolean properties (e.g. `"altKey"`), other keys match `event.code` (e.g. `"KeyT"`). Modifiers you leave out must be up, so `Alt`+`T` does not also fire on `Ctrl`+`Alt`+`T`. Pass `[]` to disable | | `scaleFactor` | `number` | `0.05` | Scale factor for stacked toasts (0-1) | | `width` | `number \| string` | `460` | Width of the toast in pixels or CSS value | | `queue` | `ToastQueue` | - | Custom toast queue instance | | `children` | `ReactNode \| ((props: {toast: QueuedToast}) => ReactNode)` | - | Custom render function or children | | `className` | `string` | - | Additional CSS classes | ### Toast | Prop | Type | Default | Description | |------|------|---------|-------------| | `toast` | `QueuedToast` | - | Toast data from queue (required) | | `variant` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Visual variant of the toast | | `placement` | `ToastVariants["placement"]` | - | Placement (inherited from Provider) | | `scaleFactor` | `number` | - | Scale factor (inherited from Provider) | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Toast content (ToastContent, ToastIndicator, etc.) | ### Toast.Content | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `ReactNode` | - | Content (typically ToastTitle and ToastDescription) | | `className` | `string` | - | Additional CSS classes | ### Toast.Indicator | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `ToastVariants["variant"]` | - | Variant for default icon | | `children` | `ReactNode` | - | Custom indicator icon (defaults to variant icon) | | `className` | `string` | - | Additional CSS classes | ### Toast.Title | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `ReactNode` | - | Title text | | `className` | `string` | - | Additional CSS classes | ### Toast.Description | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `ReactNode` | - | Description text | | `className` | `string` | - | Additional CSS classes | ### Toast.ActionButton | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `ReactNode` | - | Action button content | | `className` | `string` | - | Additional CSS classes | | All `Button` props | - | - | Accepts all Button component props | ### Toast.CloseButton | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | All `CloseButton` props | - | - | Accepts all CloseButton component props | ### ToastQueue A `ToastQueue` manages the state for a ``. The state is stored outside React so you can trigger toasts from anywhere in your application. #### Constructor Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `exitDuration` | `number` | `300` | How long a closing toast stays mounted for its exit animation (0 removes immediately) | | `maxVisibleToasts` | `number` | `3` | Maximum number of toasts to display at once (visual only) | | `wrapUpdate` | `(fn: () => void) => void` | - | Function to wrap state updates (e.g. `document.startViewTransition`); by default updates are applied directly and animated with CSS transitions | #### Methods | Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | `add` | `(content: T, options?: ToastOptions)` | `string` | Add a toast to the queue, returns toast key | | `update` | `(key: string, content: T, options?: {timeout?: number; onClose?: () => void})` | `boolean` | Update a toast in place, preserving its stack position; `timeout` restarts the countdown (0 keeps it open), omit it to keep the current countdown. Returns `false` if the toast no longer exists | | `close` | `(key: string)` | `void` | Close a toast by its key | | `pauseAll` | `()` | `void` | Pause all toast timers | | `resumeAll` | `()` | `void` | Resume all toast timers | | `clear` | `()` | `void` | Close all toasts (each toast animates out and fires its `onClose`) | | `subscribe` | `(fn: () => void)` | `() => void` | Subscribe to queue changes, returns unsubscribe function | ### toast Function The default `toast` function provides convenient methods for showing toasts: ```tsx import { toast } from '@heroui/react'; // Basic toast (auto-dismisses after 4 seconds by default) toast("Event has been created"); // Variant methods (also auto-dismiss after 4 seconds by default) toast.success("File saved"); toast.info("New update available"); toast.warning("Please check your settings"); toast.danger("Something went wrong"); // With options. The returned id lets the action close its own toast. const eventId = toast("Event has been created", { description: "Your event has been scheduled for tomorrow", variant: "default", timeout: 5000, // Custom timeout: 5 seconds onClose: () => console.log("Closed"), actionProps: { children: "View", onPress: () => toast.close(eventId), }, indicator: , }); // Update an existing toast in place (keeps its position in the stack). // Options you omit are inherited, so pass `timeout` to start a countdown // on a toast that was created persistent. const id = toast("Saving…", { timeout: 0 }); toast.update(id, "Saved", { variant: "success", timeout: 4000 }); // Promise support (automatically shows loading spinner). The loading toast // updates in place when the promise settles — same toast, same stack // position; the auto-dismiss countdown starts at that point. toast.promise( uploadFile(), { loading: "Uploading file...", success: (data) => `File ${data.filename} uploaded`, error: "Failed to upload file", } ); // Manual loading state (persistent toast - no auto-dismiss) const loadingId = toast("Creating event...", { isLoading: true, timeout: 0, // Persistent toast that doesn't auto-dismiss }); // Later, update in place and start the auto-dismiss countdown toast.update(loadingId, "Event created", { variant: "success", timeout: 4000 }); // Queue methods toast.close(key); toast.clear(); toast.pauseAll(); toast.resumeAll(); ``` #### toast Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `title` | `ReactNode` | - | Toast title (first parameter for variant methods) | | `description` | `ReactNode` | - | Optional description text | | `variant` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"default"` | Visual variant | | `indicator` | `ReactNode` | - | Custom indicator icon (null to hide) | | `actionProps` | `ButtonProps` | - | Props for action button | | `isLoading` | `boolean` | `false` | Show loading spinner instead of indicator | | `timeout` | `number` | `4000` | Auto-dismiss timeout in milliseconds. Defaults to 4000ms (4 seconds). Set to `0` for persistent toasts that don't auto-dismiss | | `onClose` | `() => void` | - | Called when the toast is dismissed, as its exit animation starts | #### toast.promise Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `loading` | `ReactNode` | - | Message shown while promise is pending | | `success` | `ReactNode \| ((data: T) => ReactNode)` | - | Message shown on success (can be function) | | `error` | `ReactNode \| ((error: Error) => ReactNode)` | - | Message shown on error (can be function) | ## Accessibility Each toast implements the [WAI-ARIA alertdialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/), grouped inside a labeled landmark region: - **Landmark region**: Toasts render in a labeled landmark reachable with `F6`; `Alt` + `T` moves focus straight to it. The hotkey is configurable via the `hotkey` prop and can be disabled by passing an empty array, and the region label can be overridden with `aria-label` - **Keyboard**: `Tab` reaches the controls of visible toasts, `Escape` collapses the expanded stack, and dismissing a focused toast moves focus to the nearest remaining toast - **Screen readers**: Each toast uses `role="alertdialog"` with its title and description linked; new toasts are announced automatically - **Timers**: Auto-dismiss pauses while the stack is hovered or focused, and while the page is in a background tab ## Related Components ## Related Components - **Button**: Allows a user to perform an action - **Alert**: Display important messages and notifications - **CloseButton**: Button for dismissing overlays