Dialog

Blocks the page with one focused task the user finishes or dismisses.

import { Dialog } from "@usefragments/ui";Source

Preview

<Dialog>
  <Dialog.Trigger render={<Button>Open dialog</Button>} />
  <Dialog.Content>
    <Dialog.Close />
    <Dialog.Header>
      <Dialog.Title>Dialog title</Dialog.Title>

Usage

Use when

  • Collecting input the user must finish in one pass
  • Content that needs acknowledgment before continuing
  • Isolating a step in a longer workflow

Avoid when

  • A decision the user must answer, such as a destructive confirmation (use AlertDialog)
  • A short hint (use Tooltip)
  • A list of actions (use Menu)
  • Contextual content that should not block (use Popover)
  • Feedback the user does not act on (use Toast or Alert)

Implementation notes

  • One task per dialog
  • Title states the task; body states the consequence
  • Pair the primary action with an explicit cancel
  • Escape and an outside press dismiss; for a destructive choice use AlertDialog
  • Pass render={<Button />} to Dialog.Trigger — the bare trigger ships unstyled

Do not use a Dialog for a non-blocking notification.

Don’t

<Dialog>Saved</Dialog>

Do

<Alert tone="info">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Title>Settings sync pending</Alert.Title>
    <Alert.Content>Changes reach every workspace within a minute.</Alert.Content>
  </Alert.Body>
</Alert>

Do not omit an accessible title and explicit close action from a Dialog.

Don’t

<Dialog><Dialog.Content>Focused task</Dialog.Content></Dialog>

Do

<Dialog defaultOpen>
  <Dialog.Content>
    <Dialog.Title>Account settings</Dialog.Title>
    <Dialog.Body>Update your workspace preferences.</Dialog.Body>
    <Dialog.Close>Close</Dialog.Close>
  </Dialog.Content>
</Dialog>

Installation

pnpm add @usefragments/ui

Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Anatomy

Import Dialog once, then compose its parts with dot notation.

  • Dialog.Trigger
  • Dialog.Content
  • Dialog.Close
  • Dialog.Header
  • Dialog.Title
  • Dialog.Description
  • Dialog.Body
  • Dialog.Footer

Header, body, and footer in the standard layout.

<Dialog>
  <Dialog.Trigger render={<Button>Open dialog</Button>} />
  <Dialog.Content>
    <Dialog.Close />
    <Dialog.Header>
      <Dialog.Title>Dialog title</Dialog.Title>
      <Dialog.Description>Focused supporting content.</Dialog.Description>
    </Dialog.Header>
    <Dialog.Body>Dialog body</Dialog.Body>
    <Dialog.Footer>
      <Dialog.Close render={<Button variant="ghost">Close</Button>} />
    </Dialog.Footer>
  </Dialog.Content>
</Dialog>

Examples

Large

Wider surface for denser content.

<Dialog>
  <Dialog.Trigger render={<Button>Open large dialog</Button>} />
  <Dialog.Content width="lg">
    <Dialog.Close />
    <Dialog.Header>
      <Dialog.Title>Detailed settings</Dialog.Title>

No Initial Focus

Skips autofocus when you place focus yourself.

<Dialog>
  <Dialog.Trigger render={<Button variant="soft">Open settings</Button>} />
  <Dialog.Content initialFocus={false}>
    <Dialog.Header>
      <Dialog.Title>Settings</Dialog.Title>
      <Dialog.Description>Choose a settings area to edit.</Dialog.Description>

Long Title

A wrapping title keeps the close control reachable.

<Dialog>
  <Dialog.Trigger render={<Button>Open long title dialog</Button>} />
  <Dialog.Content>
    <Dialog.Close />
    <Dialog.Header>
      <Dialog.Title>

API reference

Component props
Prop
Type
Default
Description
Body.childrenRequiredReact.ReactNodeNot set—
childrenRequiredReact.ReactNodeNot set—
Content.childrenRequiredReact.ReactNodeNot set—
Content.finalFocusboolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) | undefinedNot setWhere focus goes when the dialog closes.
Content.initialFocusboolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void) | undefinedNot setWhere focus goes when the dialog opens.
Content.widthDialogWidth | undefinedsmmdlgNot setSheet width.
defaultOpenboolean | undefinedNot setDefault open state
Description.childrenRequiredReact.ReactNodeNot set—
Footer.childrenRequiredReact.ReactNodeNot set—
Header.childrenRequiredReact.ReactNodeNot set—
onOpenChange((open: boolean) => void) | undefinedNot setCalled when the open state changes
openboolean | undefinedNot setControlled open state
Title.childrenRequiredReact.ReactNodeNot set—

Accessibility

  • Traps focus while open
  • Escape closes
  • Focus returns to the trigger on close
  • role="dialog" with title and description wired to aria attributes
  • PopoveralternativeUse Popover for non-modal contextual content
  • MenualternativeUse Menu for action lists
  • AlertsiblingUse Alert for inline notifications
  • AlertDialogsiblingUse AlertDialog for a decision the user must answer

Next steps