1"use client";2import { AlertTriangle, CheckCircle2, Info, X, XCircle } from "lucide-react";3import clsx from "clsx";4import { useToast, type ToastKind } from "@/lib/toast";56const ICON: Record<ToastKind, typeof Info> = { info: Info, success: CheckCircle2, warning: AlertTriangle, error: XCircle };7const STYLE: Record<ToastKind, string> = {8 info: "border-accent/40 bg-surface-1",9 success: "border-ok/50 bg-surface-1",10 warning: "border-warn/60 bg-surface-1",11 error: "border-crit/60 bg-surface-1",12};13const ICON_STYLE: Record<ToastKind, string> = { info: "text-accent", success: "text-ok", warning: "text-warn-ink", error: "text-crit" };1415export function Toaster() {16 const { toasts, dismiss } = useToast();17 if (!toasts.length) return null;18 return (19 <div className="pointer-events-none fixed inset-x-0 bottom-16 z-50 flex flex-col items-center gap-2 px-3 sm:bottom-4 sm:items-end sm:pr-4" aria-live="polite">20 {toasts.map((t) => {21 const Icon = ICON[t.kind];22 return (23 <div key={t.id} role="status" className={clsx("pointer-events-auto flex w-full max-w-sm items-start gap-2 rounded-lg border p-3 shadow-lg", STYLE[t.kind])}>24 <Icon className={clsx("mt-0.5 h-4 w-4 shrink-0", ICON_STYLE[t.kind])} aria-hidden />25 <div className="min-w-0 flex-1">26 <div className="text-sm font-medium break-words">{t.title}</div>27 {t.detail && <div className="text-xs text-ink-2 break-words">{t.detail}</div>}28 {t.requestId && (29 <div className="mt-0.5 font-mono text-[11px] text-ink-3">request_id {t.requestId}</div>30 )}31 </div>32 <button className="btn btn-ghost btn-sm -mr-1 -mt-1 px-1" onClick={() => dismiss(t.id)} aria-label="Dismiss">33 <X className="h-3.5 w-3.5" />34 </button>35 </div>36 );37 })}38 </div>39 );40}41