import { ReactNode, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import * as Dialog from "@/components/dialog/Dialog"; import { Button } from "@/components/buttons/Button"; import { DialogHeading } from "@/components/dialog/DialogHeading"; import { DialogDescription } from "@/components/dialog/DialogDescription"; import { DialogActions } from "@/components/dialog/DialogActions"; // ConfirmModal is the shared in-app confirmation modal — a left-aligned // title + (optionally multi-line) description with Cancel / confirm buttons // in the footer. It's the in-window counterpart to a native confirm dialog. // // Most call sites should not render this directly: use the imperative // `useConfirm()` from DialogContext (`await confirm({...})`), which mounts a // single instance at the provider level. Render ConfirmModal yourself only // when you need bespoke control over its open/busy lifecycle. type ConfirmModalProps = { open: boolean; title: ReactNode; description: ReactNode; /** Confirm button label. */ confirmLabel: string; /** Cancel button label; defaults to the shared "Cancel" string. */ cancelLabel?: string; /** Use the destructive (red) confirm button variant. */ danger?: boolean; /** Disable the buttons (and ignore dismiss) while an action runs. */ busy?: boolean; onConfirm: () => void; onCancel: () => void; }; export const ConfirmModal = ({ open, title, description, confirmLabel, cancelLabel, danger = false, busy = false, onConfirm, onCancel, }: ConfirmModalProps) => { const { t } = useTranslation(); // Retain the last shown content so it stays rendered through Radix's // close animation instead of blanking out the instant the caller clears // its state on close. type Snapshot = Pick & { cancelLabel: string; }; const [snapshot, setSnapshot] = useState(null); const resolvedCancel = cancelLabel ?? t("common.cancel"); useEffect(() => { if (open) { setSnapshot({ title, description, confirmLabel, cancelLabel: resolvedCancel, danger }); } }, [open, title, description, confirmLabel, resolvedCancel, danger]); const view = open ? { title, description, confirmLabel, cancelLabel: resolvedCancel, danger } : snapshot; return ( { if (!next && !busy) onCancel(); }} > e.preventDefault()} > {view && (
{view.title} {view.description}
)}
); };