Toast
Hand-drawn toasts that stack, expand on hover, and swipe away.
Types
Paper texturesThe pattern takes the toast type colour
Plain
With action
StackingHover the stack to expand it
Installation
Add Toast with the shadcn CLI.
npx shadcn@latest add https://sketchcn.chuwii.com/r/toast.json
Examples
Mount the Toaster once, then call toast from anywhere.
Setup

Render <Toaster /> once near the root of your app. It portals its own viewport, so no other wiring is needed.

import { Toaster } from "@/components/ui/toast";

export function App({ children }: { children: React.ReactNode }) {
  return (
    <>
      {children}
      <Toaster />
    </>
  );
}
Save confirmation
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function SaveButton() {
  return (
    <Button
      onClick={() =>
        toast.add({
          type: "success",
          title: "Sketch saved",
          description: "Everyone on the board can see it now.",
        })
      }
    >
      Save sketch
    </Button>
  );
}
Undo an action
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function DeleteButton() {
  return (
    <Button
      variant="destructive"
      onClick={() =>
        toast.add({
          title: "Sketch deleted",
          description: "It moves to the bin for 30 days.",
          actionProps: { children: "Undo", onClick: restoreSketch },
        })
      }
    >
      Delete sketch
    </Button>
  );
}
Paper texture
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function PublishButton() {
  return (
    <Button
      onClick={() =>
        toast.add({
          type: "warning",
          title: "Running low on space",
          description: "You have used 92% of your workspace.",
          data: { variant: "plus" },
        })
      }
    >
      Publish
    </Button>
  );
}
Promise
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function ExportButton() {
  return (
    <Button
      onClick={() =>
        toast.promise(exportSketch(), {
          loading: "Exporting sketch",
          success: "Export ready",
          error: "Export failed",
        })
      }
    >
      Export PNG
    </Button>
  );
}
Stays until dismissed
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export function ConnectionToast() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.add({
          type: "warning",
          title: "You are offline",
          description: "Changes are queued until the connection is back.",
          timeout: 0,
          priority: "high",
        })
      }
    >
      Go offline
    </Button>
  );
}