Skip to main content
Vuetify0 is now a release candidate!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

AlertDialog

A headless confirmation dialog that seeks user input before proceeding. Features a wait()/close() pattern for deferred close during async operations.

Usage

AlertDialog mirrors Dialog but with stricter defaults: no close on click outside, no close on escape. The Action component provides a deferred close pattern for async confirmation flows.

Are you sure?

This action cannot be undone.

This will permanently delete the item and all associated data. You will not be able to recover it.

<script setup lang="ts">
  import { AlertDialog } from '@vuetify/v0'
</script>

<template>
  <div class="flex justify-center">
    <AlertDialog.Root>
      <AlertDialog.Activator class="px-4 py-2 bg-error text-on-error rounded-md text-sm font-medium">
        Delete Item
      </AlertDialog.Activator>

      <AlertDialog.Content class="m-auto rounded-xl bg-surface border border-divider max-w-md w-full">
        <div class="px-4 py-2 border-b border-divider">
          <AlertDialog.Title as="h3" class="text-lg font-semibold text-on-surface">
            Are you sure?
          </AlertDialog.Title>

          <AlertDialog.Description class="text-sm text-on-surface-variant">
            This action cannot be undone.
          </AlertDialog.Description>
        </div>

        <div class="p-4 space-y-4">
          <p class="text-sm text-on-surface leading-relaxed">
            This will permanently delete the item and all associated data.
            You will not be able to recover it.
          </p>
        </div>

        <div class="flex gap-3 justify-end p-4 pt-0">
          <AlertDialog.Cancel class="px-4 py-2 text-sm font-medium rounded-md border border-divider hover:bg-surface-tint">
            Cancel
          </AlertDialog.Cancel>

          <AlertDialog.Action class="px-4 py-2 text-sm font-medium rounded-md bg-error text-on-error">
            Delete
          </AlertDialog.Action>
        </div>
      </AlertDialog.Content>
    </AlertDialog.Root>
  </div>
</template>

Anatomy

vue
<script setup lang="ts">
  import { AlertDialog } from '@vuetify/v0'
</script>

<template>
  <AlertDialog.Root>
    <AlertDialog.Activator />
    <AlertDialog.Content>
      <AlertDialog.Title />
      <AlertDialog.Description />
      <AlertDialog.Close />
      <AlertDialog.Cancel />
      <AlertDialog.Action />
    </AlertDialog.Content>
  </AlertDialog.Root>
</template>

Examples

Destructive delete confirmation

This flow wraps the full AlertDialog surface around an async operation. Every project row renders its own AlertDialog.Root: the Activator opens the modal, AlertDialog.Action drives the destructive confirm, and AlertDialog.Cancel dismisses it. The load-bearing API is the @action event — calling e.wait() at the top of the handler holds the dialog open while the mocked delete runs, and e.close() resolves it once the promise settles.

The Root slot exposes isPending, which flips to true the moment wait() is called. Binding it to :disabled on both the Action and Cancel buttons locks the dialog for the duration of the request, so a slow network can’t be double-submitted and a half-finished delete can’t be dismissed. Because AlertDialog already blocks Escape and click-outside by default, isPending is the only extra state you need — no separate loading ref, no manual open/close bookkeeping. Styling hooks off the emitted data-disabled attribute rather than a JS class binding.

Reach for this pattern whenever an accidental confirm is expensive or irreversible — permanent deletes, billing changes, irreversible writes. For non-destructive flows where dismissal is harmless (settings, informational content), a plain Dialog is the lighter choice; Popover covers non-modal disclosure.

FileRole
useDeleteProject.tsOwns the project list and the mocked async delete that drops a project after a short delay
DeleteProjectDialog.vueReusable confirmation dialog — wires @action to wait()/close() and disables its buttons while isPending
delete-project-dialog.vueEntry — renders the project list and mounts a dialog per row
  • marketing-site

    Production

    Delete marketing-site?

    This permanently removes the Production project and every deployment attached to it. This action cannot be undone.

  • api-gateway

    Production

    Delete api-gateway?

    This permanently removes the Production project and every deployment attached to it. This action cannot be undone.

  • design-tokens

    Preview

    Delete design-tokens?

    This permanently removes the Preview project and every deployment attached to it. This action cannot be undone.

  • legacy-dashboard

    Archived

    Delete legacy-dashboard?

    This permanently removes the Archived project and every deployment attached to it. This action cannot be undone.

Accessibility

AlertDialog uses role="alertdialog" instead of role="dialog", signaling to assistive technologies that the dialog requires an immediate response.

Keyboard interaction

KeyBehavior
TabMoves focus between Cancel and Action buttons
EscapeBlocked by default (opt-in via closeOnEscape prop)
Enter / SpaceActivates the focused button

Focus management

Focus moves to the Cancel button on open, as it represents the safest action. This follows the WAI-ARIA alertdialog pattern where destructive actions should not receive initial focus.

FAQ

Discord
Need help? Join our community for support and discussions ↗
Was this page helpful?

Ctrl+/