---
title: "Dialog"
description: "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert."
canonical_url: "https://vinicunca.dev/akar/components/dialog"
---
# Dialog

> A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.

```vue [index.vue]
<script setup lang="ts">
import {
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogOverlay,
  DialogPortal,
  DialogRoot,
  DialogTitle,
  DialogTrigger,
} from 'akar'
import './styles.css'
</script>

<template>
  <div class="akar-demo akar-demo-Dialog">
    <DialogRoot>
        <DialogTrigger
          class="Button grass"
        >
          Edit profile
        </DialogTrigger>
        <DialogPortal>
          <DialogOverlay class="DialogOverlay" />
          <DialogContent
            class="DialogContent"
          >
            <DialogTitle class="DialogTitle">
              Edit profile
            </DialogTitle>
            <DialogDescription class="DialogDescription">
              Make changes to your profile here. Click save when you're done.
            </DialogDescription>
            <fieldset class="Fieldset">
              <label
                class="Label"
                for="name"
              > Name </label>
              <input
                id="name"
                class="Input"
                defaultValue="Pedro Duarte"
              >
            </fieldset>
            <fieldset class="Fieldset">
              <label
                class="Label"
                for="username"
              > Username </label>
              <input
                id="username"
                class="Input"
                defaultValue="@peduarte"
              >
            </fieldset>
            <div :style="{ display: 'flex', marginTop: 25, justifyContent: 'flex-end' }">
              <DialogClose as-child>
                <button
                  class="Button green"
                >
                  Save changes
                </button>
              </DialogClose>
            </div>
            <DialogClose
              class="IconButton"
              aria-label="Close"
            >
              <PIcon name="i-lucide-x" />
            </DialogClose>
          </DialogContent>
        </DialogPortal>
      </DialogRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/green.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';

@scope (.akar-demo-Dialog) {
/* reset */
button,
fieldset,
input {
  all: unset;
}

.DialogOverlay {
  background-color: var(--black-a9);
  position: fixed;
  inset: 0;
  animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}

.DialogContent {
  background-color: white;
  border-radius: 6px;
  box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 90vw;
  max-width: 450px;
  max-height: 85vh;
  padding: 25px;
  animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
}
.DialogContent:focus {
  outline: none;
}

.DialogTitle {
  margin: 0;
  font-weight: 500;
  color: var(--mauve-12);
  font-size: 17px;
}

.DialogDescription {
  margin: 10px 0 20px;
  color: var(--mauve-11);
  font-size: 15px;
  line-height: 1.5;
}

.Button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  padding: 0 15px;
  font-size: 15px;
  line-height: 1;
  font-weight: 500;
  height: 35px;
}
.Button.grass {
  background-color: white;
  color: var(--grass-11);
  box-shadow: 0 2px 10px var(--black-a7);
}
.Button.grass:hover {
  background-color: var(--mauve-3);
}
.Button.grass:focus {
  box-shadow: 0 0 0 2px black;
}
.Button.green {
  background-color: var(--green-4);
  color: var(--green-11);
}
.Button.green:hover {
  background-color: var(--green-5);
}
.Button.green:focus {
  box-shadow: 0 0 0 2px var(--green-7);
}

.IconButton {
  font-family: inherit;
  border-radius: 100%;
  height: 25px;
  width: 25px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--grass-11);
  position: absolute;
  top: 10px;
  right: 10px;
}
.IconButton:hover {
  background-color: var(--grass-4);
}
.IconButton:focus {
  box-shadow: 0 0 0 2px var(--grass-7);
}

.Fieldset {
  display: flex;
  gap: 20px;
  align-items: center;
  margin-bottom: 15px;
}

.Label {
  font-size: 15px;
  color: var(--grass-11);
  width: 90px;
  text-align: right;
}

.Input {
  width: 100%;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  padding: 0 10px;
  font-size: 15px;
  line-height: 1;
  color: var(--grass-11);
  box-shadow: 0 0 0 1px var(--grass-7);
  height: 35px;
}
.Input:focus {
  box-shadow: 0 0 0 2px var(--grass-8);
}

@keyframes overlayShow {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes contentShow {
  from {
    opacity: 0;
    transform: translate(-50%, -48%) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}
}
```

## Features

- Supports modal and non-modal modes.
- Focus is automatically trapped when modal.
- Can be controlled or uncontrolled.
-  Manages screen reader announcements with `Title` and`Description` components.
- Esc closes the component automatically.

## Installation

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup>
import {
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogOverlay,
  DialogPortal,
  DialogRoot,
  DialogTitle,
  DialogTrigger,
} from 'akar';
</script>

<template>
  <DialogRoot>
    <DialogTrigger />
    <DialogPortal>
      <DialogOverlay />
      <DialogContent>
        <DialogTitle />
        <DialogDescription />
        <DialogClose />
      </DialogContent>
    </DialogPortal>
  </DialogRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a dialog

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defaultOpen` | `false` | `boolean` | The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. |
| `modal` | `true` | `boolean` | The modality of the dialog When set to `true`,<br><br>interaction with outside elements will be disabled and only dialog content will be visible to screen readers. |
| `open` |  | `boolean` | The controlled open state of the dialog. Can be binded as `v-model:open`. |
| `unmountOnHide` | `true` | `boolean` | When set to `false`, the dialog content will not be unmounted when closed, but instead hidden with CSS.<br><br>Useful for SEO or when you want to improve performance by not remounting the component on every open. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `value: boolean` | Event handler called when the open state of the dialog changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `open` | `boolean` | Current open state |
| `close` | `(): void` | Close the dialog |

[DialogRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogRoot.vue)

### Trigger

The button that opens the dialog

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DialogTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |

### Portal

When used, portals your overlay and content parts into the `body`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defer` |  | `boolean` | Defer the resolving of a Teleport target until other parts of the<br>application have mounted (requires Vue 3.5.0+)<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) |
| `disabled` |  | `boolean` | Disable teleport and render the component inline<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `to` |  | `string \| HTMLElement` | Vue native teleport component prop `:to`<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) |

[DialogPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogPortal.vue)

### Overlay

A layer that covers the inert portion of the view when the dialog is open.

> [!NOTE]
> 
> Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation).

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |

[DialogOverlay.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogOverlay.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |

### Content

Contains content to be rendered in the open dialog

> [!NOTE]
> 
> Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation).

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disableOutsidePointerEvents` |  | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside<br>the `DismissableLayer`. Users will need to click twice on outside elements to<br>interact with them: once to close the `DismissableLayer`, and again to trigger the element. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.<br>Can be prevented. |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `openAutoFocus` | `event: Event` | Event handler called when auto-focusing on open.<br>Can be prevented. |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[DialogContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |

### Close

The button that closes the dialog

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DialogClose.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogClose.vue)

### Title

An accessible title to be announced when the dialog is opened.

If you want to hide the title, wrap it inside our Visually Hidden utility like this `<VisuallyHidden asChild>`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"h2"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DialogTitle.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogTitle.vue)

### Description

An optional accessible description to be announced when the dialog is opened.

If you want to hide the description, wrap it inside our Visually Hidden utility like this `<VisuallyHidden asChild>`. If you want to remove the description entirely, remove this part and pass `:aria-describedby="undefined"` to `DialogContent`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"p"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DialogDescription.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog/DialogDescription.vue)

## Examples

### Nested dialog

You can nest multiple layers of dialogs.

```vue [index.vue]
<script setup lang="ts">
import {
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogOverlay,
  DialogPortal,
  DialogRoot,
  DialogTitle,
  DialogTrigger,
} from 'akar'
</script>

<template>
  <div class="akar-demo akar-demo-DialogNested">
    <div>
        <DialogRoot>
          <DialogTrigger
            class="text-grass11 font-semibold shadow-blackA7 hover:bg-mauve3 inline-flex h-[35px] items-center justify-center rounded-[4px] bg-white px-[15px] leading-none shadow-[0_2px_10px] focus:shadow-[0_0_0_2px] focus:shadow-black focus:outline-none"
          >
            Open Dialog
          </DialogTrigger>
          <DialogPortal>
            <DialogOverlay class="bg-blackA9 data-[state=open]:animate-overlayShow fixed inset-0 z-30" />
            <DialogContent
              class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none z-[100]"
            >
              <DialogTitle class="text-mauve12 m-0 text-[17px] font-semibold">
                First Dialog
              </DialogTitle>
              <DialogDescription class="text-mauve11 mt-[10px] mb-5 text-sm leading-normal">
                First dialog.
              </DialogDescription>

              <div class="mt-[25px] flex gap-4 justify-end">
                <DialogClose as-child>
                  <button
                    class="bg-green4 text-green11 hover:bg-green5 focus:shadow-green7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-semibold leading-none focus:shadow-[0_0_0_2px] focus:outline-none"
                  >
                    Close
                  </button>
                </DialogClose>

                <DialogRoot>
                  <DialogTrigger
                    class="bg-green9 font-semibold shadow-blackA7 hover:bg-green10  inline-flex h-[35px] items-center justify-center rounded-[4px] text-white px-[15px] leading-none shadow-[0_2px_10px] focus:shadow-[0_0_0_2px] focus:shadow-black focus:outline-none"
                  >
                    Open second
                  </DialogTrigger>

                  <DialogPortal>
                    <DialogOverlay class="bg-blackA9 data-[state=open]:animate-overlayShow fixed inset-0 z-30" />
                    <DialogContent
                      class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] bg-white p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none z-[100]"
                    >
                      <DialogTitle class="text-mauve12 m-0 text-[17px] font-semibold">
                        Second Dialog
                      </DialogTitle>
                      <DialogDescription class="text-mauve11 mt-[10px] mb-5 text-sm leading-normal">
                        Second dialog.
                      </DialogDescription>

                      <div class="flex justify-end">
                        <DialogClose as-child>
                          <button
                            class="bg-green4 text-green11 hover:bg-green5 focus:shadow-green7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-semibold leading-none focus:shadow-[0_0_0_2px] focus:outline-none"
                          >
                            Close
                          </button>
                        </DialogClose>
                      </div>
                    </DialogContent>
                  </DialogPortal>
                </DialogRoot>
              </div>
              <DialogClose
                class="text-grass11 hover:bg-green4 focus:shadow-green7 absolute top-[10px] right-[10px] inline-flex h-[25px] w-[25px] appearance-none items-center justify-center rounded-full focus:shadow-[0_0_0_2px] focus:outline-none"
                aria-label="Close"
              >
                <PIcon name="i-lucide-x" />
              </DialogClose>
            </DialogContent>
          </DialogPortal>
        </DialogRoot>
      </div>
  </div>
</template>
```

### Close after asynchronous form submission

Use the controlled props to programmatically close the Dialog after an async operation has completed.

```vue
<script setup>
import { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTrigger } from 'akar'

const wait = () => new Promise(resolve => setTimeout(resolve, 1000))
const open = ref(false)
</script>

<template>
  <DialogRoot v-model:open="open">
    <DialogTrigger>Open</DialogTrigger>
    <DialogPortal>
      <DialogOverlay />
      <DialogContent>
        <form
          @submit.prevent="
            (event) => {
              wait().then(() => (open = false));
            }
          "
        >
          <!-- some inputs -->
          <button type="submit">
            Submit
          </button>
        </form>
      </DialogContent>
    </DialogPortal>
  </DialogRoot>
</template>
```

### Scrollable overlay

Move the content inside the overlay to render a dialog with overflow.

```vue
// index.vue
<script setup>
import { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTrigger } from 'akar';
import './styles.css';
</script>

<template>
  <DialogRoot>
    <DialogTrigger />
    <DialogPortal>
      <DialogOverlay class="DialogOverlay">
        <DialogContent class="DialogContent">
          ...
        </DialogContent>
      </DialogOverlay>
    </DialogPortal>
  </DialogRoot>
</template>
```

```css
/* styles.css */
.DialogOverlay {
  background: rgba(0 0 0 / 0.5);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  place-items: center;
  overflow-y: auto;
}

.DialogContent {
  min-width: 300px;
  background: white;
  padding: 30px;
  border-radius: 4px;
}
```

However, there's a caveat to this approach, where user might click on the scrollbar and close the dialog unintentionally. There's no universal solution that would fix this issue for now, however you can add the following snippet to `DialogContent` to prevent closing of modal when clicking on scrollbar.

```vue
<DialogContent
  @pointer-down-outside="(event) => {
    const originalEvent = event.detail.originalEvent;
    const target = originalEvent.target as HTMLElement;
    if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
      event.preventDefault();
    }
  }"
>
```

### Custom portal container

Customise the element that your dialog portals into.

```vue
<script setup>
import { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTrigger } from 'akar'

const container = ref(null)
</script>

<template>
  <div>
    <DialogRoot>
      <DialogTrigger />
      <DialogPortal to="container">
        <DialogOverlay />
        <DialogContent>...</DialogContent>
      </DialogPortal>
    </DialogRoot>

    <div ref="container" />
  </div>
</template>
```

### Disable close on interaction outside

If a global toast (or similar overlay) should not dismiss the dialog when clicked, cancel `interact-outside` when the event target is inside that overlay.

```vue
<DialogContent
  @interact-outside="(event) => {
    const target = event.target as HTMLElement
    if (target?.closest('[data-sonner-toaster]')) event.preventDefault()
  }"
>
  …
</DialogContent>
```

## Accessibility

Adheres to the [Dialog WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/).

### Close icon button

When providing an icon (or font icon), remember to label it correctly for screen reader users.

```vue
<template>
  <DialogRoot>
    <DialogTrigger />
    <DialogPortal>
      <DialogOverlay />
      <DialogContent>
        <DialogTitle />
        <DialogDescription />
        <DialogClose aria-label="Close">
          <span aria-hidden="true">×
        </DialogClose>
      </DialogContent>
    </DialogPortal>
  </DialogRoot>
</template>
```

### Close using slot props

Alternatively, you can use the `close` method provided by the `DialogRoot` slot props to programmatically close the dialog.

```vue
<script setup>
import { DialogContent, DialogOverlay, DialogPortal, DialogRoot, DialogTrigger } from 'akar'
</script>

<template>
  <DialogRoot v-slot="{ close }">
    <DialogTrigger>Open</DialogTrigger>
    <DialogPortal>
      <DialogOverlay />
      <DialogContent>
        <form>
          <!-- some inputs -->
          <button type="submit" @click="close">
            Submit
          </button>
        </form>
      </DialogContent>
      <DialogFooter>
        <button type="submit" @click="close">
          Submit
        </button>
      </DialogFooter>
    </DialogPortal>
  </DialogRoot>
</template>
```

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>Space</kbd> | Opens/closes the dialog |
| <kbd>Enter</kbd> | Opens/closes the dialog |
| <kbd>Tab</kbd> | Moves focus to the next focusable element. |
| <kbd>Shift + Tab</kbd> | Moves focus to the previous focusable element. |
| <kbd>Esc</kbd> | Closes the dialog and moves focus to `DialogTrigger`. |

## Custom APIs

Create your own API by abstracting the primitive parts into your own component.

### Abstract the overlay and the close button

This example abstracts the `DialogOverlay` and `DialogClose` parts.

#### Usage

```vue
<script setup>
import { Dialog, DialogContent, DialogTrigger } from './your-dialog';
</script>

<template>
  <Dialog>
    <DialogTrigger>Dialog trigger</DialogTrigger>
    <DialogContent>Dialog Content</DialogContent>
  </Dialog>
</template>
```

#### Implementation

```ts
export { DialogRoot as Dialog, DialogTrigger } from 'akar';
// your-dialog.ts
export { default as DialogContent } from 'DialogContent.vue';
```

```vue
<!-- DialogContent.vue -->
<script setup lang="ts">
import type { DialogContentEmits, DialogContentProps } from 'akar';
import { Cross2Icon } from '@radix-icons/vue';
import { DialogClose, DialogContent, DialogOverlay, DialogPortal, useForwardPropsEmits } from 'akar';

const props = defineProps<DialogContentProps>();
const emits = defineEmits<DialogContentEmits>();

const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
  <DialogPortal>
    <DialogOverlay />
    <DialogContent v-bind="forwarded">
      <slot />

      <DialogClose>
        <Cross2Icon />
        <span class="sr-only">Close
        </span>
      </DialogClose>
    </DialogContent>
  </DialogPortal>
</template>
```

---

- [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal)
- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Dialog)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
