Experience System
Components

Dialog

A modal window for focused tasks, confirmations, and forms—built on Radix Dialog with Experience System styling.

Installation

The component is exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.

Composition

Use the following composition to build a Dialog:

Dialog
├── DialogTrigger (optional if controlled)
└── DialogContent
    ├── DialogHeader
    │   ├── DialogTitle
    │   └── DialogDescription (optional)
    ├── (body)
    └── DialogFooter (optional)
        └── DialogClose (optional)

DialogContent includes portal, overlay, and the default corner close button unless you set showCloseButton={false}. Use DialogHeader / DialogFooter for spacing; pair DialogTitle (and usually DialogDescription) for accessibility. Radix behavior: Radix Dialog.

Usage

import {
  Button,
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@by/experience-system';

Dialog and its parts are client components ('use client'). Wrap your tree in ThemeProvider so the portal targets the correct container. Use dialogs inside a Client Component or a dynamic import when using the Next.js App Router.

<Dialog>
  <DialogTrigger asChild>
    <Button>Open</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Title</DialogTitle>
      <DialogDescription>Optional description.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="outline">Cancel</Button>
      </DialogClose>
    </DialogFooter>
  </DialogContent>
</Dialog>

When to use

  • Blocking confirmation or multi-step flows that need focus and a clear dismiss path.
  • Short forms or edits where the page should stay visible but de-emphasized behind a backdrop.

When not to use

Examples

The live preview at the top of this page uses dialog-usage (open trigger + titled modal shell).

Overview

A typical profile-style dialog: header, scrollable body with fields, and footer actions. The default close control appears in the content header.

No close button

Set showCloseButton={false} on DialogContent when the corner close control should be hidden (for example, force an explicit Cancel / Continue choice).

Use flex / overflow on DialogContent, shrink-0 on header and footer, and a min-h-0 flex-1 overflow-y-auto region for long content. Hide the default close button and place DialogClose in the header when you need custom actions.

Custom close in the header

With showCloseButton={false}, compose DialogClose next to other header controls while keeping DialogTitle for accessibility.

API Reference

Subsection titles name @by/experience-system exports and the Radix part they wrap. Full primitive props and behavior: Radix Dialog.

Dialog

Root

PropTypeDefault
openboolean
defaultOpenboolean
onOpenChange(open: boolean) => void
modalbooleantrue
Data attributeValues
data-slotdialog

DialogTrigger

PropTypeDefault
asChildbooleanfalse

Also accepts standard button attributes when not using asChild.

DialogPortal

Portals dialog parts. DialogContent already includes portal behavior for the main modal.

PropTypeDefault
forceMountboolean
containerHTMLElementFrom ThemeProvider / useContainerElement() when applicable

DialogOverlay

Backdrop; typically rendered as part of DialogContent in this experience system.

DialogContent

Modal panel; merges className. Design-system prop showCloseButton (default true) toggles the header close icon button.

PropTypeDefault
showCloseButtonbooleantrue
asChildbooleanfalse
forceMountboolean

Also accepts Radix Dialog.Content positioning and focus props. See Radix Dialog — Content.

DialogClose

PropTypeDefault
asChildbooleanfalse

DialogHeader

Layout wrapper for the title region (Experience System spacing, not a separate Radix primitive).

DialogFooter

Action row (column on small screens, row on sm+). Optional showCloseButton (default false) adds an outline Close button.

PropTypeDefault
showCloseButtonbooleanfalse

DialogTitle

Accessible title. Required for dialog accessibility.

DialogDescription

Supporting text (optional but recommended).

Accessibility

  • Always include DialogTitle (and usually DialogDescription) inside the dialog for screen reader context.
  • Ensure at least one keyboard-focusable dismiss path: default close, DialogClose, or controlled onOpenChange from a primary action.
  • Focus trap and Escape follow Radix Dialog.

Source in the repo: packages/experience-system/src/components/Dialog/Dialog.tsx. Agent-oriented contracts: packages/experience-system/src/components/Dialog/Dialog_instructions.md.