/** * The destructive-action confirmation (milestone 23, ruling 5), which replaces * every `window.confirm` call in the app. * * `role="alertdialog"` rather than `dialog`: the message is the reason the * dialog exists, so it is announced with the dialog instead of after it. The * overlay is deliberately not dismissable — a delete needs an explicit answer, * and a stray outside click is not one. Escape still cancels. */ import type { ReactNode } from "react"; import * as stylex from "@stylexjs/stylex"; import { Dialog as AriaDialog, Heading, Modal, ModalOverlay } from "react-aria-components"; import { colors, layers, metrics } from "./tokens.stylex"; import { styles as shared } from "./styles"; interface Props { isOpen: boolean; title: string; /** The full sentence the operator reads before confirming; names the entity. */ message: string; confirmLabel: string; /** * Stands in for the confirm action when the write can no longer land, the way * an open edit dialog drops its Save. Closing the dialog instead would throw * focus at a control that is now disabled and say nothing about why, so the * question stays on screen and only the answer that would fail is withdrawn. * Cancel is always live. */ lock?: ReactNode; onConfirm: () => void; onCancel: () => void; } const styles = stylex.create({ overlay: { position: "fixed", inset: 0, zIndex: layers.confirm, display: "flex", alignItems: "center", justifyContent: "center", padding: "1rem", backgroundColor: "rgba(0, 0, 0, 0.4)", }, panel: { width: "100%", maxWidth: "26rem", borderRadius: "0.5rem", borderWidth: 1, borderStyle: "solid", borderColor: colors.dangerBorder, backgroundColor: colors.surfaceRaised, color: colors.text, padding: "1.5rem", boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", }, body: { outlineStyle: "none", }, title: { fontSize: "1.125rem", lineHeight: "1.75rem", fontWeight: 600, }, message: { marginTop: "0.5rem", fontSize: "0.875rem", lineHeight: "1.25rem", color: colors.textMuted, }, actions: { display: "flex", justifyContent: "flex-end", gap: "0.5rem", marginTop: "1.5rem", }, dangerButton: { cursor: { default: "pointer", ":disabled": "not-allowed" }, borderRadius: metrics.radius, borderStyle: "none", backgroundColor: colors.danger, color: colors.primaryText, paddingInline: "0.75rem", paddingBlock: "0.375rem", fontSize: "0.875rem", lineHeight: "1.25rem", fontWeight: 500, }, }); export default function ConfirmDialog({ isOpen, title, message, confirmLabel, lock, onConfirm, onCancel }: Props) { return ( { if (!open) onCancel(); }} className={() => stylex.props(styles.overlay).className ?? ""} > stylex.props(styles.panel).className ?? ""}> {title}

{message}

{lock === undefined ? ( ) : ( lock )}
); }