Alert Dialog
A modal confirmation that requires an explicit user response before a destructive action.
Basic
Show codeHide code
import {
AlertDialog,
AlertDialogActions,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogIcon,
AlertDialogIntro,
AlertDialogTitle,
AlertDialogTrigger,
} from "@makeplane/propel/components/alert-dialog";
import { Button } from "@makeplane/propel/components/button";
import { TriangleAlert } from "lucide-react";
export default function BasicDemo() {
return (
<AlertDialog>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogTrigger />}
label="Delete project"
/>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="danger">
<TriangleAlert />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Delete project?</AlertDialogTitle>
<AlertDialogDescription>
This permanently removes the project and all of its work items. This action can't
be undone.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogClose />}
label="Delete"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
);
}Tones
The leading AlertDialogIcon sets the confirmation’s intent through its required tone — danger, warning, info, or success.
Show codeHide code
import {
AlertDialog,
AlertDialogActions,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogIcon,
AlertDialogIntro,
AlertDialogTitle,
AlertDialogTrigger,
} from "@makeplane/propel/components/alert-dialog";
import { Button } from "@makeplane/propel/components/button";
import { CircleCheck, Info, TriangleAlert, Trash2 } from "lucide-react";
export default function TonesDemo() {
return (
<div className="flex flex-wrap items-center gap-3">
<AlertDialog>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogTrigger />}
label="Delete project"
/>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="danger">
<Trash2 />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Delete project?</AlertDialogTitle>
<AlertDialogDescription>
This permanently removes the project and all of its work items. This action
can't be undone.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogClose />}
label="Delete"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
<AlertDialog>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogTrigger />}
label="Archive project"
/>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="warning">
<TriangleAlert />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Archive project?</AlertDialogTitle>
<AlertDialogDescription>
Archiving hides the project from your sidebar. You can restore it later from
workspace settings.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Archive"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
<AlertDialog>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogTrigger />}
label="Transfer ownership"
/>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="info">
<Info />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Transfer ownership?</AlertDialogTitle>
<AlertDialogDescription>
Ownership of this project moves to another member. You'll keep your member
access.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Transfer"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
<AlertDialog>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogTrigger />}
label="Restore project"
/>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="success">
<CircleCheck />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Restore project?</AlertDialogTitle>
<AlertDialogDescription>
This brings the project back to your sidebar with all of its work items intact.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Restore"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
</div>
);
}Open from menu
An alert dialog opened by a menu item is controlled through open / onOpenChange rather than an AlertDialogTrigger.
Show codeHide code
import {
AlertDialog,
AlertDialogActions,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogIcon,
AlertDialogIntro,
AlertDialogTitle,
} from "@makeplane/propel/components/alert-dialog";
import { Button } from "@makeplane/propel/components/button";
import { Menu, MenuContent, MenuItem, MenuTrigger } from "@makeplane/propel/components/menu";
import { TriangleAlert } from "lucide-react";
import * as React from "react";
export default function OpenFromMenuDemo() {
const [confirmOpen, setConfirmOpen] = React.useState(false);
return (
<>
<Menu>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<MenuTrigger />}
label="Project options"
/>
<MenuContent sizing="sm">
<MenuItem label="Rename" />
<MenuItem label="Duplicate" />
<MenuItem onClick={() => setConfirmOpen(true)} label="Delete project…" />
</MenuContent>
</Menu>
<AlertDialog open={confirmOpen} onOpenChange={setConfirmOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="danger">
<TriangleAlert />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>Delete project?</AlertDialogTitle>
<AlertDialogDescription>
This permanently removes the project and all of its work items. This action
can't be undone.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogClose />}
label="Delete"
/>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
</>
);
}Multiple triggers
createAlertDialogHandle connects many detached triggers to one shared confirmation, each passing the project it acts on as its payload.
Show codeHide code
import {
AlertDialog,
AlertDialogActions,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogIcon,
AlertDialogIntro,
AlertDialogTitle,
AlertDialogTrigger,
createAlertDialogHandle,
} from "@makeplane/propel/components/alert-dialog";
import { Button } from "@makeplane/propel/components/button";
import { TriangleAlert } from "lucide-react";
// One shared confirmation driven by detached triggers: each trigger passes the project it acts on
// as its `payload`, and the root reads that payload to personalize the copy.
const deleteProjectHandle = createAlertDialogHandle();
export default function MultipleTriggersDemo() {
return (
<>
<div className="flex flex-wrap items-center gap-3">
{["Mobile app", "Design system"].map((project) => (
<Button
key={project}
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogTrigger handle={deleteProjectHandle} payload={project} />}
label={`Delete ${project}`}
/>
))}
</div>
<AlertDialog handle={deleteProjectHandle}>
{({ payload }: { payload: unknown }) => (
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogIcon tone="danger">
<TriangleAlert />
</AlertDialogIcon>
<AlertDialogIntro>
<AlertDialogTitle>
Delete {typeof payload === "string" ? payload : "this project"}?
</AlertDialogTitle>
<AlertDialogDescription>
This permanently removes the project and all of its work items. This action
can't be undone.
</AlertDialogDescription>
</AlertDialogIntro>
</AlertDialogHeader>
<AlertDialogActions>
<Button
sizing="hug"
prominence="secondary"
tone="neutral"
magnitude="xl"
render={<AlertDialogClose />}
label="Cancel"
/>
<Button
sizing="hug"
prominence="primary"
tone="danger"
magnitude="xl"
render={<AlertDialogClose />}
label="Delete"
/>
</AlertDialogActions>
</AlertDialogContent>
)}
</AlertDialog>
</>
);
}Installation
import {
AlertDialog,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogIcon,
AlertDialogIntro,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogActions,
AlertDialogClose,
} from "@makeplane/propel/components/alert-dialog";
Props
AlertDialog
| Prop | Type | Required | Description |
|---|---|---|---|
| children | ReactNode | PayloadChildRenderFunction<unknown> | No | The content of the dialog. This can be a regular React node or a render function that receives the `payload` of the active trigger. |
AlertDialogContent
| Prop | Type | Required | Description |
|---|---|---|---|
| render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | No | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |