Modal
Focus attention on one task or message with a modal. Compare default, large, and required-action dialogs.
Examples
Default
Mobile
320pxMobile Lg
480pxTablet
640pxDesktop
1024pxAre you sure you want to continue?
You have unsaved changes that will be lost.
Large
Mobile
320pxMobile Lg
480pxTablet
640pxDesktop
1024pxAre you sure you want to continue?
You have unsaved changes that will be lost.
Forced Action
Mobile
320pxMobile Lg
480pxTablet
640pxDesktop
1024pxYour session will end soon.
You've been inactive for too long. Please choose to stay signed in or sign out. Otherwise, you'll be signed out automatically in 5 minutes.
Component API
Root provides context. Keep Backdrop and Positioner beside the trigger inside Root, and place Content inside Positioner. Give the dialog an accessible name through Title or aria-label on Root.
Root
Root controls whether the dialog is open and sets its size.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "default" | "lg" | default | Changes content width and body/title spacing. |
open | boolean | — | Controlled open state; update it after a change callback. |
onOpenChange | ({ open: boolean }) => void | — | Called when an open-state change is requested. |
forceAction | boolean | false | Prevents Escape and outside interaction from dismissing the dialog. Supply an explicit action. |
aria-label | string | — | Names the dialog directly and takes precedence over the Title relationship. |
ids | { root?: string; trigger?: string; backdrop?: string; positioner?: string; content?: string; closeTrigger?: string; title?: string; description?: string } | — | Overrides generated part IDs. Use Root IDs when a label or external control needs a stable input or trigger target. |
The dialog traps focus, prevents background scrolling, and restores focus after closing. These behaviors are managed automatically; the dialog role is fixed to dialog.
Trigger<button>
Opens the dialog and uses the default Button styling. Accepts native button props.
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, trigger | Select the trigger. |
data-state | open | closed | Style the open and closed states. |
Backdrop<div>
Covers the page behind the dialog. Clicking it closes the dialog when forceAction is false.
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, backdrop | Select the backdrop. |
data-state | open | closed | Style the open and closed states. |
Positioner<div>
Centers the dialog content.
| Attribute | Value | Purpose |
|---|---|---|
data-state | open | closed | Style the open and closed states. |
Content<div>
Holds the dialog content. Use Title or aria-label on Root to name the dialog.
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, content | Select the dialog content. |
data-state | open | closed | Style the open and closed states. |
Title<div>
Names the dialog. Put a heading inside it at the appropriate page level.
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, title | Select the title. |
Description<div>
Provides an optional description for the dialog.
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, description | Select the description. |
Body<div>
Spacing responds to Root's size variant.
Footer<div>
Provides spacing for dialog actions.
CloseTrigger<button>
Closes the dialog. Supply aria-label when using the default icon-only button.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Overrides the default accessible name. |
| Attribute | Value | Purpose |
|---|---|---|
data-scope, data-part | modal, close-trigger | Select the close button. |
Accessibility
The dialog manages focus, labeling, and closed-state visibility. Provide a useful title or label, meaningful action names, and an explicit way to finish a forced-action dialog.