Dialog
A popup that opens on top of the page and blocks interaction with it while modal.
WAI-ARIA patternInstallation
npx nuecrea-ui add dialogUsage
import { Button } from '@/components/ui/button';
import * as Dialog from '@/components/ui/dialog';
export default function DialogStory() {
return (
<main>
<Dialog.Root>
<Dialog.Trigger render={<Button variant="outline" />}>
Delete project
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Backdrop />
<Dialog.Viewport>
<Dialog.Popup>
<Dialog.Title>Delete project?</Dialog.Title>
<Dialog.Description>
This permanently deletes the project and its files. This cannot be undone.
</Dialog.Description>
<div className="flex justify-end gap-2">
<Dialog.Close render={<Button variant="outline" />}>
Cancel
</Dialog.Close>
<Dialog.Close render={<Button variant="destructive" />}>
Delete
</Dialog.Close>
</div>
</Dialog.Popup>
</Dialog.Viewport>
</Dialog.Portal>
</Dialog.Root>
</main>
);
}API reference
Dialog.Root
Groups all parts and owns the open state.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
modal | boolean | 'trap-focus' | true | true: traps focus, locks page scroll, blocks outside pointer interaction. 'trap-focus': traps focus only. false: none. |
disablePointerDismissal | boolean | false | Prevents closing on outside press. |
| Event | Payload | Description |
|---|---|---|
onOpenChange | boolean | Fired when the dialog requests to open or close. Angular: the `open` model's change event, so `[(open)]` works. React additionally passes eventDetails with the reason. |
onOpenChangeComplete | boolean | Fired after the open or close animation finishes. |
Dialog.Trigger
A button that opens the dialog. Renders <button>.
| Data attribute | Present when |
|---|---|
data-popup-open | the dialog is open |
data-disabled | disabled |
Dialog.Portal
Moves the backdrop and popup to the end of <body>. Renders <div>.
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keeps the portal in the DOM while the dialog is closed. |
Dialog.Backdrop
An overlay beneath the popup. Renders <div>.
| Data attribute | Present when |
|---|---|
data-open | open |
data-closed | closed |
data-starting-style | animating in |
data-ending-style | animating out |
Dialog.Viewport
Positioning container for the popup; can be made scrollable. Renders <div>.
| Data attribute | Present when |
|---|---|
data-open | open |
data-closed | closed |
data-nested | nested in another dialog |
data-nested-dialog-open | a nested dialog is open |
data-starting-style | animating in |
data-ending-style | animating out |
Dialog.Popup
Container for the dialog contents. Renders <div> with role dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
initialFocus | boolean | HTMLElement | null | — | Element to focus on open. Defaults to the first tabbable element. |
finalFocus | boolean | HTMLElement | null | — | Element to focus on close. Defaults to the trigger. |
| Data attribute | Present when |
|---|---|
data-open | open |
data-closed | closed |
data-nested | nested in another dialog |
data-nested-dialog-open | a nested dialog is open |
data-starting-style | animating in |
data-ending-style | animating out |
| CSS variable | Description |
|---|---|
--nested-dialogs | Number of open nested dialogs. |
Dialog.Title
Heading that labels the popup (aria-labelledby). Renders <h2>.
Dialog.Description
Paragraph that describes the popup (aria-describedby). Renders <p>.
Dialog.Close
A button that closes the dialog. Renders <button>.
| Data attribute | Present when |
|---|---|
data-disabled | disabled |
Keyboard
| Key | Action |
|---|---|
| Escape | Closes the dialog. |
| Tab | Moves focus to the next tabbable element in the popup, wrapping. |
| Shift+Tab | Moves focus to the previous tabbable element in the popup, wrapping. |