Dialog
A modal overlay that interrupts the page for a focused task, built on Base UI's dialog primitive.
Import
import { Dialog } from '@oztix/roadie-components/dialog'
Examples
Each example leads with an IconTile (size='2xl' shape='circle', its intent inherited from the dialog) centred above the title — Dialog.Header handles the centring.
Default
A trigger opens a centred modal over a dimmed backdrop. Dialog.Content collapses the underlying Portal, Backdrop, Viewport, and Popup into a single element.
Sizes
Use the size prop on Dialog.Content to set the maximum width. Defaults to md.
Intents
Portaled popups sit outside the trigger's CSS cascade, so set the colour context directly on Dialog.Content with the intent prop. Each intent fits a different moment — info and success for informational modals (dismiss-only, with a header close), warning and danger for caution and destructive confirmations, and accent to promote an action.
Alert dialog
For a blocking message that demands a response — a session timeout, a cart-expiry
warning, an irreversible confirmation — set role='alertdialog' on the root. This
exposes the surface as role="alertdialog" and raises the backdrop and surface to
the z-alert tier so the dialog stacks above an
already-open dialog or drawer. The default role='dialog' stays on the
z-overlay / z-modal tiers.
Composition
Dialog is a compound component. Use Dialog.Header, Dialog.Body, and Dialog.Footer to structure the modal, and Dialog.Close to dismiss it.
With footer actions
A Dialog.Footer holds a centered actions row. Combine it with intent='danger' for a confirm-deletion flow.
Guidelines
Use a dialog for tasks that need the user's full attention — confirmations, short forms, and destructive actions. Keep content concise, and set intent on Dialog.Content, not the trigger, since portaled popups do not inherit the trigger's CSS cascade.
Use alertdialog for blocking or destructive confirmations
Do
Set role='alertdialog' when the user must resolve the dialog before moving on — deleting data, discarding edits, a session or cart expiry. Screen readers announce it assertively, and it stacks above an already-open dialog or drawer on the z-alert tier.
Don’t
Don't leave a destructive or blocking confirmation as the default role='dialog' — it is announced as a plain dialog and can be obscured by an open drawer. Keep role='dialog' for informational or optional content.
Name buttons by their action
Do
Label the confirming button with the specific verb and object the user is committing to. A clear action like "Save changes" lets people act without rereading the title, and for destructive flows naming the consequence — "Delete event" — leaves no doubt about what happens.
Don’t
Vague labels like "OK", "Yes", or "Submit" tell the user nothing on their own. They have to jump back to the title to work out what they are actually agreeing to.
Write a title that states the decision
Delete event?
Do
A title that names the affected object and the action — a clear question or noun phrase — tells the user exactly what is at stake before they read another word.
Are you sure?
Don’t
Vague titles that never name the affected object force the user to hunt through the body for context, and make them hesitate before acting.
Use one prominent action, the rest normal
Do
Give the dialog one prominent button — emphasis='strong' with an accent intent, or danger for a destructive task — and leave the rest as default buttons. The primary path stays obvious at a glance.
Don’t
Never use emphasis='subtle' for footer actions, and never give a dialog more than one accent or strong button. Competing prominent buttons make the user stop and weigh every option instead of following the intended path.
Dismiss with a header close, not a lone Cancel
Do
When the only action is to close, put a Close icon button in the top-left of the header and skip the footer entirely. The dialog reads as informational, not a decision awaiting a choice.
Don’t
A lone Cancel in the footer wastes the prominent action slot and adds a step. There is nothing to cancel — the user only wants to close.
Lead notable dialogs with a matching icon
Do
For confirmations and notable moments, centre a size='2xl' shape='circle' IconTile above the title and leave its intent unset so it inherits the dialog's — a danger or warning tile for caution, success for completion. It signals the nature of the action before the title is read.
Don’t
Don't give the tile an intent that clashes with the dialog, shrink it until it reads as decoration, or add one to routine dialogs where it is just noise.
Accessibility
- Keyboard:
Escapecloses the dialog and returns focus to the trigger. Focus is trapped within the dialog while it is open. - Default action:
Enteractivates the strong primary action (theemphasis='strong'button), like a form's default submit. It is ignored while focus is on another button, a multi-line textarea, or editable content so those keep their ownEnterbehaviour. - Focus: Focus moves into the dialog on open and is restored to the trigger on close.
- ARIA: The popup is exposed with
role="dialog"andaria-modal, withDialog.Title/Dialog.Descriptionproviding the accessible name and description. Setrole='alertdialog'for a blocking message that needs a response — this also raises the dialog to thez-alerttier so it stacks above an open dialog or drawer. - Icon-only close: When the dismiss control shows only an icon, give it an explicit label — e.g.
<Dialog.Close render={<IconButton aria-label='Close'><XIcon weight='bold' /></IconButton>} />— so screen readers announce its purpose.
API reference
Dialog
Whether the dialog is currently open.
Whether the dialog is initially open. To render a controlled dialog, use the `open` prop instead.
Defaults to false.
Determines if the dialog enters a modal state when open. - `true`: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled. - `false`: user interaction with the rest of the document is allowed. - `'trap-focus'`: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled. When `modal` is `true` or `'trap-focus'`, render `<Dialog.Close>` inside `<Dialog.Popup>` so touch screen readers can escape the popup.
Defaults to true.
Event handler called when the dialog is opened or closed.
Event handler called after any animations complete when the dialog is opened or closed.
Determines whether the dialog should close on outside clicks.
Defaults to false.
A ref to imperative actions. - `unmount`: When specified, the dialog will not be unmounted when closed. Instead, the `unmount` function must be called to unmount the dialog manually. Useful when the dialog's animation is controlled by an external library. - `close`: Closes the dialog imperatively when called.
A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog's open state. Can be created with the Dialog.createHandle() method.
The content of the dialog. This can be a regular React node or a render function that receives the `payload` of the active trigger.
ID of the trigger that the dialog is associated with. This is useful in conjunction with the `open` prop to create a controlled dialog. There's no need to specify this prop when the popover is uncontrolled (i.e. when the `open` prop is not set).
ID of the trigger that the dialog is associated with. This is useful in conjunction with the `defaultOpen` prop to create an initially open dialog.
`'alertdialog'` raises the dialog to the `z-alert` tier so it stacks above an open modal or drawer.
Defaults to 'dialog'.
Dialog.Backdrop
Inherited from DialogBackdropProps
Whether the backdrop is forced to render even when nested.
Defaults to false.
Dialog.Body
No additional props — forwards all standard HTML attributes to the underlying element.
Dialog.Close
Inherited from NativeButtonProps
Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (e.g. `<div>`).
Defaults to true.
Dialog.Content
Inherited from DialogPopupProps
Determines the element to focus when the dialog is opened. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (first tabbable element or popup). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
Determines the element to focus when the dialog is closed. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (trigger or previously focused element). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
Dialog.Description
No additional props — forwards all standard HTML attributes to the underlying element.
Dialog.Footer
No additional props — forwards all standard HTML attributes to the underlying element.
Dialog.Header
No additional props — forwards all standard HTML attributes to the underlying element.
Dialog.Popup
Inherited from DialogPopupProps
Determines the element to focus when the dialog is opened. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (first tabbable element or popup). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
Determines the element to focus when the dialog is closed. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (trigger or previously focused element). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
Dialog.Portal
Inherited from DialogPortalProps
Whether to keep the portal mounted in the DOM while the popup is hidden.
Defaults to false.
A parent element to render the portal element into.
Dialog.Title
No additional props — forwards all standard HTML attributes to the underlying element.
Dialog.Trigger
Inherited from DialogTriggerProps
A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method.
A payload to pass to the dialog when it is opened.
ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialogs in controlled mode (with the DialogRoot `triggerId` prop).
Inherited from NativeButtonProps
Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (e.g. `<div>`).
Defaults to true.
Dialog.Viewport
No additional props — forwards all standard HTML attributes to the underlying element.