Ark UI Logo
Components
Toast

Toast

A message that appears on the screen to provide feedback on an action.

Loading...

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.

const toaster = createToaster({
  placement: 'bottom-end',
  overlap: true,
  gap: 24,
})

Examples

Here's an example of creating a toast using the toast.create method.

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 (
    <div>
      <button
        type="button"
        onClick={() =>
          toaster.create({
            title: 'Toast Title',
            description: 'Toast Description',
            type: 'info',
          })
        }
      >
        Add Toast
      </button>
      <Toaster toaster={toaster}>
        {(toast) => (
          <Toast.Root key={toast.id}>
            <Toast.Title>{toast.title}</Toast.Title>
            <Toast.Description>{toast.description}</Toast.Description>
            <Toast.CloseTrigger>
              <XIcon />
            </Toast.CloseTrigger>
          </Toast.Root>
        )}
      </Toaster>
    </div>
  )
}

Update Toast

To update a toast, use the toast.update method.

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<string>(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 (
    <div>
      <button type="button" onClick={createToast}>
        Create Toast
      </button>
      <button type="button" onClick={updateToast}>
        Update Toast
      </button>
      <Toaster toaster={toaster}>
        {(toast) => (
          <Toast.Root key={toast.id}>
            <Toast.Title>{toast.title}</Toast.Title>
            <Toast.Description>{toast.description}</Toast.Description>
          </Toast.Root>
        )}
      </Toaster>
    </div>
  )
}

Action

To add an action to a toast, use the toast.action property.

import { Toast, Toaster, createToaster } from '@ark-ui/react/toast'

const toaster = createToaster({
  placement: 'bottom-end',
  gap: 24,
})

export const Action = () => {
  return (
    <div>
      <button
        type="button"
        onClick={() =>
          toaster.create({
            title: 'Toast Title',
            description: 'Toast Description',
            type: 'info',
            action: {
              label: 'Subscribe',
              onClick: () => {
                console.log('Subscribe')
              },
            },
          })
        }
      >
        Add Toast
      </button>
      <Toaster toaster={toaster}>
        {(toast) => (
          <Toast.Root key={toast.id}>
            <Toast.Title>{toast.title}</Toast.Title>
            <Toast.Description>{toast.description}</Toast.Description>
            {toast.action && <Toast.ActionTrigger>{toast.action?.label}</Toast.ActionTrigger>}
          </Toast.Root>
        )}
      </Toaster>
    </div>
  )
}

Styling guide

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
[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.

[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.

@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

Root

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[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

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

CloseTrigger

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Description

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Title

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Toaster

PropDefaultType
toaster
CreateToasterReturn

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
dir'ltr'
'ltr' | 'rtl'

The document's text/writing direction.

getRootNode
() => Node | ShadowRoot | Document

A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.