Toast
A short message about something the user just did, in the corner of the screen: Changes saved, Link copied, Upload failed. It closes on its own after a few seconds. Mount one Toaster at the root of the app and call toast({ title }) from an event handler; a Toast element shown with state works too.
Preview
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Changes saved" description="Your project is up to date." />
</Toaster>Usage
When to use
- Confirm an action the user just took, without stopping them: Changes saved, Link copied.
- Offer a quick undo right after an action, when the same undo also exists elsewhere.
When not to use
- An error that blocks work. Show it in the page, next to what failed, for example with Field.
- A question or a decision. Use AlertDialog.
- A state that lasts, such as a failed build. Use Badge.
Variants
variant
default has no icon. success, danger, warning and info add their status icon; the surface stays neutral.
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Changes saved" description="Your project is up to date." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="success" title="Changes saved" description="Your project is up to date." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="danger" title="Changes saved" description="Your project is up to date." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="warning" title="Changes saved" description="Your project is up to date." />
</Toaster>
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="info" title="Changes saved" description="Your project is up to date." />
</Toaster>Examples
Saved
Shown with state here; in an app, call toast({ variant: "success", title: "Changes saved" }).
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="success" title="Changes saved" />
</Toaster>With an action
A longer duration, since the user has to reach the button. The action also lives in the History panel.
import { useState } from "react"
import { Toast, ToastAction, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} title="Project archived" description="It is hidden from your project list." duration={8000} action={<ToastAction altText="Undo from the History panel" onClick={undo}>Undo</ToastAction>} />
</Toaster>Failed
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="danger" title="Upload failed" description="The file is larger than 25 MB." />
</Toaster>Info
import { useState } from "react"
import { Toast, Toaster } from "@/components/ui/toast"
const [open, setOpen] = useState(true)
<Toaster>
<Toast open={open} onOpenChange={setOpen} variant="info" title="Export started" description="The file downloads when it is ready." />
</Toaster>Do and don't
Do
- Confirm an action the user just took: Changes saved, Link copied.
- Write the title in the past tense, and keep it to a few words.
- Mount one Toaster at the root of the app, and call toast() after the action is done.
Don't
- Don't put an error that blocks work in a toast; show it in the page, next to what failed.
- Don't use it for a question or a decision; use AlertDialog.
- Don't put the only way to do something in a toast action; it closes on its own.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| variant | enum | default | success | danger | warning | info | default | default has no icon. success, danger, warning and info add their status icon; the surface stays neutral. |
| title required | node | - | - | What happened, in a few words, past tense: Changes saved. |
| description | node | - | - | One more sentence when the title is not enough. |
| duration | number | - | 4000 | How long it stays, in ms. Make it longer for a toast with an action or a long description. |
| action | node | - | - | One ToastAction, such as Undo. Its altText says where else to do it. |
| dismissible | boolean | - | true | The Dismiss button. Keep it, so a toast never sits over content the user needs. |
| open | boolean | - | - | Set on Toast shown with state. Whether it is shown. Pair it with onOpenChange. |
| onOpenChange | function | - | - | Set on Toast shown with state. Called with false when the time is up, or on Dismiss, Escape or a swipe. |
Slots
| Name | Required | Description |
|---|---|---|
| toaster | yes | One Toaster, mounted once at the root of the app. |
Anatomy
| Part | Description |
|---|---|
| root | Toast: the raised surface with a border, radius-container and shadow-med, px-lg py-md, gap-md between its parts. |
| viewport | Toaster: the stack in the end corner at the bottom of the screen, 384px wide at most, gap-sm between toasts, p-lg from the edges. |
| icon | The status icon for success, danger, warning and info: Tabler icons, 16px, in the status text color, level with the title. |
| title | What happened: 14px medium primary text. |
| description | Optional second line: 13px secondary text. |
| action | ToastAction: one small secondary Button, such as Undo. |
| close | The Dismiss button: a 24px icon button with a Tabler X, 16px, secondary. |
| hitArea | Transparent ::before on the Dismiss button, never smaller than size-target-min. |
Accessibility
Role: status
| Keys | Action |
|---|---|
| F8 | Moves focus to the toasts, so a keyboard user can reach an action or dismiss them. |
| Tab | Moves through the action and the Dismiss button of each toast. |
| Escape | Closes the focused toast. |
- Every toast is announced politely, after what a screen reader is reading. It never takes focus.
- The timer pauses while the pointer is over a toast or focus is inside it, and while the window is in the background.
- A ToastAction needs altText: how to do the same without the toast (Undo from the History panel). A toast can close before anyone reaches it, so the action must also exist elsewhere.
- The status icon is decorative; the title says what happened, so the state never relies on color alone.
- It rises in only when the user allows motion, and fades in otherwise. It closes at once.
Install
npx shadcn add https://werewolf-ui.vercel.app/r/toast.jsonThis also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").