Skip to content
Components

Toaster

Swipeable notifications with molded Caps surfaces. Dismiss the message, not the work.

TS
import { … } from "@fungi.computer/caps/components/toaster";

Hero

TSX
import { Alert } from "@fungi.computer/caps/components/alert";
import { Button } from "@fungi.computer/caps/components/button";
import { Toaster, toast } from "@fungi.computer/caps/components/toaster";
export default function Hero() {
return (
<div className="flex flex-col gap-sm">
<Toaster />
<Button
size="sm"
onClick={() =>
toast.custom(() => (
<Alert
tone="success"
title="Saved to the spore log"
description="Your chanterelle patch is on the map."
/>
))
}
>
Save the patch
</Button>
</div>
);
}

Dismissible

TSX
import { Alert } from "@fungi.computer/caps/components/alert";
import { Button } from "@fungi.computer/caps/components/button";
import { IconButton } from "@fungi.computer/caps/components/icon-button";
import { Toaster, toast } from "@fungi.computer/caps/components/toaster";
import { useId } from "react";
export default function Dismissible() {
const id = useId();
return (
<div className="flex flex-col gap-sm">
<Toaster />
<Button
size="sm"
variant="outline"
onClick={() =>
toast.custom(
() => (
<Alert
tone="error"
title="Upload failed"
description="The photo is still on your device."
action={
<IconButton
aria-label="Dismiss"
icon={
<svg
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
>
<path d="M4 4l8 8M12 4l-8 8" strokeWidth="1.5" />
</svg>
}
onClick={() => toast.dismiss(id)}
/>
}
/>
),
{ id, duration: Infinity },
)
}
>
Simulate a failed upload
</Button>
</div>
);
}