79 lines
2.2 KiB
TypeScript
79 lines
2.2 KiB
TypeScript
import { AlertTriangle, Loader2 } from "lucide-react";
|
|
|
|
interface ConfirmDialogProps {
|
|
open: boolean;
|
|
title: string;
|
|
message: string;
|
|
confirmLabel?: string;
|
|
cancelLabel?: string;
|
|
variant?: "danger" | "warning" | "default";
|
|
isLoading?: boolean;
|
|
onConfirm: () => void;
|
|
onCancel: () => void;
|
|
}
|
|
|
|
const variantStyles = {
|
|
danger: {
|
|
icon: "text-red-400 bg-red-500/10",
|
|
button: "bg-red-600 hover:bg-red-500",
|
|
},
|
|
warning: {
|
|
icon: "text-yellow-400 bg-yellow-500/10",
|
|
button: "bg-yellow-600 hover:bg-yellow-500",
|
|
},
|
|
default: {
|
|
icon: "text-cyan-400 bg-cyan-500/10",
|
|
button: "bg-cyan-600 hover:bg-cyan-500",
|
|
},
|
|
};
|
|
|
|
export default function ConfirmDialog({
|
|
open,
|
|
title,
|
|
message,
|
|
confirmLabel = "Confirm",
|
|
cancelLabel = "Cancel",
|
|
variant = "default",
|
|
isLoading = false,
|
|
onConfirm,
|
|
onCancel,
|
|
}: ConfirmDialogProps) {
|
|
if (!open) return null;
|
|
|
|
const styles = variantStyles[variant];
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
|
|
<div className="w-full max-w-md rounded-xl border border-gray-800 bg-gray-900 p-6 shadow-2xl">
|
|
<div className="flex items-start gap-4">
|
|
<div className={`rounded-lg p-2 ${styles.icon}`}>
|
|
<AlertTriangle className="h-6 w-6" />
|
|
</div>
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-white">{title}</h3>
|
|
<p className="mt-1 text-sm text-gray-400">{message}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-6 flex justify-end gap-3">
|
|
<button
|
|
onClick={onCancel}
|
|
disabled={isLoading}
|
|
className="rounded-lg border border-gray-700 px-4 py-2 text-sm font-medium text-gray-300 transition-colors hover:bg-gray-800 disabled:opacity-50"
|
|
>
|
|
{cancelLabel}
|
|
</button>
|
|
<button
|
|
onClick={onConfirm}
|
|
disabled={isLoading}
|
|
className={`flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50 ${styles.button}`}
|
|
>
|
|
{isLoading && <Loader2 className="h-4 w-4 animate-spin" />}
|
|
{confirmLabel}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|