1
ComponentsOverlays

Dialog

Dialog focuses attention on a decision, short form, or other modal task.

Purpose

Dialog focuses attention on a decision, short form, or other modal task. Use Alert Dialog for destructive confirmation.

Invite member dialog

import { Dialog, DialogClose, DialogPopup, DialogTrigger } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";

export function Example() {
  return (
    <Dialog>
      <DialogTrigger render={<Button />}>Open dialog</DialogTrigger>
      <DialogPopup>
        <DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
      </DialogPopup>
    </Dialog>
  );
}

Installation

With the Siteplane registry alias configured, add the component and import the installed source from your app.

CLI

pnpm dlx shadcn@4.16.1 add @siteplane/dialog

Import

import { Dialog, DialogClose, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPopup, DialogTitle, DialogTrigger } from "@/components/ui/dialog";

Need the machine-readable source metadata? View registry JSON.

Usage

Use Dialog for short modal workflows. Keep the title, description, panel and footer slots explicit.

import { Dialog, DialogClose, DialogPopup, DialogTrigger } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";

export function Example() {
  return (
    <Dialog>
      <DialogTrigger render={<Button />}>Open dialog</DialogTrigger>
      <DialogPopup>
        <DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
      </DialogPopup>
    </Dialog>
  );
}

Examples

Form submission, footer variants, close button control, mobile behavior and panel scrolling are props and compositions of the same primitive.

Without close button

<DialogPopup showCloseButton={false}>
  <DialogHeader>
    <DialogTitle>Remove member</DialogTitle>
    <DialogDescription>
      Maya loses access to this workspace immediately.
    </DialogDescription>
  </DialogHeader>
  <DialogFooter>
    <DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
    <DialogClose render={<Button variant="destructive" />}>Remove</DialogClose>
  </DialogFooter>
</DialogPopup>

Mobile bottom stick

{/* Default: sticks to the bottom edge on small screens */}
<DialogPopup>...</DialogPopup>

{/* Centered on every viewport */}
<DialogPopup bottomStickOnMobile={false}>...</DialogPopup>

Scrollable panel

{/* Default: long content fades at the scroll edges */}
<DialogPopup className="max-h-96">
  <DialogHeader>
    <DialogTitle>Changelog</DialogTitle>
    <DialogDescription>Everything shipped in the recent releases.</DialogDescription>
  </DialogHeader>
  <DialogPanel>
    {releaseNotes.map(({ summary, version }) => (
      <div key={version}>
        <p className="font-medium">{version}</p>
        <p className="text-muted-foreground">{summary}</p>
      </div>
    ))}
  </DialogPanel>
  <DialogFooter>
    <DialogClose render={<Button variant="outline" />}>Close</DialogClose>
  </DialogFooter>
</DialogPopup>

{/* Hard scroll edges without the fade */}
<DialogPanel scrollFade={false}>...</DialogPanel>

Nested dialogs

A dialog opened from an open dialog scales and fades the parent through the built-in nested styling.

<Dialog>
  <DialogTrigger render={<Button variant="outline" />}>Manage plan</DialogTrigger>
  <DialogPopup>
    <DialogHeader>
      <DialogTitle>Manage plan</DialogTitle>
      <DialogDescription>Your workspace is on the Team plan.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose render={<Button variant="outline" />}>Close</DialogClose>
      {/* Nested dialog: the parent scales and fades while it is open */}
      <Dialog>
        <DialogTrigger render={<Button />}>Change plan</DialogTrigger>
        <DialogPopup>
          <DialogHeader>
            <DialogTitle>Change plan</DialogTitle>
            <DialogDescription>
              The parent dialog stays open behind this one.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <DialogClose render={<Button variant="outline" />}>Cancel</DialogClose>
            <DialogClose render={<Button />}>Confirm</DialogClose>
          </DialogFooter>
        </DialogPopup>
      </Dialog>
    </DialogFooter>
  </DialogPopup>
</Dialog>

API Reference

The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.

  • Compose Trigger, Popup, Title, Description, optional Panel and Footer, and explicit actions.
  • DialogCreateHandle supports one dialog with detached triggers or imperative opening.
  • DialogPopup closeProps customizes the built-in close Button while preserving it. Use showCloseButton={false} only when another clear close action exists.
  • DialogContent is a compatibility alias for DialogPopup; use DialogPopup in new code.

Motion

Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.

  • Backdrop uses the overlay duration and opacity transition.
  • Popup uses native dialog motion and the modal duration.
  • Do not add a second Dialog animation around the popup.
  • Global reduced-motion behavior removes unnecessary transforms.

Accessibility

  • Every Dialog requires a concise DialogTitle and should include a DialogDescription when the task needs explanation.
  • Preserve modal focus trapping, initial focus, Escape, outside-click behavior, and focus restoration.
  • All close and submit controls must be real Button components with accessible names.
  • If the built-in close Button is hidden, provide an equally discoverable close action.

Implementation Guidance

  • Use Dialog for focused modal tasks and Alert Dialog for destructive confirmation.
  • Use canonical DialogPopup in new code.
  • Preserve native focus, dismissal, close Button, and motion behavior.

On This Page