# Toast URL: https://ark-ui.com/docs/components/toast Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/toast.mdx A message that appears on the screen to provide feedback on an action. --- ## Anatomy To set up the toast correctly, you'll need to understand its anatomy and how we name its parts. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Setup To use the Toast component, create the toast engine using the `createToaster` function. This function manages the placement and grouping of toasts, and provides a `toast` object needed to create toast notification. ```ts const toaster = createToaster({ placement: 'bottom-end', overlap: true, gap: 24, }) ``` ## Examples Here's an example of creating a toast using the `toast.create` method. **Example: basic** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { XIcon } from 'lucide-react' const toaster = createToaster({ placement: 'bottom-end', overlap: true, gap: 24, }) export const Basic = () => { return (
{(toast) => ( {toast.title} {toast.description} )}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { XIcon } from 'lucide-solid' export const Basic = () => { const toaster = createToaster({ placement: 'bottom-end', gap: 24, }) return (
{(toast) => ( {toast().title} {toast().description} )}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)} {toast().title} {toast().description} {/snippet}
``` ### Toast Types You can create different types of toasts (`success`, `error`, `warning`, `info`) with appropriate styling. For example, to create a success toast, you can do: ```ts toaster.success({ title: 'Success!', description: 'Your changes have been saved.', }) ``` **Example: types** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { CircleAlertIcon, TriangleAlertIcon, CircleCheckIcon, InfoIcon, X } from 'lucide-react' const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) const iconMap = { success: CircleCheckIcon, error: CircleAlertIcon, warning: TriangleAlertIcon, info: InfoIcon, } export const Types = () => { return (
{(toast) => { const ToastIcon = toast.type ? iconMap[toast.type as keyof typeof iconMap] : undefined return (
{ToastIcon && }
{toast.title} {toast.description}
) }}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { CircleAlertIcon, TriangleAlertIcon, CircleCheckIcon, InfoIcon, XIcon } from 'lucide-solid' import { Dynamic } from 'solid-js/web' const iconMap = { success: CircleCheckIcon, error: CircleAlertIcon, warning: TriangleAlertIcon, info: InfoIcon, } export const Types = () => { const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) return (
{(toast) => { const icon = () => (toast().type ? iconMap[toast().type as keyof typeof iconMap] : InfoIcon) return (
{toast().title} {toast().description}
) }}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)} {@const icon = toast().type ? iconMap[toast().type as keyof typeof iconMap] : InfoIcon}
{toast().title} {toast().description}
{/snippet}
``` ### Promise You can use `toaster.promise()` to automatically handle the different states of an asynchronous operation. It provides options for the `success`, `error`, and `loading` states of the promise and will automatically update the toast when the promise resolves or rejects. **Example: promise-toast** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { XIcon, LoaderIcon, CircleCheckIcon, CircleAlertIcon } from 'lucide-react' const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) const uploadFile = () => { return new Promise((resolve, reject) => { setTimeout(() => { Math.random() > 0.5 ? resolve() : reject(new Error('Upload failed')) }, 2000) }) } export const PromiseToast = () => { const handleUpload = async () => { toaster.promise(uploadFile, { loading: { title: 'Uploading...', description: 'Please wait while we process your request.', }, success: { title: 'Success!', description: 'Your request has been processed successfully.', }, error: { title: 'Failed', description: 'Something went wrong. Please try again.', }, }) } const getIcon = (type: string | undefined) => { switch (type) { case 'loading': return case 'success': return case 'error': return default: return null } } return (
{(toast) => (
{getIcon(toast.type)}
{toast.title} {toast.description}
)}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { CircleAlertIcon, CircleCheckIcon, InfoIcon, LoaderIcon, XIcon } from 'lucide-solid' import { Dynamic } from 'solid-js/web' const uploadFile = () => { return new Promise((resolve, reject) => { setTimeout(() => { Math.random() > 0.5 ? resolve() : reject(new Error('Upload failed')) }, 2000) }) } export const PromiseToast = () => { const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) const handleUpload = async () => { toaster.promise(uploadFile, { loading: { title: 'Uploading...', description: 'Please wait while we process your request.', }, success: { title: 'Success!', description: 'Your request has been processed successfully.', }, error: { title: 'Failed', description: 'Something went wrong. Please try again.', }, }) } const getIcon = (type: string | undefined) => { switch (type) { case 'loading': return LoaderIcon case 'success': return CircleCheckIcon case 'error': return CircleAlertIcon default: return InfoIcon } } return (
{(toast) => { const icon = () => getIcon(toast().type) return (
{toast().title} {toast().description}
) }}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)} {@const icon = toast().type ? iconMap[toast().type as keyof typeof iconMap] : undefined}
{#if icon} {/if}
{toast().title} {toast().description}
{/snippet}
``` ### Update Toast To update a toast, use the `toast.update` method. **Example: update** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { useRef } from 'react' const toaster = createToaster({ placement: 'bottom-end', overlap: true, gap: 24, }) export const Update = () => { const id = useRef(undefined) const createToast = () => { id.current = toaster.create({ title: 'Loading', description: 'Loading ...', type: 'info', }) } const updateToast = () => { if (!id.current) { return } toaster.update(id.current, { title: 'Success', description: 'Success!', }) } return (
{(toast) => ( {toast.title} {toast.description} )}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { createSignal } from 'solid-js' const toaster = createToaster({ placement: 'bottom-end', overlap: true, gap: 24, }) export const Update = () => { const [id, setId] = createSignal(undefined) const createToast = () => { const newId = toaster.create({ title: 'Loading', description: 'Loading ...', type: 'info', }) setId(newId) } const updateToast = () => { const currentId = id() if (!currentId) { return } toaster.update(currentId, { title: 'Success', description: 'Success!', }) } return (
{(toast) => ( {toast().title} {toast().description} )}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)} {toast().title} {toast().description} {/snippet}
``` ### Action To add an action to a toast, use the `toast.action` property. **Example: action** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' const toaster = createToaster({ placement: 'bottom-end', gap: 24, }) export const Action = () => { return (
{(toast) => ( {toast.title} {toast.description} {toast.action && {toast.action?.label}} )}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' const toaster = createToaster({ placement: 'bottom-end', gap: 24, }) export const Action = () => { return (
{(toast) => ( {toast().title} {toast().description} {toast().action && {toast().action?.label}} )}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)} {toast().title} {toast().description} {#if toast().action} {toast().action?.label} {/if} {/snippet}
``` ### Custom Duration You can control how long a toast stays visible by setting a custom `duration` in milliseconds, or use `Infinity` to keep it visible until manually dismissed. **Example: duration** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { XIcon, ClockIcon } from 'lucide-react' const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) const durations = [ { label: '1s', value: 1000 }, { label: '3s', value: 3000 }, { label: '5s', value: 5000 }, { label: '∞', value: Infinity }, ] export const Duration = () => { return (
{durations.map((duration) => ( ))}
{(toast) => (
{toast.title} {toast.description}
)}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { XIcon, ClockIcon } from 'lucide-solid' import { For } from 'solid-js' const durations = [ { label: '1s', value: 1000 }, { label: '3s', value: 3000 }, { label: '5s', value: 5000 }, { label: '∞', value: Infinity }, ] export const Duration = () => { const toaster = createToaster({ overlap: true, placement: 'bottom-end', gap: 16, }) return (
{(duration) => ( )}
{(toast) => (
{toast().title} {toast().description}
)}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#each durations as duration} {/each}
{#snippet children(toast)}
{toast().title} {toast().description}
{/snippet}
``` ### Maximum Visible Toasts Set the `max` prop on the `createToaster` function to define the maximum number of toasts that can be rendered at any one time. Any extra toasts will be queued and rendered when a toast has been dismissed. **Example: max-toasts** #### React ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/react/toast' import { XIcon, InfoIcon } from 'lucide-react' const toaster = createToaster({ max: 3, overlap: true, placement: 'bottom-end', gap: 16, }) export const MaxToasts = () => { return (
{(toast) => (
{toast.title} {toast.description}
)}
) } ``` #### Solid ```tsx import { Toast, Toaster, createToaster } from '@ark-ui/solid/toast' import { XIcon, InfoIcon } from 'lucide-solid' export const MaxToasts = () => { const toaster = createToaster({ max: 3, overlap: true, placement: 'bottom-end', gap: 16, }) return (
{(toast) => (
{toast().title} {toast().description}
)}
) } ``` #### Vue ```vue ``` #### Svelte ```svelte
{#snippet children(toast)}
{toast().title} {toast().description}
{/snippet}
``` ## Guides ### Creating Toast in Effects When creating a toast inside React effects (like `useEffect`, `useLayoutEffect`, or event handlers that trigger during render), you may encounter a "flushSync" warning. To avoid this, wrap the toast call in `queueMicrotask`: ```tsx import { useEffect } from 'react' export const EffectToast = () => { useEffect(() => { // ❌ This may cause flushSync warnings // toaster.create({ title: 'Effect triggered!' }) // ✅ Wrap in queueMicrotask to avoid warnings queueMicrotask(() => { toaster.create({ title: 'Effect triggered!', description: 'This toast was called safely from an effect', type: 'success', }) }) }, []) return
Component content
} ``` This ensures the toast creation is deferred until after the current execution context, preventing React's concurrent rendering warnings. ### Styling the toast There's a minimal styling required for the toast to work correctly. #### Toast root The toast root will be assigned these css properties at runtime: - `--x` - The x position - `--y` - The y position - `--scale` - The scale - `--z-index` - The z-index - `--height` - The height - `--opacity` - The opacity - `--gap` - The gap between toasts ```css [data-scope='toast'][data-part='root'] { translate: var(--x) var(--y); scale: var(--scale); z-index: var(--z-index); height: var(--height); opacity: var(--opacity); will-change: translate, opacity, scale; transition: translate 400ms, scale 400ms, opacity 400ms, height 400ms, box-shadow 200ms; transition-timing-function: cubic-bezier(0.21, 1.02, 0.73, 1); &[data-state='closed'] { transition: translate 400ms, scale 400ms, opacity 200ms; transition-timing-function: cubic-bezier(0.06, 0.71, 0.55, 1); } } ``` #### Styling based on type You can also style based on the `data-type` attribute. ```css [data-scope='toast'][data-part='root'] { &[data-type='error'] { background: red; color: white; } &[data-type='info'] { background: blue; color: white; } &[data-type='warning'] { background: orange; } &[data-type='success'] { background: green; color: white; } } ``` #### Mobile considerations A very common use case is to adjust the toast width on mobile so it spans the full width of the screen. ```css @media (max-width: 640px) { [data-scope='toast'][data-part='group'] { width: 100%; } [data-scope='toast'][data-part='root'] { inset-inline: 0; width: calc(100% - var(--gap) * 2); } } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | toast | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-type]` | The type of the item | | `[data-placement]` | The placement of the toast | | `[data-align]` | | | `[data-side]` | | | `[data-mounted]` | Present when mounted | | `[data-paused]` | Present when paused | | `[data-first]` | | | `[data-sibling]` | | | `[data-stack]` | | | `[data-overlap]` | Present when overlapping | **ActionTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **CloseTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Description Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Title Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Toaster Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `toaster` | `CreateToasterReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `getRootNode` | `() => Node | ShadowRoot | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | toast | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-type]` | The type of the item | | `[data-placement]` | The placement of the toast | | `[data-align]` | | | `[data-side]` | | | `[data-mounted]` | Present when mounted | | `[data-paused]` | Present when paused | | `[data-first]` | | | `[data-sibling]` | | | `[data-stack]` | | | `[data-overlap]` | Present when overlapping | **ActionTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **CloseTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Description Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Title Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Toaster Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `toaster` | `CreateToasterReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `getRootNode` | `() => Node | ShadowRoot | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | toast | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-type]` | The type of the item | | `[data-placement]` | The placement of the toast | | `[data-align]` | | | `[data-side]` | | | `[data-mounted]` | Present when mounted | | `[data-paused]` | Present when paused | | `[data-first]` | | | `[data-sibling]` | | | `[data-stack]` | | | `[data-overlap]` | Present when overlapping | **ActionTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **CloseTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Description Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Title Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Toaster Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `toaster` | `CreateToasterReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | toast | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-type]` | The type of the item | | `[data-placement]` | The placement of the toast | | `[data-align]` | | | `[data-side]` | | | `[data-mounted]` | Present when mounted | | `[data-paused]` | Present when paused | | `[data-first]` | | | `[data-sibling]` | | | `[data-stack]` | | | `[data-overlap]` | Present when overlapping | **ActionTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **CloseTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseToastContext]>` | Yes | | **Description Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Title Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Toaster Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `toaster` | `CreateToasterReturn` | Yes | The toaster instance. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `getRootNode` | `() => Node | ShadowRoot | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | | `ref` | `Element` | No | | ### Context These are the properties available when using `Toast.Context`, `useToastContext` hook or `useToast` hook. **API:** | Property | Type | Description | |----------|------|-------------| | `getCount` | `() => number` | The total number of toasts | | `getToasts` | `() => ToastProps[]` | The toasts | | `subscribe` | `(callback: (toasts: Options[]) => void) => VoidFunction` | Subscribe to the toast group |