Dialog
Modal dialog using native <dialog> with title, description, close button, scrollable body, and action slot.
Overview
The Dialog component provides a modal overlay for focused user
interactions. Built on the native <dialog> element, it includes
built-in focus trapping, backdrop, and accessibility. Use it for forms, settings
panels, detail views, and any content that requires the user's full attention.
import { Dialog, Button } from '@enara-health/ui-react';
const [isOpen, setIsOpen] = useState(false);
<Button onClick={() => setIsOpen(true)}>Open Dialog</Button>
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
title="Edit Profile"
actions={
<>
<Button role="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button role="primary" onClick={handleSave}>Save</Button>
</>
}
>
<p>Dialog body content goes here.</p>
</Dialog> Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Required. Whether the dialog is visible |
onOpenChange | (open: boolean) => void | - | Required. Callback when open state changes |
title | string | - | Required. Dialog title displayed in the header |
description | string | - | Optional description text below the title |
children | ReactNode | - | Required. Body content of the dialog (scrollable) |
actions | ReactNode | - | Action buttons rendered in a fixed footer outside the scrollable body |
maxWidth | number | 500 | Maximum width of the dialog in pixels |
persistent | boolean | false | Prevents closing via Escape or backdrop click |
className | string | - | Additional CSS class names |
Variants
Basic Dialog
A simple dialog with title and body content.
<Dialog open={isOpen} onOpenChange={setIsOpen} title="Information">
<p>This is a basic dialog with just a title and content.</p>
</Dialog> With Description
Add a description below the title for additional context.
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
title="Edit Profile"
description="Update your personal information below."
actions={
<>
<Button role="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button role="primary" onClick={handleSave}>Save</Button>
</>
}
>
<Input label="Name" value={name} onChange={setName} />
<Input label="Email" value={email} onChange={setEmail} />
</Dialog> Persistent Mode
Use persistent to prevent closing via Escape or backdrop click.
The close button in the header is always available.
<Dialog
open={isProcessing}
onOpenChange={setIsProcessing}
title="Processing..."
persistent
>
<Spinner />
<p>Please wait while we process your request.</p>
</Dialog> Examples
Form Dialog
Common pattern for editing data in a modal form.
const [isOpen, setIsOpen] = useState(false);
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
title="Edit Patient"
actions={
<>
<Button role="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button role="primary" onClick={handleSave}>Save Changes</Button>
</>
}
>
<FormField label="Name">
<Input value={name} onChange={e => setName(e.target.value)} />
</FormField>
<FormField label="Email">
<Input type="email" value={email} onChange={e => setEmail(e.target.value)} />
</FormField>
</Dialog> Scrollable Content
Long content automatically scrolls within the dialog body. Actions stay fixed at the bottom.
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
title="Terms of Service"
actions={
<>
<Button role="secondary" onClick={() => setIsOpen(false)}>Decline</Button>
<Button role="primary" onClick={handleAccept}>Accept</Button>
</>
}
>
<p>Long content here... (scrolls within the body, actions stay fixed at bottom)</p>
</Dialog> Custom Width
Override the default max width for wider content.
<Dialog
open={isOpen}
onOpenChange={setIsOpen}
title="Data Preview"
maxWidth={700}
>
<Table data={previewData} columns={columns} />
</Dialog> Accessibility
- Role: Uses the native
<dialog>element which provides built-inrole="dialog". - Focus Trapping: Native
<dialog>traps focus within the dialog while it's open. - Keyboard Support: Escape closes the dialog (unless persistent). Tab navigates through focusable elements within.
- Screen Reader: Title is announced as the dialog label when the dialog opens.
- WCAG Compliance: Meets AA standards for modal interactions.
Best Practices
-
Use for focused tasks that require user attention — not for simple
confirmations (use
AlertDialog) - Avoid nesting dialogs — replace content or use navigation instead
- Always provide a clear way to close the dialog
- Keep dialog content focused on a single task
-
Use
persistentsparingly — only when dismissal would cause data loss