Overlays
DiscardChangesDialog
An alert dialog that asks the user to confirm throwing away unsaved edits.
Guidelines#
Use it for leaving a form or closing an editor while there are unsaved changes. In Max, DiscardChangesProvider (src/contexts/discard-changes-provider.tsx) mounts it once and exposes showDialog(onConfirm, onCancel?). Use that provider rather than mounting your own copy per form.
What you provide:
openandonOpenChange(open).onConfirm(): runs, then the dialog closes.- Optional
onCancel(): runs, then the dialog closes.
Copy (fixed in the component):
- Title: "Discard Changes?"
- Description: "You have unsaved changes. Are you sure you want to discard them? This action cannot be undone."
- Actions: "Cancel" and "Discard Changes".
Anatomy: the standard AlertDialog (overlay, centred content, header, footer). The confirm action is bg-destructive text-white hover:bg-destructive/90, and Cancel uses the outline style.
Behaviour: as an alert dialog it doesn't close on an outside click. Focus goes to Cancel when it opens. Escape only calls onOpenChange(false); the provider treats that as a cancel. Motion is the AlertDialog enter and exit transition.
Don't reuse it to confirm deleting a record or other irreversible actions on data. Use ConfirmDialogProvider / useConfirm with copy that names the object.
Facts#
| Group | Overlays |
|---|---|
| Product | Max |
| Global | window.DigitalCrew.DiscardChangesDialog |
| Source | max-agent: src/components/shared/discard-changes-dialog.tsx |
| Import in the app | import { DiscardChangesDialog } from "@/components/shared/discard-changes-dialog"; |
API#
TypeScript declarations emitted from src/components/shared/discard-changes-dialog.tsx.
interface DiscardChangesDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onConfirm: () => void;
onCancel?: () => void;
}
export declare function DiscardChangesDialog({ open, onOpenChange, onConfirm, onCancel, }: DiscardChangesDialogProps): JSX.Element;Example#
The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.
<div id="root" class="p-6"></div>
<script>
(function () {
var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
function App() {
var s = React.useState(true), open = s[0], setOpen = s[1];
return h("div", { className: "min-h-[272px] space-y-4" },
h("div", { className: "space-y-1.5" },
h(DC.Label, null, "Campaign name"),
h(DC.Input, { defaultValue: "Q4 DACH logistics — CFO outreach" })),
h("div", { className: "space-y-1.5" },
h(DC.Label, null, "Opening line"),
h(DC.Textarea, { rows: 3, defaultValue: "Hi {{first_name}}, saw Northwind is hiring three SDRs in Lyon…" })),
h("div", { className: "flex gap-2" },
h(DC.Button, { variant: "outline", onClick: function () { setOpen(true); } }, "Leave page"),
h(DC.Button, null, "Save changes")),
h(DC.DiscardChangesDialog, { open: open, onOpenChange: setOpen, onConfirm: function () {}, onCancel: function () {} }));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>