Dialog
React dialog component with focus trapping, keyboard navigation, and animations. Perfect for forms, confirmations, and modals that need user attention.
Building forms that need focus? Confirmation dialogs for delete actions? The Dialog component handles all your modal needs with built-in accessibility, animations, and keyboard navigation.
Perfect for login forms, settings panels, confirmation prompts, and any content that deserves your user's full attention.
npx shadcn@latest add dialog
Why developers love this Dialog
Built for modern React apps with all the features you expect:
- Focus trapping - Users can't accidentally click away and lose form data
- Keyboard shortcuts - Tab navigation + Escape to close works instantly
- Screen reader support - WCAG compliant out of the box
- Smooth animations - Professional fade/scale transitions included
- Mobile responsive - Looks great on phone, tablet, desktop
- No layout shift - Body scroll locks, z-index conflicts solved
Common dialog patterns developers need
Delete confirmation dialogs
The classic "Are you sure?" moment - essential for any destructive action:
Login and signup forms
Keep users focused during authentication flows:
Share and export features
One-click sharing with copy-to-clipboard functionality:
Terms of service and privacy policies
Long content that scrolls without breaking your layout:
Custom styled modals
When you need brand-specific close buttons and styling:
Context menu triggered dialogs
Right-click workflows that open modal actions:
API Reference
Dialog
Contains all the parts of a dialog. The root component that manages state.
Prop | Type | Default | Description |
---|---|---|---|
defaultOpen | boolean | false | The open state of the dialog when initially rendered |
open | boolean | - | The controlled open state of the dialog |
onOpenChange | (open: boolean) => void | - | Event handler called when the open state changes |
modal | boolean | true | Whether the dialog is modal (traps focus and blocks interaction with the rest of the page) |
DialogTrigger
The button that opens the dialog.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
DialogPortal
When used, portals your overlay and content parts into the body.
Prop | Type | Default | Description |
---|---|---|---|
forceMount | boolean | false | Used to force mounting when more control is needed |
container | HTMLElement | document.body | Specify a container element to portal the content into |
DialogOverlay
A layer that covers the inert portion of the view when the dialog is open.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
forceMount | boolean | false | Used to force mounting when more control is needed |
DialogContent
Contains content to be rendered in the open dialog.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
forceMount | boolean | false | Used to force mounting when more control is needed |
onOpenAutoFocus | (event: Event) => void | - | Event handler called when the dialog is opened |
onCloseAutoFocus | (event: Event) => void | - | Event handler called when the dialog is closed |
onEscapeKeyDown | (event: KeyboardEvent) => void | - | Event handler called when the escape key is down |
onPointerDownOutside | (event: PointerDownOutsideEvent) => void | - | Event handler called when a pointer event occurs outside the bounds |
onInteractOutside | (event: InteractOutsideEvent) => void | - | Event handler called when an interaction happens outside the component |
DialogClose
The button that closes the dialog.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
DialogTitle
An accessible title to be announced when the dialog is opened.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
DialogDescription
An optional accessible description to be announced when the dialog is opened.
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Change the default rendered element for the one passed as a child |
Keyboard Navigation
Key | Description |
---|---|
Space | Opens/closes the dialog |
Enter | Opens/closes the dialog |
Tab | Moves focus to the next focusable element |
Shift + Tab | Moves focus to the previous focusable element |
Escape | Closes the dialog and moves focus to trigger |
Dialog best practices for better UX
What we've learned from testing with thousands of users:
- Write clear button labels - "Save changes" beats "OK" every time
- Give users escape routes - Escape key, X button, Cancel button - the more the better
- Show what's happening - Loading spinners during saves prevent anxious re-clicks
- Focus smart - Put the cursor where users expect to type first
- Keep it snappy - Long dialogs lose people. Break complex flows into steps
- Confirm the scary stuff - Deleting data? Make them click twice
- Test with Tab and Space - Your keyboard-only users will thank you