Dialog
A Dialog shows users a window over the page and keeps focus inside it until it is closed.
When to Use
- for a short form that changes one record, such as “Rename project”
- for a task that users have to finish or cancel before anything else
- to show a command palette, as
CommandDialogin Command does
When Not to Use
- to ask for a response before an action that can’t be undone (use an Alert Dialog)
- for a panel docked to one side of the screen (use a Sheet)
- for a panel that users swipe away (use a Drawer)
- for content that belongs to one control and keeps the page interactive (use a Popover)
| Dialog | Alert Dialog | Sheet | Drawer | |
|---|---|---|---|---|
| Purpose | A short form | A message that needs a response | A side panel that needs no gestures | A panel that needs a swipe or snap points |
| Position | Center | Center | One side, the right by default | One edge, the bottom by default |
| Width From 640px | 576px | 384px, or 320px at size="sm" | 384px on the left or right | 384px on the left or right |
| Click Outside | Closes it | Does nothing | Closes it | Closes it |
Escape | Closes it | Closes it | Closes it | Closes it |
| Swipe | Does nothing | Does nothing | Does nothing | Closes it |
| Close Button | Shown by default | None | Shown by default | None |
| Role | dialog | alertdialog | dialog | dialog |
Anatomy
| Element | Usage |
|---|---|
| Overlay | Required |
| Close button | Shown by default |
| Popup | Required |
| Title* | Required |
| Description | Optional |
| Footer | Optional |
* The title is the Dialog’s accessible name. If the design shows no title, visually hide it and keep it in the markup.
DialogContent renders the portal, the overlay, and the close button, so you don’t need to add them. The figure is 352px wide, so its footer shows the stacked layout that is used below 640px.
Behavior
By default, a Dialog is modal: Base UI keeps focus in the popup, locks the page’s scroll, and prevents clicks from reaching the page. If you want the page to stay interactive, set modal={false} on Dialog. If you want the Dialog to stay open when users click the overlay, set disablePointerDismissal.
Footer
From 640px, the Buttons in the footer are placed in a row at its end. Below 640px, they are stacked in reverse order. Write the main action last so that it is at the end of the row and at the top of the stack.
Overflow
The popup is at most as tall as the screen. If the content is taller, the popup scrolls. To keep the header and the footer in view, place the content between them in a region that scrolls.
Content
| String | Rule | Example | Counterexample |
|---|---|---|---|
| Title | Repeat the trigger’s label so that the Dialog names its task | “Rename project” | “Project” |
| Description | Say in one sentence what the change affects | “The new name shows on invoices and reports.” | “Enter a new name below.” |
| Main action | Use the verb for what the click does | “Save” | “OK” |
The label of the close button is labels.dialog.close, which is “Close” by default. To translate it, use the Summit Provider.
Accessibility
Base UI’s Dialog sets the role, moves focus in and out, and closes when users press Escape. You provide the title that names the Dialog.
Requirements
A Dialog needs a DialogTitle so that screen readers can announce what it is for, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires.
If the design shows no title, add sr-only to its DialogHeader to visually hide it, as CommandDialog does.
If showCloseButton is false, keep a DialogClose in the popup. The ARIA Authoring Practices Guide strongly recommends a visible button that closes a dialog. The overlay is hidden from assistive technology, so if there is no such button, Escape is the only way for screen reader users to close the Dialog, and users on a touch screen have no Escape key.
Installation
npx shadcn@latest add @summit/dialogThe CLI also adds @summit/button and @summit/summit-provider.
Usage
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>Rename project</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Rename project</DialogTitle>
<DialogDescription>The new name shows on invoices and reports.</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
<DialogClose render={<Button />}>Save</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>;Hide the Close Button
To remove the close button in the corner, set showCloseButton={false} on DialogContent. To add an outline Button with the same label to the footer, set showCloseButton on DialogFooter.
<DialogContent showCloseButton={false}>
<DialogTitle>Rename project</DialogTitle>
<DialogFooter showCloseButton />
</DialogContent>Change the Width
By default, the width is sm:max-w-xl. To change it, pass another width in className on DialogContent.
<DialogContent className="sm:max-w-sm">
<DialogTitle>Rename project</DialogTitle>
</DialogContent>API Reference
The parts accept the props of their matching parts in Base UI’s Dialog, where DialogContent is Dialog.Popup and DialogOverlay is Dialog.Backdrop. DialogHeader and DialogFooter accept the props of a div. See the Base UI Dialog documentation for the props of each part.
DialogContent
| Prop | Type | Default | Description |
|---|---|---|---|
showCloseButton | boolean | true | Shows the close button in the top corner |
overlayClassName | string | None | Classes for the overlay |
DialogFooter
| Prop | Type | Default | Description |
|---|---|---|---|
showCloseButton | boolean | false | Adds an outline Button labeled by labels.dialog.close |