The Toast component provides temporary notifications that appear at the edge of the screen. It supports multiple variants, actions, promise handling, and anchored positioning.
Installation
npx shadcn@latest add @eo-n/toast
Install dependencies
npm install @base-ui/react class-variance-authority lucide-react
Copy component code
Copy and paste the component code into your project at components/ui/toast.tsx. Due to the length of the component, please refer to the source repository for the complete implementation.
Update imports
Update the import paths to match your project setup.
Setup Provider
Add the ToastProvider to your app layout:
import { ToastProvider } from "@/components/ui/toast";
<html lang="en">
<body>
<ToastProvider>{children}</ToastProvider>
</body>
</html>
Show Toasts
Use toastManager to display toasts from anywhere in your app:
import { toastManager } from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
export default function Example() {
return (
<Button
onClick={() => {
toastManager.add({
title: "Profile Updated",
description: "Your changes have been saved.",
});
}}
>
Save Changes
</Button>
);
}
The toastManager can be called from anywhere, including outside of React components. No hooks required.
Examples
Basic Toast
import { toastManager } from "@/components/ui/toast";
toastManager.add({
title: "Success",
description: "Your action completed successfully.",
});
Toast Variants
// Success
toastManager.add({
type: "success",
title: "Changes saved",
description: "Your profile has been updated.",
});
// Error
toastManager.add({
type: "error",
title: "Error occurred",
description: "Unable to save your changes.",
});
// Warning
toastManager.add({
type: "warning",
title: "Warning",
description: "Your session will expire soon.",
});
// Info
toastManager.add({
type: "info",
title: "Tip",
description: "You can customize your workspace in settings.",
});
// Loading
toastManager.add({
type: "loading",
title: "Processing",
description: "Please wait while we process your request.",
});
With Action Button
import { toastManager } from "@/components/ui/toast";
toastManager.add({
title: "File deleted",
description: "Your file has been moved to trash.",
actionText: "Undo",
onAction: () => {
console.log("Undo action triggered");
},
});
Promise-based Toast
Automatically show loading, success, or error states:
import { toastManager } from "@/components/ui/toast";
const uploadPromise = uploadFile(file);
toastManager.promise(uploadPromise, {
loading: {
title: "Uploading...",
description: "Please wait while we upload your file.",
},
success: (data) => ({
title: "Upload complete",
description: `${data.filename} has been uploaded successfully.`,
}),
error: (error) => ({
title: "Upload failed",
description: error.message,
}),
});
Custom Duration
toastManager.add({
title: "Quick notification",
timeout: 2000, // 2 seconds
});
// Persistent (won't auto-dismiss)
toastManager.add({
title: "Important message",
timeout: null,
});
Anchored Toast
Anchor toasts to specific elements (useful for copy-to-clipboard feedback):
import { AnchoredToastProvider, ToastProvider } from "@/components/ui/toast";
<ToastProvider>
<AnchoredToastProvider>{children}</AnchoredToastProvider>
</ToastProvider>
import { useRef } from "react";
import { anchoredToastManager } from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
export default function CopyButton() {
const buttonRef = useRef<HTMLButtonElement>(null);
function handleCopy() {
navigator.clipboard.writeText("Hello world");
anchoredToastManager.add({
description: "Copied to clipboard!",
positionerProps: {
anchor: buttonRef.current,
sideOffset: 8,
},
timeout: 1500,
});
}
return (
<Button ref={buttonRef} onClick={handleCopy}>
Copy
</Button>
);
}
Custom Position
<ToastProvider position="top-center">
{children}
</ToastProvider>
Available positions:
top-center
top-left
top-right
bottom-center (default)
bottom-left
bottom-right
Rich Colors
Enable variant-specific background colors:
<ToastProvider richColors>
{children}
</ToastProvider>
With Close Button
<ToastProvider closeButton>
{children}
</ToastProvider>
Component API
ToastProvider
position
'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right'
Where to display toasts on the screen. Defaults to bottom-right.
Enable variant-specific background colors. Defaults to false.
Show a close button on each toast. Defaults to false.
Maximum number of toasts to display at once.
toastManager.add()
type
'default' | 'success' | 'error' | 'warning' | 'info' | 'loading'
The visual variant of the toast.
Text for the action button.
Callback when action button is clicked.
Auto-dismiss delay in milliseconds. Pass null to disable auto-dismiss. Defaults to 5000.
Callback when toast is dismissed.
toastManager.promise()
Toast options to show while loading.
success
ToastOptions | ((data: T) => ToastOptions)
Toast options to show on success.
error
ToastOptions | ((error: Error) => ToastOptions)
Toast options to show on error.
Accessibility
The Toast component includes:
- ARIA live regions for screen reader announcements
- Keyboard navigation (ESC to dismiss)
- Focus management
- Swipe gestures for touch devices
- Proper semantic markup
Reference
Built on top of Base UI Toast.