Dialog
Installation
Install the component via the CLI in one command.
npx shadcn@latest add @intentui/dialog
Composed components
When you install this component via the CLI, it automatically loads all composed components, so you don’t need to add them individually.
Manual installation
Use this approach if you prefer to install and wire up the component yourself instead of using the CLI.
npm install react-aria-components @heroicons/react cn
Anatomy
import { Button } from "@/components/ui/button"
import { Dialog, DialogBody, DialogClose, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"<DialogTrigger>
<Button>Open Dialog</Button>
<Dialog>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Dialog Description</DialogDescription>
</DialogHeader>
<DialogBody>Dialog Body</DialogBody>
<DialogFooter>
<DialogClose>Close</DialogClose>
<Button>Confirm</Button>
</DialogFooter>
</Dialog>
</DialogTrigger>Examples
Alert dialog
Use role="alertdialog" for a critical message that requires an explicit response.
Alert dialogs cannot be dismissed by clicking outside by default, and the close icon is hidden. Provide an explicit action such as Cancel.
<Dialog role="alertdialog" />Controlled
You can control the dialog programmatically.
Sizes
The dialog defaults to md. Available sizes are 2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, and fullscreen.
Dialog overlay styles
The overlay uses a subtle 1px blur by default. You can increase it or disable it entirely.
<DialogTrigger>
<Button intent="outline">Rename</Button>
<Dialog overlay={{ className: "backdrop-blur-2xl" }}>If you want to turn it off, use backdrop-blur-none. If you do not need any blur at all, the recommended approach is to remove the blur class from the component defaults.
-"bg-background/15 backdrop-blur-[1px] motion-reduce:backdrop-blur-none",
+"bg-background/15",Or, you can override it per instance from the component usage:
<DialogTrigger>
<Button intent="outline">Rename</Button>
<Dialog overlay={{ className: "backdrop-blur-none" }}>Sticky
Use DialogBody for scrollable content while the header and footer stay visible.
Nested
You can also nest dialogs. Try open it and confirm!
Header
This setup’s super flexible. If you skip adding DialogTitle and just drop a string as its child, it'll auto-render as the title. Like this:
<DialogHeader>
Title
</DialogHeader>Wanna customize more? Throw in props like title and description for a tailored header:
<DialogHeader title='Title' description='Description' />Triggered by menu
You can also trigger the dialog by clicking on a menu item.
It might be a good idea to extract the dialog into a separate component for better organization.
interface DialogActionProps {
state: string | null
onOpenChange: () => void
actionType: { description: string; action: () => void; confirmText: string; title: string }
disabled: boolean
}
const DialogAction = (props: DialogActionProps) => (
<Dialog isOpen={props.state !== null} onOpenChange={props.onOpenChange}>
<DialogHeader>
<DialogTitle>{props.actionType?.title}</DialogTitle>
<DialogDescription>{props.actionType?.description}</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>Cancel</DialogClose>
<Button
intent={props.state === "ban" ? "danger" : "primary"}
className="min-w-24"
isDisabled={props.disabled}
onPress={props.actionType?.action}
>
{props.disabled ? <Loader variant="spin" /> : props.actionType?.confirmText}
</Button>
</DialogFooter>
</Dialog>
)Then you can use it like this.
<DialogAction
state={state}
onOpenChange={closeDialog}
actionType={actionType(state)}
disabled={loading}
/>With that, now we can modify the actionType function to return the initial state.
const actionType = (t: string | null) => {
const initialsState = {
title: '',
description: '',
confirmText: '',
action: () => {}
}
switch (t) {
case 'delete': ...
case 'ban': ...
case 'restore': ...
default:
return initialsState
}
}Component API
DialogTrigger
DialogTrigger extends the React Aria Components <DialogTrigger> component.
Dialog
Dialog extends the React Aria Components <ModalOverlay> component.
classNamestringisOpenbooleanonOpenChange(isOpen: boolean) => voidisDismissablebooleantrue, except for alertdialogrole"dialog" | "alertdialog"dialogcloseButtonbooleantrueoverlayPick<ModalOverlayProps, "className">sizekeyof typeof sizesmdDialogBody
DialogBody extends the native <div> element.
classNamestringDialogCloseIcon
DialogCloseIcon renders a React Aria Button with the close slot. Dialog renders it automatically when closeButton and isDismissable are enabled.
classNamestringisDismissableboolean | undefinedDialogClose
DialogClose extends the Intent UI <Button> component.
classNamestringintent"primary" | "secondary" | "warning" | "danger" | "success" | "outline" | "plain"plainDialogDescription
DialogDescription renders a native <p> element.
classNamestringDialogFooter
DialogFooter extends the native <div> element.
classNamestringDialogHeader
DialogHeader extends the native <div> element.
classNamestringdescriptionstringtitlestringDialogTitle
DialogTitle extends the React Aria Components <Heading> component.
classNamestring