Skip to content

Dialog

A modal dialog surface with backdrop, focus management, and configurable dismiss behavior.

Confirm changes

Review the updates before applying them.

Are you sure you want to apply these changes to this workspace?

<>
<Button label="Open dialog" onClick={() => setIsOpen(true)} />
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<Text as="p" color="secondary">
Are you sure you want to apply these changes to this
workspace?
</Text>
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Apply"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
secondaryButton={
<Button label="Cancel" onClick={() => setIsOpen(false)} />
}
/>
}
header={
<LayoutHeader
subtitle="Review the updates before applying them."
title="Confirm changes"
/>
}
/>
</Dialog>
</>

Confirm changes

Review the updates before applying them.

Are you sure you want to apply these changes to this workspace?

<>
<Button
label="Open dialog without dividers"
onClick={() => setIsOpen(true)}
/>
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<Text as="p" color="secondary">
Are you sure you want to apply these changes to this
workspace?
</Text>
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Apply"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
secondaryButton={
<Button label="Cancel" onClick={() => setIsOpen(false)} />
}
/>
}
hasDividers={false}
header={
<LayoutHeader
subtitle="Review the updates before applying them."
title="Confirm changes"
/>
}
/>
</Dialog>
</>

Required action

This dialog can only be closed from an explicit action.

<>
<Button label="Open required dialog" onClick={() => setIsOpen(true)} />
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<Text as="p" color="secondary">
This dialog can only be closed from an explicit action.
</Text>
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Acknowledge"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
/>
}
header={<LayoutHeader title="Required action" />}
/>
</Dialog>
</>

Edit profile

<>
<Button label="Open form dialog" onClick={() => setIsOpen(true)} />
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 12,
}}>
<TextInput
hasAutoFocus
label="Name"
onChange={() => {}}
value="Ada Lovelace"
/>
<TextInput
label="Email"
onChange={() => {}}
type="email"
value="ada@example.com"
/>
</div>
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Save"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
secondaryButton={
<Button label="Cancel" onClick={() => setIsOpen(false)} />
}
/>
}
header={<LayoutHeader title="Edit profile" />}
/>
</Dialog>
</>

Full screen

This dialog takes up the entire viewport.

<>
<Button
label="Open fullscreen dialog"
onClick={() => setIsOpen(true)}
/>
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<Text as="p" color="secondary">
This dialog takes up the entire viewport.
</Text>
</LayoutContent>
}
header={<LayoutHeader title="Full screen" />}
/>
</Dialog>
</>

Terms of Service

Section 1: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 3: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 4: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 5: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 6: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 7: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 8: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 9: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 10: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 11: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 12: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 13: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 14: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 15: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 16: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 17: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 18: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 19: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section 20: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

<>
<Button
label="Open scrollable dialog"
onClick={() => setIsOpen(true)}
/>
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
{Array.from({length: 20}, (_, i) => (
<Text as="p" color="secondary" key={i}>
Section {i + 1}: Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Sed do eiusmod tempor incididunt ut labore
et dolore magna aliqua.
</Text>
))}
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Accept"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
/>
}
header={<LayoutHeader title="Terms of Service" />}
/>
</Dialog>
</>

Nested overlays

<>
<Button label="Open nested overlays" onClick={() => setIsOpen(true)} />
<Dialog {...args} isOpen={isOpen} onOpenChange={setIsOpen}>
<Layout
content={
<LayoutContent>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 16,
}}>
<Select
label="Fruit"
onChange={setFruit}
options={['Apple', 'Banana', 'Cherry']}
value={fruit}
/>
<DropdownMenu
button={{label: 'Dialog actions'}}
items={[
{label: 'Duplicate'},
{label: 'Archive'},
{type: 'divider'},
{label: 'Delete'},
]}
/>
</div>
</LayoutContent>
}
footer={
<LayoutFooter
primaryButton={
<Button
label="Done"
onClick={() => setIsOpen(false)}
variant="primary"
/>
}
/>
}
header={<LayoutHeader title="Nested overlays" />}
/>
</Dialog>
</>

Basic — title only (no close button outside Dialog)

Basic header

With subtitle and endContent

Full header

Supporting text below the title

Draft

With all slots populated

New

Kitchen sink

All slots populated

Draft
<div style={{display: 'flex', flexDirection: 'column', gap: 24}}>
<div>
<Text as="p" color="secondary" type="supporting">
Basic — title only (no close button outside Dialog)
</Text>
<div
style={{
border: '1px solid #eee',
borderRadius: 8,
marginTop: 8,
maxWidth: 480,
}}>
<LayoutHeader title="Basic header" />
</div>
</div>
<div>
<Text as="p" color="secondary" type="supporting">
With subtitle and endContent
</Text>
<div
style={{
border: '1px solid #eee',
borderRadius: 8,
marginTop: 8,
maxWidth: 480,
}}>
<LayoutHeader
endContent={<Badge color="info" label="Draft" size="sm" />}
subtitle="Supporting text below the title"
title="Full header"
/>
</div>
</div>
<div>
<Text as="p" color="secondary" type="supporting">
With all slots populated
</Text>
<div
style={{
border: '1px solid #eee',
borderRadius: 8,
marginTop: 8,
maxWidth: 480,
}}>
<LayoutHeader
endContent={<Badge color="info" label="Draft" size="sm" />}
startContent={<Badge color="success" label="New" size="sm" />}
subtitle="All slots populated"
title="Kitchen sink"
/>
</div>
</div>
</div>
<>
<Button
label="Show report"
onClick={() =>
dialog.show(
<Layout
content={
<LayoutContent>
<Text as="p" color="secondary">
The report is ready for review.
</Text>
</LayoutContent>
}
header={<LayoutHeader title="Generated report" />}
/>,
)
}
/>
{dialog.element}
</>

A modal dialog surface with backdrop, focus management, and configurable dismiss behavior.

PropTypeDefaultDescription
children*ReactNodeDialog body content.
classNamestringAdditional CSS class names applied to the dialog.
data-testidstringTest ID applied to the dialog.
dismissBehaviorDialogDismissBehavior{isEscapeDismissEnabled: true, isBackdropDismissEnabled: true}Controls whether Escape and backdrop clicks request dismissal. Pass a boolean to enable or disable both behaviors together.
isOpen*booleanWhether the dialog is open.
labelstringAccessible label for the dialog. When provided, sets aria-label directly. When omitted, the dialog uses aria-labelledby to reference the heading rendered by a child LayoutHeader. Omit this prop when using a LayoutHeader inside the dialog. Set it when the dialog has no visible heading.
maxHeightnumber | string'75vh'Maximum height of the dialog. Numbers are treated as pixels.
onOpenChange*(isOpen: boolean) => voidCalled when the dialog requests an open-state change.
positionReadonly<DialogPosition>Fixed positioning offsets for the dialog.
refRef<HTMLDialogElement>Ref forwarded to the dialog element.
role"dialog" | "alertdialog"'dialog'ARIA role exposed by the dialog.
styleCSSPropertiesInline styles applied to the dialog.
variant"fullscreen" | "standard"'standard'Display variant.
widthnumber | string400Dialog width. Numbers are treated as pixels.