Dialog

A modal surface that blocks the page until it is dismissed.

Dialog is the modal counterpart to Popover: it dims and blocks interaction with the rest of the page, traps focus, and returns focus to its trigger on close. Use it for a required step, a form, or anything the reader should not be able to dismiss by accident.

DialogTrigger pairs the trigger with the Dialog; the dialog opens on press and closes on Escape or its own DialogCloseButton. An outside press does not close it unless you pass isDismissable.

import { DialogTrigger, Heading } from 'react-aria-components';
import { Button } from '@base-org/bds-web/product/button';
import { Dialog, DialogCloseButton } from '@base-org/bds-web/product/dialog';

DialogTrigger and Heading come from react-aria-components; BDS does not re-export them.

<DialogTrigger>
<Button variant="primary">Open Dialog</Button>
<Dialog>
  <div className="flex items-start justify-between gap-4">
    <Heading slot="title" className="text-headline text-bds-gray-100">
      Dialog title
    </Heading>
    <DialogCloseButton />
  </div>
  <p className="text-body text-bds-gray-60">Dialog content goes here.</p>
</Dialog>
</DialogTrigger>

A Heading with slot="title" gives the dialog its accessible name automatically; pass aria-label instead when there is no visible heading.

When to use

Use Dialog for a required step, a form, or a confirmation the reader must complete or dismiss on purpose.

Use something else when:

  • The content is optional context to glance at. Use Popover.
  • It only names a control. Use Tooltip.
  • The message can sit in the page without blocking it. Use Banner.

Usage

Do

Reach for Dialog when the content blocks a flow the reader must complete or acknowledge — a form, a confirmation, a required choice.

Don't

Use a Dialog for content that is optional context the reader can glance at and dismiss. That belongs in a Popover, which does not block the rest of the page.

Content taller than the viewport scrolls inside the dialog without a scrollbar: the top or bottom edge fades while more content sits past it.

Props

PropTypeDefault
className

The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the

TypeClassNameOrFunction<ModalRenderProps>Default—
defaultOpen

Whether the overlay is open by default (uncontrolled).

TypebooleanDefault—
isDismissable

Whether to close the modal when the user interacts outside it.

TypebooleanDefaultfalse
isEntering

Whether the modal is currently performing an entry animation.

TypebooleanDefault—
isExiting

Whether the modal is currently performing an exit animation.

TypebooleanDefault—
isKeyboardDismissDisabled

Whether pressing the escape key to close the modal should be disabled.

TypebooleanDefaultfalse
isOpen

Whether the overlay is open by default (controlled).

TypebooleanDefault—
role

The accessibility role for the dialog.

Type"dialog" | "alertdialog"Default'dialog'
shouldCloseOnInteractOutside

When user interacts with the argument element outside of the overlay ref,

Type((element: Element) => boolean)Default—
UNSTABLE_portalContainer

The container element in which the overlay portal will be placed. This may have unknown

TypeElementDefaultdocument.body

DialogCloseButton

An icon button pre-wired to close the nearest Dialog or Popover. It reads the open state from context, so it works without an explicit onPress. Its accessible name defaults to "Close".

PropTypeDefault
arrow

Appends an animated chevron in place of `endIcon`. Its shaft draws in and

TypebooleanDefault—
className

The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the

TypeClassNameOrFunction<ButtonRenderProps>Default—
endIconTypeReactNode | ((renderProps: ButtonRenderProps) => ReactNode)Default—
externalArrow

Appends a small ↗ in place of `endIcon` for links that leave the site, and

TypebooleanDefault—
isDisabled

Whether the button is disabled.

TypebooleanDefault—
sizeType"sm" | "md" | "lg" | nullDefaultmd
startIconTypeReactNode | ((renderProps: ButtonRenderProps) => ReactNode)Default—
statusType"idle" | "pending" | "success"Default—
successIconTypeReactNodeDefault—
titleTypestringDefault—
type

The behavior of the button when used in an HTML form.

Type"button" | "submit" | "reset"Default'button'
variantType"outline" | "outline-negative" | "secondary" | "primary" | "negative" | "ghost" | "bare" | nullDefaultbare

Accessibility

Dialog wraps React Aria's Modal and Dialog: it traps focus while open, restores focus to the trigger on close, and dismisses on Escape unless isKeyboardDismissDisabled is set. Outside presses dismiss it only when isDismissable is set — leave it off for a required step. Give it an accessible name via a slot="title" heading or an aria-label.

The panel scales up from 95% as it opens and leaves with a shorter, smaller fade. When the reader prefers reduced motion, it opens and closes without animating.