Dialog

A focused task on top of the page — confirm a cancellation, create a booking, edit a week of hours. A squircle of the floating glass in three widths over a softly blurred page, built on the vendored Base UI dialog: it traps focus, closes on Escape and hands focus back to its trigger. On a phone it's a bottom sheet.

Playground

DialogContent
Parts

Confirm

A small dialog with a question, one sentence of consequence and two buttons. The way out comes first and takes focus; the confirming button repeats the title's verb. No X — the footer already offers a way out.

Sizes

sm 24rem for confirmations, md 28rem by default, lg 32rem for forms that need room. On a phone every size fills the width, less a 1rem margin each side.

With a form

Fields go in a DialogBody, which stacks them 16px apart. The first field takes focus when the dialog opens; the main action sits last in the footer.

Long content

A dialog never grows past five sixths of the screen. When its content would, only the DialogBody scrolls — the title and the save button stay in view.

Opened from a row

One dialog serves every row: open it from state instead of a trigger. Keep open and the row separate, so the text doesn't blank out while the dialog animates away.

  • 10:00 · Skin fade

    Jana Nováková

  • 11:00 · Beard trim

    Peter Kováč

On a phone, a sheet

Under sm every dialog rises from the screen's foot as a bottom sheet (Base UI's Drawer): the full width, a handle on top, dragged down or pressed outside to close (no X: Cancel is the way out), the page dimming less as it's pulled away. Nothing changes in how it's built — the same header, body and footer, the title and description the dialog's own — and a field in it stays in view over the keyboard. It moves on the motion tokens (SHEET_MOTION): up on duration-slow, down a step quicker, following the finger while it's dragged. A dialog that is a page of its own on a phone (SectionDialog) passes sheet={false}. Narrow this window, or open the catalog on a phone, to see it.

API reference

DialogContent

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"24, 28 or 32rem wide from the sm breakpoint; full width less 1rem each side below it.
showCloseButtonbooleantrueThe ghost X in the top corner. Drop it when the footer already offers a way out.
closeLabelstring"Close"The X's accessible name. Pass it translated.
initialFocusRefObject | boolean | fnfirst fieldWhere focus lands on open — by default the first focusable element. Base UI Popup prop.
classNamestring—Layout only. Never restyle the surface here.

Dialog

PropTypeDefaultDescription
openboolean—Controlled open state; pair it with onOpenChange. Leave both out and let DialogTrigger open it.
onOpenChange(open: boolean) => void—Called on every open and close — trigger, DialogClose, Escape, a press outside.
defaultOpenbooleanfalseOpen on first render, uncontrolled.
sheetbooleantrueOn a phone, a bottom sheet. false keeps it a dialog everywhere — one that is a page of its own there.
disablePointerDismissalbooleanfalseKeep it open on a press outside — for a form that would lose typed work.

Parts

PropTypeDefaultDescription
DialogTriggerrender—Opens the dialog. Give it a Button: render={<Button>…</Button>}.
DialogHeaderdiv—Stacks the title over the description.
DialogTitleh2—Names the dialog for assistive tech. Every dialog has one.
DialogDescriptionp—A quiet sentence under the title.
DialogBodydiv—Stacks content 16px apart and scrolls when the dialog meets the screen's edge.
DialogFooterdiv—The actions, main one last in source: stacked full width on a phone with the main action on top; in a row at the end from sm.
DialogCloserender—Closes the dialog. Give it a Button: render={<Button variant="secondary" />}.

Guidelines

  • Reach for a dialog only when the task must interrupt: a decision that can't be undone, or a short form that belongs to this moment. Anything that can wait is a toast; anything tied to one control is a popover.
  • Title the dialog with the question or the task — “Cancel booking?”, “New booking” — in sentence case. The confirming button repeats its verb; never “OK” or “Yes”.
  • One main action, last in the footer. The way out comes first, as a secondary DialogClose, and is where focus lands in a confirmation.
  • While the action runs, keep the dialog open and the button loading; close it on success. On failure keep it open and say what went wrong.
  • Pass closeLabel translated wherever the X shows — screen readers read it aloud.
  • Don't stack dialogs. If a step needs another step, it's a page.