A popup that opens on top of the entire page.
Import the component and assemble its parts:
import { Dialog } from "@/components/ui/dialog";
<Dialog>
<DialogTrigger />
<DialogPopup>
<DialogTitle />
<DialogDescription />
<DialogClose />
</DialogPopup>
</Dialog>;By default, the dialog is dismissible. You can make it non dismissible by passing disablePointerDismissal={true} to the Dialog component. This is useful when you want to prevent the user from closing the dialog by clicking outside of it or by pressing the escape key.
Use open and onOpenChange props if you need to access or control the state of the dialog.
For example, you can control the dialog state in order to open it imperatively from another place in your app.
const [open, setOpen] = React.useState(false);
return (
<Dialog.Root
open={open}
onOpenChange={setOpen}
>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Popup>
<form
// Close the dialog once the form data is submitted
onSubmit={async () => {
await submitData();
setOpen(false);
}}
>
...
</form>
</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>
);The modal property controls how users can interact with the page when the dialog is open.
modal={true} (default) -
Focus is trapped, scrolling is locked, and outside interactions are disabled.
modal={false} -
Users can interact with both the dialog and the rest of the page freely.
modal="trap-focus" -
Focus is trapped for keyboard navigation, but scrolling and outside pointer interactions remain enabled.
Currently, two of animation presets (flip and slide) are direction aware. So, when dialogs are nested, those dialogs will be stacked as they are also direction aware.
A separate guide is available for Detached Triggers because this concept is also applicable to other components like menu, popover, etc. So, I thought it would be better to keep it in a separate guide.
You'll find using detached triggers with dialog in the Detached Triggers - Dialog guide.
You can reduce the motion of the dialog by passing reduceMotion to the DialogPopup component.