Files
initiative/apps/web/src/components/toast.tsx
Lukas 36768d3aa1 Upgrade Biome to 2.4.7 and enable 54 additional lint rules
Add rules covering bug prevention (noLeakedRender, noFloatingPromises,
noImportCycles, noReactForwardRef), security (noScriptUrl, noAlert),
performance (noAwaitInLoops, useTopLevelRegex), and code style
(noNestedTernary, useGlobalThis, useNullishCoalescing, useSortedClasses,
plus ~40 more). Fix all violations: extract top-level regex constants,
guard React && renders with boolean coercion, refactor nested ternaries,
replace window with globalThis, sort Tailwind classes, and introduce
expectDomainError test helper to eliminate conditional expects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 14:25:09 +01:00

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-foreground text-sm">{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,
);
}