Dialog

PreviousNext

A windowed dialog component.

Component dialog-demo not found in registry.

Installation

pnpm dlx shadcn@latest add dialog

Usage

import * as Button from "@/registry/react-aria/ui/button"
import * as Dialog from "@/registry/react-aria/ui/dialog"
 
export function DialogExample() {
  return (
    <Dialog.Root>
      <Dialog.Trigger>
        <Button.Root>Open Dialog</Button.Root>
      </Dialog.Trigger>
      <Dialog.Content>
        <Dialog.Header title="Dialog Title" description="Dialog description" />
        <Dialog.Body>
          <p>Dialog content goes here.</p>
        </Dialog.Body>
        <Dialog.Footer>
          <Button.Root variant="secondary" appearance="ghost">
            Cancel
          </Button.Root>
          <Button.Root>Confirm</Button.Root>
        </Dialog.Footer>
      </Dialog.Content>
    </Dialog.Root>
  )
}

Features

  • Accessible: Built on React-Aria primitives with full keyboard navigation and screen reader support
  • Customizable: Flexible styling with Tailwind CSS variants
  • Animated: Smooth enter/exit animations
  • Responsive: Adapts to different screen sizes
  • Composable: Modular components for different dialog sections

Variants

Basic Dialog

A simple dialog with title, description, and action buttons.

<Dialog.Root>
  <Dialog.Trigger>
    <Button.Root>Open Dialog</Button.Root>
  </Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header
      title="Basic Dialog"
      description="This is a basic dialog example."
    />
    <Dialog.Body>
      <p>Dialog content goes here.</p>
    </Dialog.Body>
    <Dialog.Footer>
      <Button.Root variant="secondary" appearance="ghost">
        Cancel
      </Button.Root>
      <Button.Root>Confirm</Button.Root>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>

Dialog with Icon

A dialog with an icon in the header.

<Dialog.Root>
  <Dialog.Trigger>
    <Button.Root>Show Alert</Button.Root>
  </Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header
      icon={AlertTriangle}
      title="Warning"
      description="This action cannot be undone."
    />
    <Dialog.Body>
      <p>Are you sure you want to proceed?</p>
    </Dialog.Body>
    <Dialog.Footer>
      <Button.Root variant="secondary" appearance="ghost">
        Cancel
      </Button.Root>
      <Button.Root variant="error">Delete</Button.Root>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>

Custom Header

A dialog with custom header content.

<Dialog.Root>
  <Dialog.Trigger>
    <Button.Root>Custom Dialog</Button.Root>
  </Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header>
      <div className="flex items-center gap-3">
        <div className="bg-primary/10 flex size-10 items-center justify-center rounded-full">
          <Info className="text-primary size-5" />
        </div>
        <div>
          <Dialog.Title>Custom Header</Dialog.Title>
          <Dialog.Description>
            This dialog has custom header content
          </Dialog.Description>
        </div>
      </div>
    </Dialog.Header>
    <Dialog.Body>
      <p>Custom dialog content.</p>
    </Dialog.Body>
  </Dialog.Content>
</Dialog.Root>

Examples

Confirmation Dialog

function ConfirmationDialog() {
  const [open, setOpen] = React.useState(false)
 
  return (
    <Dialog.Root>
      <Dialog.Trigger>
        <Button.Root variant="error" appearance="bordered">
          <Trash2 className="mr-2 h-4 w-4" />
          Delete Item
        </Button.Root>
      </Dialog.Trigger>
      <Dialog.Content>
        <Dialog.Header
          icon={Trash2}
          title="Delete Item"
          description="This action cannot be undone."
        />
        <Dialog.Body>
          <p className="text-muted-foreground text-sm">
            Are you sure you want to delete this item? This action will
            permanently remove it from your account.
          </p>
        </Dialog.Body>
        <Dialog.Footer>
          <Button.Root
            variant="secondary"
            appearance="ghost"
            onPress={() => setOpen(false)}
          >
            Cancel
          </Button.Root>
          <Button.Root variant="error" onPress={() => setOpen(false)}>
            Delete
          </Button.Root>
        </Dialog.Footer>
      </Dialog.Content>
    </Dialog.Root>
  )
}

Success Dialog

function SuccessDialog() {
  return (
    <Dialog.Root>
      <Dialog.Trigger>
        <Button.Root variant="primary" appearance="bordered">
          <CheckCircle className="mr-2 h-4 w-4" />
          Show Success
        </Button.Root>
      </Dialog.Trigger>
      <Dialog.Content>
        <Dialog.Header
          icon={CheckCircle}
          title="Success!"
          description="Your action was completed successfully."
        />
        <Dialog.Body>
          <p className="text-muted-foreground text-sm">
            The item has been saved and is now available in your account.
          </p>
        </Dialog.Body>
        <Dialog.Footer>
          <Button.Root>Continue</Button.Root>
        </Dialog.Footer>
      </Dialog.Content>
    </Dialog.Root>
  )
}

Accessibility

The Dialog component is built on React-Aria primitives and includes:

  • Keyboard Navigation: Full keyboard support with Escape to close
  • Focus Management: Automatic focus trapping and restoration
  • Screen Reader Support: Proper ARIA attributes and announcements
  • Portal Rendering: Renders outside the DOM hierarchy to avoid z-index issues
  • Backdrop Interaction: Click outside to close functionality