---
title: Dialog
description: A popup that opens on top of the entire page.
links:
  doc: https://base-ui.com/react/components/dialog
  anatomy: https://base-ui.com/react/components/dialog#anatomy
  api: https://base-ui.com/react/components/dialog#api-reference
---

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";

export function DialogDemo() {
  return (
    <Dialog>
      <DialogTrigger render={<Button variant="outline" />}>Open Dialog</DialogTrigger>
      <DialogPopup>
        <Form className="grid">
          <DialogHeader>
            <DialogTitle>Edit profile</DialogTitle>
            <DialogDescription>
              Make changes to your profile here. Click save when you&apos;re done.
            </DialogDescription>
          </DialogHeader>
          <DialogBody className="grid gap-4">
            <Field>
              <FieldLabel>Name</FieldLabel>
              <Input defaultValue="ZBM Zubayer" type="text" />
            </Field>
            <Field>
              <FieldLabel>Username</FieldLabel>
              <Input defaultValue="zbmzubayer@example.com" type="text" />
            </Field>
          </DialogBody>
          <DialogFooter>
            <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
            <Button type="submit">Save</Button>
          </DialogFooter>
        </Form>
      </DialogPopup>
    </Dialog>
  );
}
```

## Installation

<ComponentSource name="dialog" title="components/ui/dialog.tsx" />

## Usage

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

```tsx
<Dialog>
  <DialogTrigger>Open Dialog</DialogTrigger>
  <DialogPopup>
    <DialogHeader>
      <DialogTitle>Dialog Title</DialogTitle>
      <DialogDescription>Dialog description text goes here.</DialogDescription>
    </DialogHeader>
    <DialogBody>
      Dialog content goes here. You can put forms, text, or any other elements inside the dialog.
    </DialogBody>
    <DialogFooter>
      <DialogClose>Close</DialogClose>
    </DialogFooter>
  </DialogPopup>
</Dialog>
```

## Examples

### With muted footer

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Form } from "@/components/ui/form";
import { Input } from "@/components/ui/input";

export function DialogDemo() {
  return (
    <Dialog>
      <DialogTrigger render={<Button variant="outline" />}>Open Dialog</DialogTrigger>
      <DialogPopup>
        <Form className="contents">
          <DialogHeader>
            <DialogTitle>Edit profile</DialogTitle>
            <DialogDescription>
              Make changes to your profile here. Click save when you&apos;re done.
            </DialogDescription>
          </DialogHeader>
          <DialogBody className="grid gap-4">
            <Field>
              <FieldLabel>Name</FieldLabel>
              <Input defaultValue="ZBM Zubayer" type="text" />
            </Field>
            <Field>
              <FieldLabel>Username</FieldLabel>
              <Input defaultValue="zbmzubayer@example.com" type="text" />
            </Field>
          </DialogBody>
          <DialogFooter variant="muted">
            <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
            <Button type="submit">Save</Button>
          </DialogFooter>
        </Form>
      </DialogPopup>
    </Dialog>
  );
}
```

### Backdrop variants

The backdrop of the dialog can be customized using the `backdropVariant` prop on `DialogPopup`. The available variants are `blur` (default), `opaque`, and `transparent`.

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogDescription,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";

const backdropVariants: React.ComponentProps<typeof DialogPopup>["backdropVariant"][] = [
  "blur",
  "opaque",
  "transparent",
];

export function DialogDemo() {
  return (
    <div className="flex flex-wrap items-center gap-5">
      {backdropVariants.map((variant) => (
        <Dialog key={variant}>
          <DialogTrigger render={<Button variant="outline" className="capitalize" />}>
            {variant}
          </DialogTrigger>
          <DialogPopup backdropVariant={variant}>
            <DialogHeader>
              <DialogTitle>Title</DialogTitle>
              <DialogDescription>Description</DialogDescription>
            </DialogHeader>
          </DialogPopup>
        </Dialog>
      ))}
    </div>
  );
}
```

### Popup position

Change the position of the popup by passing a `position` prop to `DialogPopup`. The default position is `center`. Other options include `top`, `bottom`, `top-center`, and `bottom-center`.

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogDescription,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";

export const positions: React.ComponentProps<typeof DialogPopup>["position"][] = [
  "top-left",
  "top",
  "top-right",
  "top-center",
  "center",
  "bottom-center",
  "bottom-left",
  "bottom",
  "bottom-right",
];

export function DialogDemo() {
  return (
    <div className="grid grid-cols-2 items-center gap-5 sm:grid-cols-3">
      {positions.map((position) => (
        <Dialog key={position}>
          <DialogTrigger render={<Button variant="outline" className="capitalize" />}>
            {position}
          </DialogTrigger>
          <DialogPopup position={position}>
            <DialogHeader>
              <DialogTitle>Title</DialogTitle>
              <DialogDescription>Description</DialogDescription>
            </DialogHeader>
          </DialogPopup>
        </Dialog>
      ))}
    </div>
  );
}
```

### No close button

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogDescription,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";

export function DialogDemo() {
  return (
    <Dialog>
      <DialogTrigger render={<Button variant="outline" />}>Open Dialog</DialogTrigger>
      <DialogPopup showCloseButton={false}>
        <DialogHeader>
          <DialogTitle>Title</DialogTitle>
          <DialogDescription>
            Description text goes here. You can provide additional information about the dialog
            content or instructions for the user.
          </DialogDescription>
        </DialogHeader>
      </DialogPopup>
    </Dialog>
  );
}
```

### Scrollable content

```tsx
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogClose,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";

export function DialogDemo() {
  return (
    <div className="flex flex-col gap-5">
      <Dialog>
        <div className="grid grid-cols-2 items-center gap-2 text-sm">
          <p>Scroll Area (Default)</p>
          <DialogTrigger render={<Button variant="outline" />}>Terms & Conditions</DialogTrigger>
        </div>
        <DialogPopup className="sm:max-w-md" showCloseButton={false}>
          <DialogHeader>
            <DialogTitle>Terms & Conditions</DialogTitle>
          </DialogHeader>
          <DialogBody>
            <ScrollContent />
          </DialogBody>
          <DialogFooter>
            <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
            <Button type="button">I agree</Button>
          </DialogFooter>
        </DialogPopup>
      </Dialog>
      <Dialog>
        <div className="grid grid-cols-2 items-center gap-2 text-sm">
          <p>Native scrollbar</p>
          <DialogTrigger render={<Button variant="outline" />}>Terms & Conditions</DialogTrigger>
        </div>
        <DialogPopup className="sm:max-w-md" showCloseButton={false}>
          <DialogHeader>
            <DialogTitle>Terms & Conditions</DialogTitle>
          </DialogHeader>
          <DialogBody scrollArea={false} className="border-y py-4 [scrollbar-width:thin]">
            <ScrollContent />
          </DialogBody>
          <DialogFooter>
            <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
            <Button type="button">I agree</Button>
          </DialogFooter>
        </DialogPopup>
      </Dialog>
      <Dialog>
        <div className="grid grid-cols-2 items-center gap-2 text-sm">
          <p>No scrollbar</p>
          <DialogTrigger render={<Button variant="outline" />}>Terms & Conditions</DialogTrigger>
        </div>
        <DialogPopup className="sm:max-w-md" showCloseButton={false}>
          <DialogHeader>
            <DialogTitle>Terms & Conditions</DialogTitle>
          </DialogHeader>
          <DialogBody scrollArea={false} className="no-scrollbar">
            <ScrollContent />
          </DialogBody>
          <DialogFooter>
            <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
            <Button type="button">I agree</Button>
          </DialogFooter>
        </DialogPopup>
      </Dialog>
    </div>
  );
}

function ScrollContent() {
  return (
    <div className="space-y-4 [&_strong]:font-semibold [&_strong]:text-foreground">
      <div className="space-y-4">
        <div className="space-y-1">
          <p>
            <strong>Acceptance of Terms</strong>
          </p>
          <p>
            By accessing and using this website, users agree to comply with and be bound by these
            Terms of Service. Users who do not agree with these terms should discontinue use of the
            website immediately.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>User Account Responsibilities</strong>
          </p>
          <p>
            Users are responsible for maintaining the confidentiality of their account credentials.
            Any activities occurring under a user&apos;s account are the sole responsibility of the
            account holder. Users must notify the website administrators immediately of any
            unauthorized account access.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>Content Usage and Restrictions</strong>
          </p>
          <p>
            The website and its original content are protected by intellectual property laws. Users
            may not reproduce, distribute, modify, create derivative works, or commercially exploit
            any content without explicit written permission from the website owners.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>Limitation of Liability</strong>
          </p>
          <p>
            The website provides content &ldquo;as is&rdquo; without any warranties. The website
            owners shall not be liable for direct, indirect, incidental, consequential, or punitive
            damages arising from user interactions with the platform.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>User Conduct Guidelines</strong>
          </p>
          <ul className="list-disc pl-6">
            <li>Not upload harmful or malicious content</li>
            <li>Respect the rights of other users</li>
            <li>Avoid activities that could disrupt website functionality</li>
            <li>Comply with applicable local and international laws</li>
          </ul>
        </div>
        <div className="space-y-1">
          <p>
            <strong>Modifications to Terms</strong>
          </p>
          <p>
            The website reserves the right to modify these terms at any time. Continued use of the
            website after changes constitutes acceptance of the new terms.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>Termination Clause</strong>
          </p>
          <p>
            The website may terminate or suspend user access without prior notice for violations of
            these terms or for any other reason deemed appropriate by the administration.
          </p>
        </div>
        <div className="space-y-1">
          <p>
            <strong>Governing Law</strong>
          </p>
          <p>
            These terms are governed by the laws of the jurisdiction where the website is primarily
            operated, without regard to conflict of law principles.
          </p>
        </div>
      </div>
    </div>
  );
}
```

### Nested dialogs

```tsx
"use client";

import { useState } from "react";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";

export function DialogDemo() {
  const [parentOpen, setParentOpen] = useState(false);

  return (
    <Dialog open={parentOpen} onOpenChange={setParentOpen}>
      <DialogTrigger render={<Button variant="outline" />}>Open parent</DialogTrigger>
      <DialogPopup showCloseButton={false}>
        <DialogHeader>
          <DialogTitle>Manage team member</DialogTitle>
          <DialogDescription>View and manage a user in your team.</DialogDescription>
        </DialogHeader>
        <DialogBody className="grid gap-4">
          <div className="grid gap-1">
            <p className="text-muted-foreground text-sm">Name</p>
            <p className="font-medium text-sm">ZBM Zubayer</p>
          </div>
          <div className="grid gap-1">
            <p className="text-muted-foreground text-sm">Email</p>
            <p className="font-medium text-sm">zbm@example.com</p>
          </div>
        </DialogBody>
        <DialogFooter>
          <Dialog>
            <DialogTrigger render={<Button variant="outline" />}>Edit details</DialogTrigger>
            <DialogPopup showCloseButton={false}>
              <DialogHeader>
                <DialogTitle>Edit details</DialogTitle>
                <DialogDescription>
                  Make changes to the member&apos;s information.
                </DialogDescription>
              </DialogHeader>
              <DialogBody className="grid gap-4">
                <Field>
                  <FieldLabel>Name</FieldLabel>
                  <Input defaultValue="ZBM Zubayer" type="text" />
                </Field>
                <Field>
                  <FieldLabel>Email</FieldLabel>
                  <Input defaultValue="zbm@example.com" type="text" />
                </Field>
              </DialogBody>
              <DialogFooter>
                <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
                <DialogClose render={<Button onClick={() => setParentOpen(false)} />}>
                  Save
                </DialogClose>
              </DialogFooter>
            </DialogPopup>
          </Dialog>
        </DialogFooter>
      </DialogPopup>
    </Dialog>
  );
}
```

### Show parent dialog of nested dialog

To show the parent dialog when a nested dialog is open, pass the `showNestedParent` prop to `DialogPopup`. This will keep the parent dialog visible while the nested dialog is open.

```tsx
"use client";

import { useState } from "react";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";

export function DialogDemo() {
  const [parentOpen, setParentOpen] = useState(false);

  return (
    <Dialog open={parentOpen} onOpenChange={setParentOpen}>
      <DialogTrigger render={<Button variant="outline" />}>Open parent</DialogTrigger>
      <DialogPopup showCloseButton={false} showNestedParent>
        <DialogHeader>
          <DialogTitle>Manage team member</DialogTitle>
          <DialogDescription>View and manage a user in your team.</DialogDescription>
        </DialogHeader>
        <DialogBody className="grid gap-4">
          <div className="grid gap-1">
            <p className="text-muted-foreground text-sm">Name</p>
            <p className="font-medium text-sm">ZBM Zubayer</p>
          </div>
          <div className="grid gap-1">
            <p className="text-muted-foreground text-sm">Email</p>
            <p className="font-medium text-sm">zbm@example.com</p>
          </div>
        </DialogBody>
        <DialogFooter>
          <Dialog>
            <DialogTrigger render={<Button variant="outline" />}>Edit details</DialogTrigger>
            <DialogPopup showCloseButton={false}>
              <DialogHeader>
                <DialogTitle>Edit details</DialogTitle>
                <DialogDescription>
                  Make changes to the member&apos;s information.
                </DialogDescription>
              </DialogHeader>
              <DialogBody className="grid gap-4">
                <Field>
                  <FieldLabel>Name</FieldLabel>
                  <Input defaultValue="ZBM Zubayer" type="text" />
                </Field>
                <Field>
                  <FieldLabel>Email</FieldLabel>
                  <Input defaultValue="zbm@example.com" type="text" />
                </Field>
              </DialogBody>
              <DialogFooter>
                <DialogClose render={<Button variant="ghost" />}>Cancel</DialogClose>
                <DialogClose render={<Button onClick={() => setParentOpen(false)} />}>
                  Save
                </DialogClose>
              </DialogFooter>
            </DialogPopup>
          </Dialog>
        </DialogFooter>
      </DialogPopup>
    </Dialog>
  );
}
```

## Api Reference

### Dialog Backdrop props

<ApiReferenceAccordion
  type={{
    variant: {
      description: "The variant of the backdrop.",
      type: "'blur' | 'opaque' | 'transparent'",
      default: `'blur'`,
    },
  }}
/>

### Dialog Viewport props

<ApiReferenceAccordion
  type={{
    position: {
      description: "The position of the popup.",
      type: "'center' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center'",
      default: `'center'`,
    },
  }}
/>

### Dialog Popup props

<ApiReferenceAccordion
  type={{
    bottomStickyOnMobile: {
      description:
        "Whether to make the popup bottom sticky on mobile devices. This is useful for dialogs that have important actions in the footer that should be easily accessible on mobile.",
      type: "boolean",
      default: `false`,
    },
    showCloseButton: {
      description: "Whether to show the close button in the header.",
      type: "boolean",
      default: `true`,
    },
    showNestedParent: {
      description:
        "Whether to show the parent dialog when a nested dialog is open. Useful for keeping the context of the parent dialog visible while interacting with the nested dialog.",
      type: "boolean",
      default: `false`,
    },
    backdropVariant: {
      description: "The variant of the backdrop.",
      type: "'blur' | 'opaque' | 'transparent'",
      default: `'blur'`,
    },
    position: {
      description: "The position of the popup.",
      type: "'center' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center'",
      default: `'center'`,
    },
  }}
/>

### Dialog Body props

<ApiReferenceAccordion
  type={{
    scrollArea: {
      description:
        "Whether to wrap the body in a scroll area. If false, native scrollbar will be shown if the content overflows.",
      type: "boolean",
      default: `true`,
    },
    scrollFade: {
      description: "Whether to show a fade effect at the top and bottom of the scroll area.",
      type: "boolean",
      default: `true`,
    },
    scrollbarGutter: {
      description: "Whether to show the scrollbar gutter when `scrollArea` is true.",
      type: "boolean",
      default: `false`,
    },
  }}
/>

### Dialog Footer props

<ApiReferenceAccordion
  type={{
    variant: {
      description: "The variant of the footer.",
      type: "'default' | 'muted'",
      default: `'default'`,
    },
  }}
/>
