Skip to content

Alert Dialog

A modal dialog that interrupts the user with important content and expects a response.
vue
<script setup lang="ts">
import {
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogOverlay,
  AlertDialogPortal,
  AlertDialogRoot,
  AlertDialogTitle,
  AlertDialogTrigger,
} from 'radix-vue'

function handleAction() {
  alert('clicked action button!')
}
</script>

<template>
  <AlertDialogRoot>
    <AlertDialogTrigger
      class="bg-white text-grass11 font-semibold hover:bg-white/90 shadow-sm inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] leading-none outline-none focus:shadow-[0_0_0_2px] focus:shadow-black transition-all"
    >
      Delete account
    </AlertDialogTrigger>
    <AlertDialogPortal>
      <AlertDialogOverlay class="bg-blackA9 data-[state=open]:animate-overlayShow fixed inset-0 z-30" />
      <AlertDialogContent
        class="z-[100] text-[15px] data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[500px] 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"
      >
        <AlertDialogTitle class="text-mauve12 m-0 text-[17px] font-semibold">
          Are you absolutely sure?
        </AlertDialogTitle>
        <AlertDialogDescription class="text-mauve11 mt-4 mb-5 text-[15px] leading-normal">
          This action cannot be undone. This will permanently delete your account and remove your data from our servers.
        </AlertDialogDescription>
        <div class="flex justify-end gap-[25px]">
          <AlertDialogCancel
            class="text-mauve11 bg-mauve4 hover:bg-mauve5 focus:shadow-mauve7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-semibold leading-none outline-none focus:shadow-[0_0_0_2px]"
          >
            Cancel
          </AlertDialogCancel>
          <AlertDialogAction
            class="text-red11 bg-red4 hover:bg-red5 focus:shadow-red7 inline-flex h-[35px] items-center justify-center rounded-[4px] px-[15px] font-semibold leading-none outline-none focus:shadow-[0_0_0_2px]"
            @click="handleAction"
          >
            Yes, delete account
          </AlertDialogAction>
        </div>
      </AlertDialogContent>
    </AlertDialogPortal>
  </AlertDialogRoot>
</template>

Features

  • Focus is automatically trapped.
  • 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
npm install radix-vue

Anatomy

Import all parts and piece them together.

vue
<script setup lang="ts">
import {
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogOverlay,
  AlertDialogPortal,
  AlertDialogRoot,
  AlertDialogTitle,
  AlertDialogTrigger,
} from 'radix-vue'
</script>

<template>
  <AlertDialogRoot>
    <AlertDialogTrigger />
    <AlertDialogPortal>
      <AlertDialogOverlay />
      <AlertDialogContent>
        <AlertDialogTitle />
        <AlertDialogDescription />
        <AlertDialogCancel />
        <AlertDialogAction />
      </AlertDialogContent>
    </AlertDialogPortal>
  </AlertDialogRoot>
</template>

API Reference

Root

Contains all the parts of an alert dialog.

PropDefaultType
defaultOpen
boolean

The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.

open
boolean

The controlled open state of the dialog. Can be binded with `v-model`.

EmitType
@update:open
(open: boolean) => void

Trigger

A button that opens the dialog.

PropDefaultType
as
trigger
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data AttributeValue
[data-state]"open" | "closed"

Portal

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

PropDefaultType
to
body
string | HTMLElement

Vue native teleport component props. (to)

Overlay

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

PropDefaultType
as
div
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

forceMount
boolean

Used to force mounting when more control is needed. Useful when controlling animation with Vue.js animation libraries.

Data AttributeValue
[data-state]"open" | "closed"

Content

Contains content to be rendered when the dialog is open.

PropDefaultType
as
div
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

forceMount
boolean

Used to force mounting when more control is needed. Useful when controlling animation with Vue.js animation libraries.

EmitType
@openAutoFocus
(event: Event) => void
@closeAutoFocus
(event: Event) => void
@escapeKeyDown
(event: KeyboardEvent) => void
Data AttributeValue
[data-state]"open" | "closed"

Cancel

A button that closes the dialog. This button should be distinguished visually from AlertDialogAction buttons.

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Action

A button that closes the dialog. These buttons should be distinguished visually from the AlertDialogCancel button.

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Title

An accessible name to be announced when the dialog is opened. Alternatively, you can provide aria-label or aria-labelledby to AlertDialogContent and exclude this component.

PropDefaultType
as
h2
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Description

An accessible description to be announced when the dialog is opened. Alternatively, you can provide aria-describedby to AlertDialogContent and exclude this component.

PropDefaultType
as
p
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Examples

Close after asynchronous form submission

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

vue
<script setup>
import {
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogOverlay,
  AlertDialogPortal,
  AlertDialogRoot,
  AlertDialogTitle,
  AlertDialogTrigger,
} from 'radix-vue'

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

<template>
  <AlertDialogRoot v-model:open="open">
    <AlertDialogTrigger>Open</AlertDialogTrigger>
    <AlertDialogPortal>
      <AlertDialogOverlay />
      <AlertDialogContent>
        <form
          @submit.prevent="
            (event) => {
              wait().then(() => open = false);
            }
          "
        >
          <!-- some inputs -->
          <button type="submit">
            Submit
          </button>
        </form>
      </AlertDialogContent>
    </AlertDialogPortal>
  </AlertDialogRoot>
</template>

Custom portal container

Customise the element that your alert dialog portals into.

vue
<script setup>
import { ref } from 'vue'

const container = ref(null)
</script>

<template>
  <div>
    <AlertDialogRoot>
      <AlertDialogTrigger />
      <AlertDialogPortal :to="container">
        <AlertDialogOverlay />
        <AlertDialogContent>...</AlertDialogContent>
      </AlertDialogPortal>
    </AlertDialogRoot>

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

Accessibility

Adheres to the Alert and Message Dialogs WAI-ARIA design pattern.

Keyboard Interactions

KeyDescription
Space
Opens/closes the dialog.
Enter
Opens/closes the dialog.
Tab
Moves focus to the next focusable element.
Shift + Tab
Moves focus to the previous focusable element.
Esc
Closes the dialog and moves focus to AlertDialogTrigger.