shadcn.io is not affiliated with official shadcn/ui
Shadcn Toast for React and Tailwind
Provides feedback on an action.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/toast.jsonpnpm dlx shadcn@latest add https://kit.dev/r/toast.jsonnpx shadcn@latest add https://kit.dev/r/toast.jsonyarn shadcn@latest add https://kit.dev/r/toast.jsonThis component depends on Button and Spinner. Install them first if you haven't already.
Install the following dependencies:
bun add @ark-ui/react tailwind-variants lucide-reactpnpm add @ark-ui/react tailwind-variants lucide-reactnpm install @ark-ui/react tailwind-variants lucide-reactyarn add @ark-ui/react tailwind-variants lucide-reactAdd the following to your globals.css.
:root {
--destructive-foreground: var(--color-red-700);
--info: var(--color-blue-500);
--info-foreground: var(--color-blue-700);
--success: var(--color-emerald-500);
--success-foreground: var(--color-emerald-700);
--warning: var(--color-amber-500);
--warning-foreground: var(--color-amber-700);
}
.dark {
--destructive-foreground: var(--color-red-400);
--info: var(--color-blue-500);
--info-foreground: var(--color-blue-400);
--success: var(--color-emerald-500);
--success-foreground: var(--color-emerald-400);
--warning: var(--color-amber-500);
--warning-foreground: var(--color-amber-400);
}Copy and paste the following code into your project.
"use client";
import { Portal } from "@ark-ui/react/portal";
import {
Toast as ArkToast,
Toaster as ArkToaster,
createToaster,
useToastContext,
} from "@ark-ui/react/toast";
import {
CircleAlertIcon,
CircleCheckIcon,
InfoIcon,
TriangleAlertIcon,
XIcon,
} from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
export { createToaster } from "@ark-ui/react/toast";
export const useToast = useToastContext;
export const toast = createToaster({
max: 3,
overlap: true,
placement: "bottom-end",
});
interface ToasterProps
extends Omit<
React.ComponentProps<typeof ArkToaster>,
"toaster" | "children"
> {
/**
* Toaster instance
*/
toaster?: React.ComponentProps<typeof ArkToaster>["toaster"];
}
export const Toaster = (props: ToasterProps) => {
const { toaster: toasterInstance = toast, className, style, ...rest } = props;
return (
<Portal>
<ArkToaster
className={cn(
"w-[calc(100%-var(--viewport-offset-left))] sm:w-(--width)",
"data-[align=center]:left-[calc(var(--viewport-offset-right)/2)]!",
"sm:data-[align=center]:w-full",
className
)}
data-slot="toaster"
style={{ "--width": "356px", ...style } as React.CSSProperties}
toaster={toasterInstance}
{...rest}
>
{(toastItem) => <ToastItem toast={toastItem} />}
</ArkToaster>
</Portal>
);
};
const TOAST_ICONS = {
error: <CircleAlertIcon />,
info: <InfoIcon />,
loading: <Spinner />,
success: <CircleCheckIcon />,
warning: <TriangleAlertIcon />,
} as const;
interface ToastItemProps extends React.ComponentProps<typeof ArkToast.Root> {
/**
* The toast item data
*/
toast: ArkToast.Options;
}
export const ToastItem = (props: ToastItemProps) => {
const { toast: toastData, className, ...rest } = props;
const ToastIcon = toastData.type
? TOAST_ICONS[toastData.type as keyof typeof TOAST_ICONS]
: null;
const isExplicitClosable = toastData.closable === false;
return (
<ArkToast.Root
className={cn(
"z-(--z-index) translate-x-(--x) translate-y-(--y)",
"relative",
"w-[calc(100%-var(--viewport-offset-left))] sm:w-(--width)",
"px-3.5 py-3",
"flex items-start justify-between gap-1.5",
"bg-popover",
"select-none text-card-foreground text-sm",
"rounded-lg border shadow-lg/5",
"scale-(--scale) opacity-(--opacity)",
"transition-all duration-250 will-change-[translate,opacity,scale]",
"ease-[cubic-bezier(0.21,1.02,0.73,1)]",
"data-[state=closed]:transition-[translate,scale,opacity]",
"data-[state=closed]:duration-[300ms,300ms,150ms]",
"data-[state=closed]:ease-[cubic-bezier(0.06,0.71,0.55,1)]",
"motion-reduce:transition-none!",
className
)}
data-slot="toast"
{...rest}
>
<div className="flex items-start gap-1.5">
<div
className={cn(
"in-data-[type=warning]:text-warning",
"in-data-[type=success]:text-success",
"in-data-[type=error]:text-destructive",
"in-data-[type=info]:text-info",
"[&_svg]:pointer-events-none [&_svg]:h-lh [&_svg]:w-4 [&_svg]:shrink-0"
)}
data-slot="toast-icon"
>
{ToastIcon}
</div>
<div className="flex flex-col gap-0.5">
<ArkToast.Title
className="font-medium text-sm"
data-slot="toast-title"
>
{toastData.title}
</ArkToast.Title>
{!!toastData.description && (
<ArkToast.Description
className="text-muted-foreground text-sm"
data-slot="toast-description"
>
{toastData.description}
</ArkToast.Description>
)}
</div>
</div>
<div className="flex items-center gap-2">
{!!toastData.action && (
<ArkToast.ActionTrigger
asChild
data-slot="toast-action-trigger"
onClick={toastData.action.onClick}
>
<Button size="sm" variant="secondary">
{toastData.action.label}
</Button>
</ArkToast.ActionTrigger>
)}
{!isExplicitClosable && (
<ArkToast.CloseTrigger asChild data-slot="toast-close-trigger">
<Button
aria-label="Close"
className="opacity-64 hover:opacity-100"
size="icon-xs"
variant="ghost"
>
<XIcon />
</Button>
</ArkToast.CloseTrigger>
)}
</div>
</ArkToast.Root>
);
};Update the import paths to match your project setup.
Anatomy
ToastItem
├── ToastGroup
├── ToastTitle
├── ToastDescription
├── ToastActionTrigger
└── ToastCloseTriggerUsage
import { Button } from "@/components/ui/button";
import { createToaster, Toaster } from "@/components/ui/toast";const toast = createToaster({
overlap: true,
placement: "bottom-end",
});
const ToastDemo = () => (
<>
<Toaster toaster={toast} />
<Button
onClick={() => {
toast.create({
description: "Tuesday, February 10, 2026 at 10:00 AM.",
title: "Event has been created.",
});
}}
variant="outline"
>
Toast
</Button>
</>
);Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
Demos
Action
Closable
Dedupe
Duration
Placement
Promise
Variants
API Reference
ToastItem
div
PropType
AttributeType
CSS variableType
ToastTitle
div
PropType
CSS variableType
ToastDescription
div
PropType
CSS variableType
ToastActionTrigger
button
PropType
CSS variableType
ToastCloseTrigger
button
PropType
CSS variableType
toast
AttributeType
Toaster
div
PropType
AttributeType
CSS variableType