Previously the button silently did nothing for creatures whose bestiary source wasn't loaded. Now it reports how many were skipped and why. Also keeps the roll-all button visible (but disabled) when there's nothing left to roll, and moves toasts to the bottom-left corner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
import { X } from "lucide-react";
|
|
import { useEffect } from "react";
|
|
import { createPortal } from "react-dom";
|
|
import { Button } from "./ui/button.js";
|
|
|
|
interface ToastProps {
|
|
message: string;
|
|
progress?: number;
|
|
onDismiss: () => void;
|
|
autoDismissMs?: number;
|
|
}
|
|
|
|
export function Toast({
|
|
message,
|
|
progress,
|
|
onDismiss,
|
|
autoDismissMs,
|
|
}: ToastProps) {
|
|
useEffect(() => {
|
|
if (autoDismissMs === undefined) return;
|
|
const timer = setTimeout(onDismiss, autoDismissMs);
|
|
return () => clearTimeout(timer);
|
|
}, [autoDismissMs, onDismiss]);
|
|
|
|
return createPortal(
|
|
<div className="fixed bottom-4 left-4 z-50">
|
|
<div className="flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3 shadow-lg">
|
|
<span className="text-sm text-foreground">{message}</span>
|
|
{progress !== undefined && (
|
|
<div className="h-2 w-24 overflow-hidden rounded-full bg-muted">
|
|
<div
|
|
className="h-full rounded-full bg-primary transition-all"
|
|
style={{ width: `${Math.round(progress * 100)}%` }}
|
|
/>
|
|
</div>
|
|
)}
|
|
<Button
|
|
variant="ghost"
|
|
size="icon-sm"
|
|
onClick={onDismiss}
|
|
className="text-muted-foreground"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</Button>
|
|
</div>
|
|
</div>,
|
|
document.body,
|
|
);
|
|
}
|