Skip to content
Esc
navigateopen⌘Jpreview
On this page

Toast

A succinct message that is displayed temporarily.

import { Button } from '@/components/ui/button';
import { toast, Toaster, ToastProvider } from '@/components/ui/toast';

export default function ToastDemo() {
  return (
    <ToastProvider>
      <Button
        variant="outline"
        onClick={() =>
          toast('Scheduled: Catch up', {
            description: 'Friday, February 10 at 5:57 PM',
          })
        }
      >
        Show toast
      </Button>
      <Toaster />
    </ToastProvider>
  );
}

Install

npx shadcn@latest add @madeui/toast

Usage

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

// 1. Wrap your app in <ToastProvider> and mount <Toaster /> once (e.g. in the root layout).
// 2. Call `toast` from anywhere — components, event handlers, stores:
toast('Saved', { description: 'Your changes were saved.' });
toast.success('Deployed');
toast.error('Could not save');

Stacking

Toasts pile up behind the newest one (up to the provider’s limit, 3 by default). Hovering or focusing the stack expands it to show every toast. Trigger the demo above a few times in a row to see it.

Swipe to dismiss

Drag a toast down or right (touch or mouse) to dismiss it. Configure with <Toaster swipeDirection={['down', 'right']} /> — any of 'up' | 'down' | 'left' | 'right', or a single value.

Promise

toast.promise shows a loading toast, then updates it in place when the promise settles.

import { Button } from '@/components/ui/button';
import { toast, Toaster, ToastProvider } from '@/components/ui/toast';

function save() {
  return new Promise<void>((resolve) => setTimeout(resolve, 2000));
}

export default function ToastPromise() {
  return (
    <ToastProvider>
      <Button
        variant="outline"
        onClick={() =>
          toast.promise(save(), {
            loading: 'Saving…',
            success: 'Changes saved',
            error: 'Could not save',
          })
        }
      >
        Save with toast.promise
      </Button>
      <Toaster />
    </ToastProvider>
  );
}

Duration

import { Button } from '@/components/ui/button';
import { Toaster, ToastProvider, useToast } from '@/components/ui/toast';

function DemoButton() {
  const toast = useToast();
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.add({
          title: 'Sticky toast',
          description: 'Stays for 10 seconds.',
          timeout: 10000,
        })
      }
    >
      Show sticky toast
    </Button>
  );
}

export default function ToastDuration() {
  return (
    <ToastProvider>
      <DemoButton />
      <Toaster />
    </ToastProvider>
  );
}

Types

toast.success and toast.error set a type on the toast (mirrored as data-type on the rendered element). Styling is identical across types out of the box — since you own components/ui/toast.tsx, add a [data-type="…"] condition to styles.root to color-code them.

import * as stylex from '@stylexjs/stylex';

import { Button } from '@/components/ui/button';
import { toast, Toaster, ToastProvider } from '@/components/ui/toast';
import { space } from '@/lib/constants.stylex';

export default function ToastTypes() {
  return (
    <ToastProvider>
      <div {...stylex.props(styles.row)}>
        <Button
          variant="outline"
          onClick={() => toast('Event created', { description: 'Team sync at 3 PM.' })}
        >
          Default
        </Button>
        <Button
          variant="outline"
          onClick={() => toast.success('Changes saved')}
        >
          Success
        </Button>
        <Button
          variant="outline"
          onClick={() => toast.error('Could not save', { description: 'Try again.' })}
        >
          Error
        </Button>
      </div>
      <Toaster />
    </ToastProvider>
  );
}

const styles = stylex.create({
  row: {
    display: 'flex',
    flexWrap: 'wrap',
    gap: space.s2,
  },
});

Action

Pass actionProps to render an action button inside the toast.

import { Button } from '@/components/ui/button';
import { toast, Toaster, ToastProvider } from '@/components/ui/toast';

export default function ToastAction() {
  return (
    <ToastProvider>
      <Button
        variant="outline"
        onClick={() =>
          toast('Message archived', {
            actionProps: {
              children: 'Undo',
              onClick: () => toast('Message restored'),
            },
          })
        }
      >
        Archive message
      </Button>
      <Toaster />
    </ToastProvider>
  );
}

Position

The stack’s screen position lives in Toaster’s own styles; override it with the style prop, same as any other component in this library.

import * as stylex from '@stylexjs/stylex';

import { Button } from '@/components/ui/button';
import { toast, Toaster, ToastProvider } from '@/components/ui/toast';
import { space } from '@/lib/constants.stylex';

export default function ToastPosition() {
  return (
    <ToastProvider>
      <Button
        variant="outline"
        onClick={() => toast('Synced to top left')}
      >
        Show toast
      </Button>
      <Toaster style={styles.topLeft} />
    </ToastProvider>
  );
}

const styles = stylex.create({
  topLeft: {
    bottom: null,
    right: null,
    left: space.s4,
    top: space.s4,
  },
});

API reference

Built on Base UI Toast. The tables below cover the props this library adds or changes — every other prop is forwarded to the underlying Base UI part; see the Base UI Toast API reference for the full list.

toast(title, options?)

Imperative API backed by a module-level toast manager — no hook needed, works outside React. useToast() remains available for the hook form (useToast().add({ … })).

Prop Type Default Description
title ReactNode Toast heading.
description ReactNode Supporting text.
timeout number Auto-dismiss delay in ms (Base UI default: 5000).
type string Toast type; toast.success / toast.error set it for you.
actionProps object Props for the action button (e.g. { children: 'Undo', onClick }).

Also available: toast.promise(promise, { loading, success, error }), toast.update(id, options), toast.close(id).

Toaster

Prop Type Default Description
swipeDirection Direction | Direction[] ['down', 'right'] Direction(s) a toast can be swiped to dismiss.

Toaster renders the styled toast stack; to change its look, edit components/ui/toast.tsx directly — you own the source.

Was this page helpful?