branch:
Toaster.tsx
1184 bytesRaw
import { createPortal } from "react-dom";
import { useToast } from "../hooks/useToast";
import {
CheckCircleIcon,
WarningCircleIcon,
InfoIcon
} from "@phosphor-icons/react";
const ICONS = {
success: <CheckCircleIcon size={16} className="text-kumo-success shrink-0" />,
error: <WarningCircleIcon size={16} className="text-kumo-danger shrink-0" />,
info: <InfoIcon size={16} className="text-kumo-info shrink-0" />
};
const BORDERS = {
success: "border-green-500/30",
error: "border-kumo-danger",
info: "border-blue-500/30"
};
export function Toaster() {
const { toasts } = useToast();
if (toasts.length === 0) return null;
return createPortal(
<div className="fixed bottom-4 right-4 z-50 flex flex-col items-end gap-2 max-w-sm">
{toasts.map((t) => (
<div
key={t.id}
className={`flex items-start gap-2 px-3 py-2 rounded-lg shadow-lg backdrop-blur-sm bg-kumo-elevated border ${BORDERS[t.kind]} animate-in fade-in slide-in-from-bottom-2 text-sm text-kumo-default`}
>
{ICONS[t.kind]}
<span className="break-words">{t.message}</span>
</div>
))}
</div>,
document.body
);
}