Toast
A stacked toast manager built on Base UI with promise helpers, inline actions, and optional expandable details.
Installation
npx shadcn@latest add https://ui.jarv.is/r/toast.jsonUsage
App root setup
Render one Toaster near your React app root, then call toast from any client component.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Toaster } from "@/components/ui/toast";
import { App } from "./app";
import "./index.css";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
<Toaster closeButton richColors position="bottom-right" />
</StrictMode>,
);Basic feedback
Use basic typed toasts for routine product feedback.
import { toast } from "@/components/ui/toast";
export function SaveButton() {
return <button onClick={() => toast.success("Saved")}>Save</button>;
}Descriptions
Add descriptions when the user needs context, not just confirmation.
toast.success("Deployment complete", {
description: "Production is now serving build 1042.",
});
toast.warning("Verification paused", {
description: "A required secret is missing for the production smoke test.",
});Actions
Use actions for reversible operations or next steps.
toast.info("Invite copied", {
action: {
label: "Undo",
onClick: () => {
void restoreInvite(inviteId);
},
},
});Promise states
Use toast.promise when a toast should track an async operation from loading to final state.
await toast.promise(publishRelease(), {
loading: {
title: "Publishing release",
description: "Uploading assets and warming the deployment.",
},
success: (release) => ({
title: "Release published",
description: `${release.version} is live in production.`,
}),
error: (error) => ({
title: "Publish failed",
description: error instanceof Error ? error.message : "Try again from the releases page.",
}),
});Error details
Error toasts with string descriptions include a copy-details button by default. Set
hideCopyButton when copying the description is not useful.
toast.error("Upload failed", {
description:
"The source map upload hit a permissions error. Re-authenticate the CI token and retry.",
closeButton: true,
});Expandable details
Use expandable content for diagnostics, checklists, or secondary detail that should not dominate the collapsed toast.
toast.warning("Verification paused", {
description: "A required secret is missing for the production smoke test.",
actionLayout: "stacked-end",
actionVariant: "outline",
action: {
label: "Open checklist",
onClick: () => openDeploymentChecklist(),
},
expandableContent: (
<ul>
<li>`VERCEL_TOKEN` is not configured for this environment.</li>
<li>`POSTHOG_API_KEY` is missing from the deployment step.</li>
<li>Smoke tests were skipped after the build artifact upload.</li>
</ul>
),
});Manual dismissal
Use a longer-lived loading toast when work crosses screens, then dismiss it explicitly.
const toastId = toast.loading("Syncing workspace", {
description: "This can take a few seconds.",
duration: 30_000,
});
try {
await syncWorkspace();
toast.success("Workspace synced");
} finally {
toast.dismiss(toastId);
}API
Refer to the Base UI documentation for more details.