dialog
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
Philosophy
Dialogs demand attention and block interaction — use them when the user must make a decision before continuing. We split the anatomy into DialogTrigger, DialogContent, DialogHeader, etc. because every dialog has different needs but the same accessibility requirements: focus trapping, escape dismissal, and return focus.
How It's Built
Installation
npx @gentleduck/cli add dialog
npx @gentleduck/cli add dialog
Usage
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog><Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>Examples
Controlled Dialog
Notes
To use the Dialog component from within a Context Menu or Dropdown Menu, you must encase the Context Menu or
Dropdown Menu component in the Dialog component.
<Dialog>
<ContextMenu>
<ContextMenuTrigger>Right click</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Open</ContextMenuItem>
<ContextMenuItem>Download</ContextMenuItem>
<DialogTrigger asChild>
<ContextMenuItem>
<span>Delete</span>
</ContextMenuItem>
</DialogTrigger>
</ContextMenuContent>
</ContextMenu>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. Are you sure you want to permanently
delete this file from our servers?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="submit">Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog><Dialog>
<ContextMenu>
<ContextMenuTrigger>Right click</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Open</ContextMenuItem>
<ContextMenuItem>Download</ContextMenuItem>
<DialogTrigger asChild>
<ContextMenuItem>
<span>Delete</span>
</ContextMenuItem>
</DialogTrigger>
</ContextMenuContent>
</ContextMenu>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. Are you sure you want to permanently
delete this file from our servers?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="submit">Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>Component Composition
API Reference
Dialog
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | false | Initial open state for uncontrolled usage |
open | boolean | -- | Controlled open state |
onOpenChange | (open: boolean) => void | -- | Callback when open state changes |
modal | boolean | true | Enables modal focus/interaction behavior (focus trapping, scroll blocking) |
dir | 'ltr' | 'rtl' | -- | Text direction. Resolved by primitives useDirection (dir prop -> DirectionProvider -> 'ltr'). |
children | React.ReactNode | -- | Dialog sub-components (DialogTrigger, DialogContent, etc.) |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root> | -- | Additional props inherited from DialogPrimitive.Root |
DialogTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | -- | Trigger content |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger> | -- | Additional props inherited from DialogPrimitive.Trigger |
DialogPortal
| Prop | Type | Default | Description |
|---|---|---|---|
container | HTMLElement | -- | Optional portal container |
forceMount | true | -- | Forces mounted state for all portal children |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal> | -- | Additional props inherited from DialogPrimitive.Portal |
DialogOverlay
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> | -- | Additional props inherited from DialogPrimitive.Overlay |
DialogContent
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | true | -- | Force mounting for animation control |
closeText | string | 'Close' | Accessible label for the built-in close button |
className | string | -- | Additional CSS classes applied to the content panel |
children | React.ReactNode | -- | Dialog inner content |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> | -- | Additional props inherited from DialogPrimitive.Content |
DialogContent renders a built-in close button in the top-right corner.
DialogHeader
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes applied to the header |
children | React.ReactNode | -- | Header content (typically DialogTitle and DialogDescription) |
...props | React.HTMLAttributes<HTMLDivElement> | -- | Additional props to spread to the header container |
DialogFooter
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes applied to the footer |
children | React.ReactNode | -- | Footer content (typically action buttons) |
...props | React.HTMLAttributes<HTMLDivElement> | -- | Additional props to spread to the footer container |
DialogTitle
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes applied to the title |
children | React.ReactNode | -- | Title text |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> | -- | Additional props inherited from DialogPrimitive.Title |
DialogDescription
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes applied to the description |
children | React.ReactNode | -- | Description text |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> | -- | Additional props inherited from DialogPrimitive.Description |
DialogClose
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | -- | Close control content |
...props | React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close> | -- | Additional props inherited from DialogPrimitive.Close |
Responsive Variants
The following responsive components automatically render a Dialog on desktop (>=768px) and a Drawer on mobile. Each accepts the same props as its non-responsive counterpart.
| Component | Desktop renders | Mobile renders |
|---|---|---|
DialogResponsive | Dialog | Drawer |
DialogTriggerResponsive | DialogTrigger | DrawerTrigger |
DialogContentResponsive | DialogContent | DrawerContent |
DialogHeaderResponsive | DialogHeader | DrawerHeader |
DialogFooterResponsive | DialogFooter | DrawerFooter |
DialogTitleResponsive | DialogTitle | DrawerTitle |
DialogDescriptionResponsive | DialogDescription | DrawerDescription |
DialogCloseResponsive | DialogClose | DrawerClose |
RTL Support
Set dir="rtl" on Dialog for a local override, or set DirectionProvider once at app/root level for global direction. Dialog content parts inherit direction automatically.
<Dialog dir="rtl">
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>عنوان الحوار</DialogTitle>
<DialogDescription>وصف الحوار هنا.</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog><Dialog dir="rtl">
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>عنوان الحوار</DialogTitle>
<DialogDescription>وصف الحوار هنا.</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>See also
- Sheet — Side panel overlay, extends Dialog
- Drawer — Bottom drawer overlay, great for mobile
- Alert Dialog — Confirmation dialog that requires user action