Dialog
A modal window for confirmations, short forms and decisions.
Dialog opens a modal over the page. Build it from Dialog, DialogTitle, DialogContent,
DialogContentText and DialogActions. It sits on React Aria's modal overlay, so focus moves
in, Tab stays inside, the page behind is hidden from screen readers and scrolling locks.
import Dialog from '@hone-ui/react/Dialog';
import DialogTitle from '@hone-ui/react/DialogTitle';
import DialogContent from '@hone-ui/react/DialogContent';
import DialogContentText from '@hone-ui/react/DialogContentText';
import DialogActions from '@hone-ui/react/DialogActions';Basic dialog
You own the open state. The dialog never closes by itself, so set it to false in onClose.
const [open, setOpen] = useState(false);
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>Delete file?</DialogTitle>
<DialogContent>
<DialogContentText>This cannot be undone.</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Cancel</Button>
<Button onClick={remove}>Delete</Button>
</DialogActions>
</Dialog>;Force a choice
Ignore backdrop clicks so the dialog closes only through its buttons.
<Dialog
open={open}
onClose={(event, reason) => {
if (reason !== 'backdropClick') setOpen(false);
}}
>
...
</Dialog>Size and scrolling
<Dialog open={open} onClose={close} fullWidth maxWidth="md">...</Dialog>
<Dialog open={open} onClose={close} fullScreen>...</Dialog>
<Dialog open={open} onClose={close} scroll="body">...</Dialog>Dialog props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | required | Whether the dialog is visible. |
onClose | (event, reason) => void | none | Called on Escape or an outside press. reason is 'backdropClick' or 'escapeKeyDown'. |
fullWidth | boolean | false | Grows the paper to maxWidth. |
maxWidth | 'xs', 'sm', 'md', 'lg', 'xl', false | 'sm' | 444, 600, 900, 1200 or 1536px. |
fullScreen | boolean | false | Fills the viewport with square corners. |
scroll | 'paper', 'body' | 'paper' | Scroll DialogContent inside the paper, or the whole dialog. |
disableEscapeKeyDown | boolean | false | Makes Escape do nothing. |
hideBackdrop | boolean | false | Hides the dimmed layer. |
PaperProps, slotProps.paper | object | none | Props for the Paper surface. slotProps.paper wins. The default elevation is 24. See Form dialog. |
slotProps.backdrop | object | none | Props for the Backdrop, such as invisible. |
aria-labelledby, aria-describedby | string | none | Land on the element with role="dialog". |
sx, className, style, ref, id, children | Standard. They land on the root layer that holds the backdrop and paper. |
Part props
| Component | Props |
|---|---|
DialogTitle | children, sx, className, style, ref and every HTML prop of an h2. |
DialogContent | dividers (boolean, default false) adds borders above and below with even padding. Plus the standard props. |
DialogContentText | Every Typography prop. variant defaults to 'body1', color to 'text.secondary' and component to 'p'. |
DialogActions | disableSpacing (boolean, default false) removes the gap between actions. Plus the standard props. |
Form dialog
The paper is always a section. Set component: 'form' and Dialog renders a form inside it, around
the title, content and actions. onSubmit, onReset, action, method, noValidate, encType,
target, autoComplete, name and acceptCharset go to the form, and nothing else does.
className, sx, style, elevation, aria-* and every other prop stay on the paper section.
<Dialog
open={open}
onClose={close}
slotProps={{ paper: { component: 'form', onSubmit: handleSubmit } }}
>
<DialogTitle>Subscribe</DialogTitle>
<DialogContent>...</DialogContent>
<DialogActions>
<Button type="submit">Subscribe</Button>
</DialogActions>
</Dialog>Notes
onClosereceives the real DOMEvent, not a ReactSyntheticEvent. React Aria drops the event, so Dialog readswindow.eventinside the synchronous dismiss callback. If no event is running, it skipsonCloseinstead of inventing one. The event is not cancelable.- Not supported are
keepMounted,TransitionComponent,transitionDuration,TransitionProps,slots,container,disableScrollLock,disableAutoFocus,disableEnforceFocusanddisableRestoreFocus. Focus trap, scroll lock and focus return always run. - DialogContent, DialogContentText and DialogActions are Server Components and ignore theme
defaultProps. Dialog and DialogTitle read them. - Enter and exit are CSS fades. They drop to none under
prefers-reduced-motion.
Accessibility
A Dialog needs an accessible name. A DialogTitle supplies one with no id. Without a title, set aria-label or
aria-labelledby on the Dialog. To describe it with body text, give DialogContentText an id
and pass that id as aria-describedby. Keep the Dialog mounted and toggle open, so the exit
fade runs. Put the safe action first in DialogActions and the main action last.