OpenVuln / src /components /ConfirmDialog.tsx
zRzRzRzRzRzRzR
feat: sync latest OpenVuln frontend
d22337b
Raw
History Blame Contribute Delete
2.01 kB
import { useEffect, useRef } from "react";
import { Button } from "./Button";
export function ConfirmDialog({
open,
title,
body,
confirmLabel = "Confirm",
danger = false,
busy = false,
onConfirm,
onCancel,
}: {
open: boolean;
title: string;
body: string;
confirmLabel?: string;
danger?: boolean;
busy?: boolean;
onConfirm: () => void;
onCancel: () => void;
}) {
const cancelRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
if (!open) return;
cancelRef.current?.focus();
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onCancel();
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [open, onCancel]);
if (!open) return null;
return (
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"
role="dialog"
aria-modal="true"
aria-labelledby="confirm-title"
onMouseDown={(e) => {
if (e.target === e.currentTarget) onCancel();
}}
>
<div className="w-full max-w-md rounded-md border border-line bg-surface-raised p-5 shadow-lg">
<h2 id="confirm-title" className="text-base font-semibold text-ink">
{title}
</h2>
<p className="mt-2 text-sm leading-relaxed text-ink-secondary">{body}</p>
<div className="mt-5 flex justify-end gap-2">
<button
ref={cancelRef}
type="button"
onClick={onCancel}
disabled={busy}
className="inline-flex h-9 items-center justify-center rounded-md border border-line bg-surface-raised px-3.5 text-sm font-medium text-ink hover:bg-surface-sunken focus-ring disabled:opacity-50"
>
Cancel
</button>
<Button variant={danger ? "danger" : "primary"} onClick={onConfirm} disabled={busy}>
{busy ? "Working…" : confirmLabel}
</Button>
</div>
</div>
</div>
);
}