Dialog

A window over the page that asks for the person's attention, for forms, details and confirmations.

import { Button } from "@hel/ui/button"
import {
  Dialog,

When to use it

Use a dialog when people have to finish or dismiss something before going on: a short form such as inviting a teammate, the details of a record, or terms to accept. The page behind it is dimmed and cannot be used, and keyboard focus stays inside the dialog until it is closed.

Use dialogs sparingly, because they interrupt. For a small amount of extra content that does not need to block the page, use a Popover. For a question that must be answered before something destructive happens, use an Alert Dialog. For a panel that slides in from the edge, use a Drawer.

Import

import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from "@hel/ui/dialog"

Anatomy

Dialog holds the open state, and DialogTrigger is the button that opens it. DialogContent is the window, together with the dimmed backdrop behind it.

Inside it, DialogHeader groups a DialogTitle and a DialogDescription with a close button at the end of the row. The title names the dialog for screen readers, and the description is read after it. Then come the body, which is whatever you like, and a DialogFooter for the buttons.

DialogClose closes the dialog when its element is pressed. Pass the button you want with render, so the two are one element.

<Dialog>
  <DialogTrigger render={<Button variant="outline">Invite a teammate</Button>} />
  <DialogContent size="sm">
    <DialogHeader>
      <DialogTitle>Invite a teammate</DialogTitle>
      <DialogDescription>They will get an email with a link to join.</DialogDescription>
    </DialogHeader>
    ...
    <DialogFooter>
      <DialogClose render={<Button variant="outline">Cancel</Button>} />
      <DialogClose render={<Button>Send invite</Button>} />
    </DialogFooter>
  </DialogContent>
</Dialog>

Escape and a click on the backdrop close the dialog too. The close button in the header can be left out with showClose={false}, for a dialog that must end with one of its own buttons.

Examples

Controlled

Use open and onOpenChange when your own code decides when the dialog opens or closes, such as when it should stay open while something is being saved. The trigger is then an ordinary button that sets the state. Here the dialog cannot be dismissed while it is saving.

Current name: Quarterly report

import * as React from "react"

import { Button } from "@hel/ui/button"

Long content

Give a long dialog a fixed height with height="tall", and put the long part in a scroll area, so the header and the footer stay in view. blur blurs the page behind the dialog instead of only dimming it.

import { Button } from "@hel/ui/button"
import {
  Dialog,

Size and position

size is the width of the window: sm, md or lg, or auto, which fits the content. A dialog never gets wider than the screen. placement="top" puts the window near the top of the screen instead of the center, which suits a dialog whose height changes, such as one with search results. padding takes a step of the spacing scale and defaults to xl, and gap="none" removes the space between the header, the body and the footer.

Props

DialogContent

PropTypeDefault
size"auto" | "sm" | "md" | "lg""auto"
placement"center" | "top""center"
height"auto" | "tall""auto"
paddinga spacing step"xl"
gap"default" | "none""default"
blurbooleanfalse
disableAnimationbooleanfalse

DialogHeader

PropTypeDefault
showClosebooleantrue

Dialog

Takes every prop of the Base UI dialog, such as open, defaultOpen and onOpenChange.