---
type: doc
title: Dialog
description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
---

> Fulldev UI for Astro. The `@fulldev` registry in `components.json` points at `https://ui.full.dev/r/styles/{style}/{name}.json`; see [installation](/astro/docs/installation.md).

```astro title="src/components/examples/dialog/dialog-demo.astro"
---
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { Field, FieldGroup } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
---

<Dialog>
  <form>
    <DialogTrigger variant="outline">Open Dialog</DialogTrigger>
    <DialogContent class="sm:max-w-sm">
      <DialogHeader>
        <DialogTitle>Edit profile</DialogTitle>
        <DialogDescription>
          Make changes to your profile here. Click save when you&apos;re done.
        </DialogDescription>
      </DialogHeader>
      <FieldGroup>
        <Field>
          <Label for="name-1">Name</Label>
          <Input id="name-1" name="name" value="Pedro Duarte" />
        </Field>
        <Field>
          <Label for="username-1">Username</Label>
          <Input id="username-1" name="username" value="@peduarte" />
        </Field>
      </FieldGroup>
      <DialogFooter>
        <DialogClose variant="outline">Cancel</DialogClose>
        <Button type="submit">Save changes</Button>
      </DialogFooter>
    </DialogContent>
  </form>
</Dialog>
```

## Installation

```bash
npx shadcn@latest add @fulldev/dialog
```

## Usage

```ts
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
```

```astro
<Dialog>
  <DialogTrigger>Open</DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Are you absolutely sure?</DialogTitle>
      <DialogDescription>
        This action cannot be undone. This will permanently delete your account
        and remove your data from our servers.
      </DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>
```

`DialogTrigger` and `DialogClose` render a `Button` and take its props, such as
`variant="outline"`. `DialogContent` moves to `document.body` while open, so a
`form` around the whole dialog does not contain the content: put the `form`
inside `DialogContent` when the dialog submits.

## Composition

```text
Dialog
├── DialogTrigger
└── DialogContent
    ├── DialogHeader
    │   ├── DialogTitle
    │   └── DialogDescription
    └── DialogFooter
```

## Custom Close Button

Replace the default close control with your own `DialogClose`.

```astro title="src/components/examples/dialog/dialog-close-button.astro"
---
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
---

<Dialog>
  <DialogTrigger variant="outline">Share</DialogTrigger>
  <DialogContent class="sm:max-w-md">
    <DialogHeader>
      <DialogTitle>Share link</DialogTitle>
      <DialogDescription>
        Anyone who has this link will be able to view this.
      </DialogDescription>
    </DialogHeader>
    <div class="flex items-center gap-2">
      <div class="grid flex-1 gap-2">
        <Label for="link" class="sr-only">
          Link
        </Label>
        <Input
          id="link"
          value="https://ui.shadcn.com/docs/installation"
          readonly
        />
      </div>
    </div>
    <DialogFooter class="sm:justify-start">
      <DialogClose>Close</DialogClose>
    </DialogFooter>
  </DialogContent>
</Dialog>
```

## No Close Button

Use `showCloseButton={false}` to hide the close button.

```astro title="src/components/examples/dialog/dialog-no-close-button.astro"
---
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
---

<Dialog>
  <DialogTrigger variant="outline">No Close Button</DialogTrigger>
  <DialogContent showCloseButton={false}>
    <DialogHeader>
      <DialogTitle>No Close Button</DialogTitle>
      <DialogDescription>
        This dialog doesn&apos;t have a close button in the top-right corner.
      </DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>
```

## Sticky Footer

Keep actions visible while the content scrolls.

```astro title="src/components/examples/dialog/dialog-sticky-footer.astro"
---
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
---

<Dialog>
  <DialogTrigger variant="outline">Sticky Footer</DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Sticky Footer</DialogTitle>
      <DialogDescription>
        This dialog has a sticky footer that stays visible while the content
        scrolls.
      </DialogDescription>
    </DialogHeader>
    <div class="-mx-4 no-scrollbar max-h-[50vh] overflow-y-auto px-4">
      {Array.from({ length: 10 }).map(() => (
        <p class="mb-4 leading-normal">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
      ))}
    </div>
    <DialogFooter>
      <DialogClose variant="outline">Close</DialogClose>
    </DialogFooter>
  </DialogContent>
</Dialog>
```

## Scrollable Content

Long content can scroll while the header stays in view.

```astro title="src/components/examples/dialog/dialog-scrollable-content.astro"
---
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
---

<Dialog>
  <DialogTrigger variant="outline">Scrollable Content</DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Scrollable Content</DialogTitle>
      <DialogDescription>
        This is a dialog with scrollable content.
      </DialogDescription>
    </DialogHeader>
    <div class="-mx-4 no-scrollbar max-h-[50vh] overflow-y-auto px-4">
      {Array.from({ length: 10 }).map(() => (
        <p class="mb-4 leading-normal">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
      ))}
    </div>
  </DialogContent>
</Dialog>
```

## RTL

```astro title="src/components/examples/dialog/dialog-rtl.astro"
---
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { Field, FieldGroup } from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

const translations = {
  en: {
    dir: "ltr",
    values: {
      openDialog: "Open Dialog",
      editProfile: "Edit profile",
      description:
        "Make changes to your profile here. Click save when you're done.",
      name: "Name",
      username: "Username",
      cancel: "Cancel",
      saveChanges: "Save changes",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      openDialog: "فتح الحوار",
      editProfile: "تعديل الملف الشخصي",
      description:
        "قم بإجراء تغييرات على ملفك الشخصي هنا. انقر فوق حفظ عند الانتهاء.",
      name: "الاسم",
      username: "اسم المستخدم",
      cancel: "إلغاء",
      saveChanges: "حفظ التغييرات",
    },
  },
  he: {
    dir: "rtl",
    values: {
      openDialog: "פתח דיאלוג",
      editProfile: "ערוך פרופיל",
      description: "בצע שינויים בפרופיל שלך כאן. לחץ על שמור כשתסיים.",
      name: "שם",
      username: "שם משתמש",
      cancel: "בטל",
      saveChanges: "שמור שינויים",
    },
  },
} as const

const language = "ar"
const { dir, values: t } = translations[language]
---

<Dialog>
  <form>
    <DialogTrigger variant="outline">{t.openDialog}</DialogTrigger>
    <DialogContent
      class="sm:max-w-sm"
      dir={dir}
      data-lang={dir === "rtl" ? language : undefined}
    >
      <DialogHeader>
        <DialogTitle>{t.editProfile}</DialogTitle>
        <DialogDescription>{t.description}</DialogDescription>
      </DialogHeader>
      <FieldGroup>
        <Field>
          <Label for="name-rtl-1">{t.name}</Label>
          <Input id="name-rtl-1" name="name" value="Pedro Duarte" />
        </Field>
        <Field>
          <Label for="username-rtl-1">{t.username}</Label>
          <Input id="username-rtl-1" name="username" value="@peduarte" />
        </Field>
      </FieldGroup>
      <DialogFooter>
        <DialogClose variant="outline">{t.cancel}</DialogClose>
        <Button type="submit">{t.saveChanges}</Button>
      </DialogFooter>
    </DialogContent>
  </form>
</Dialog>
```

## API Reference

Source: [`src/components/ui/dialog`](https://github.com/fulldotdev/ui/tree/main/src/components/ui/dialog)

| `Dialog` prop         | Type      | Default |
| --------------------- | --------- | ------- |
| `defaultOpen`         | `boolean` | `false` |
| `closeOnClickOutside` | `boolean` | `true`  |
| `closeOnEscape`       | `boolean` | `true`  |
| `lockScroll`          | `boolean` | `true`  |
| `alertDialog`         | `boolean` | `false` |

| `DialogContent` prop | Type      | Default |
| -------------------- | --------- | ------- |
| `showCloseButton`    | `boolean` | `true`  |

Open or close a dialog from a script with
`root.dispatchEvent(new CustomEvent("dialog:set", { detail: { open: true } }))`
and listen for `dialog:change`. See the
[Data Slot docs](https://github.com/bejamas/data-slot/blob/main/packages/dialog/README.md)
for all events and data attributes.

## Install what this page shows

```bash
npx shadcn@latest add @fulldev/dialog-examples
```
