Alert Dialog
Opinionated alert-dialog compound primitive built on Dialog.
|
|
| Package |
@vizejs/ui/alert-dialog |
| Maturity |
stable |
| Own the source |
vize lib pull alert-dialog |
| Requires |
context, dialog, dismissable-layer, focus-guards, focus-scope, inert-outside, scroll-lock |
| Aliases |
confirm dialog, destructive confirmation, modal alertdialog |
| Covers |
WAI-ARIA alertdialog pattern, Radix Alert Dialog, Reka UI AlertDialog |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { AlertDialog, AlertDialogRoot, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger } from "@vizejs/ui/alert-dialog";
Or copy the source into your project with vize lib pull alert-dialog (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Destructive confirmation that only closes through its explicit Cancel or Delete actions. -->
<script setup lang="ts">
import { ref } from "vue";
import {
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogRoot,
AlertDialogTitle,
AlertDialogTrigger,
} from "@vizejs/ui/alert-dialog";
const open = ref(false);
const deleted = ref(false);
</script>
<template>
<div>
<AlertDialogRoot v-model:open="open">
<AlertDialogTrigger>Delete project</AlertDialogTrigger>
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogContent>
<AlertDialogTitle>Delete project?</AlertDialogTitle>
<AlertDialogDescription>
This permanently removes the project and all of its deployments.
</AlertDialogDescription>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction @click="() => (deleted = true)">Delete</AlertDialogAction>
</AlertDialogContent>
</AlertDialogPortal>
</AlertDialogRoot>
<output>{{ deleted ? "Project deleted" : "Project kept" }}</output>
</div>
</template>
API
AlertDialog
Source: src/families/overlays/dialog/dialog-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned Dialog base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use. |
modal |
boolean |
true |
Whether the dialog makes outside content inert, focus-contained, and scroll-locked. |
Events
| Event |
Payload |
Description |
update:open |
[value: boolean] |
Fired when the Dialog requests a controlled open value. |
open-change |
[value: boolean, previous: boolean, nativeEvent: Event | null] |
Fired after any distinct open-state request. |
exit-complete |
[] |
Fired once when an open dialog has fully closed, including without exit motion. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState |
Compound Dialog children. Receives the current open and modal state. |
Exposed
| Member |
Type |
Description |
close |
— |
|
contentId |
— |
|
descriptionId |
— |
|
id |
— |
|
modal |
— |
|
open |
— |
|
openDialog |
— |
|
setOpen |
— |
|
state |
— |
|
titleId |
— |
|
toggle |
— |
|
AlertDialogRoot
Source: src/families/overlays/dialog/dialog-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned Dialog base id. null and undefined select a deterministic fallback. |
open |
boolean |
undefined |
Controlled open state. undefined selects uncontrolled behavior. |
defaultOpen |
boolean |
false |
Initial open state for uncontrolled use. |
modal |
boolean |
true |
Whether the dialog makes outside content inert, focus-contained, and scroll-locked. |
Events
| Event |
Payload |
Description |
update:open |
[value: boolean] |
Fired when the Dialog requests a controlled open value. |
open-change |
[value: boolean, previous: boolean, nativeEvent: Event | null] |
Fired after any distinct open-state request. |
exit-complete |
[] |
Fired once when an open dialog has fully closed, including without exit motion. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState |
Compound Dialog children. Receives the current open and modal state. |
Exposed
| Member |
Type |
Description |
close |
— |
|
contentId |
— |
|
descriptionId |
— |
|
id |
— |
|
modal |
— |
|
open |
— |
|
openDialog |
— |
|
setOpen |
— |
|
state |
— |
|
titleId |
— |
|
toggle |
— |
|
AlertDialogAction
Source: src/families/overlays/dialog/dialog-close.vue
Props
| Prop |
Type |
Default |
Description |
type |
"button" | "reset" | "submit" |
"button" |
Native button submission behavior. |
disabled |
boolean |
false |
Remove the close button from activation and sequential keyboard focus. |
ariaLabel |
string |
undefined |
Accessible name when no visible label supplies one. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the button requests closing. Call preventDefault() to keep state unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState & { readonly disabled: boolean } |
Close button contents. Receives the current Dialog state and button availability. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
AlertDialogCancel
Source: src/families/overlays/dialog/dialog-close.vue
Props
| Prop |
Type |
Default |
Description |
type |
"button" | "reset" | "submit" |
"button" |
Native button submission behavior. |
disabled |
boolean |
false |
Remove the close button from activation and sequential keyboard focus. |
ariaLabel |
string |
undefined |
Accessible name when no visible label supplies one. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the button requests closing. Call preventDefault() to keep state unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState & { readonly disabled: boolean } |
Close button contents. Receives the current Dialog state and button availability. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
AlertDialogContent
Source: src/families/overlays/alert-dialog/alert-dialog-content.vue
Props
| Prop |
Type |
Default |
Description |
forceMount |
boolean |
false |
Keep content mounted while closed. |
trapFocus |
boolean |
true |
Contain focus inside an open modal alert dialog. |
autoFocus |
boolean |
true |
Move focus into content when it opens. |
restoreFocus |
boolean |
true |
Restore focus when content closes. |
inertOutside |
boolean |
true |
Make outside content inert while the modal alert dialog is open. |
lockScroll |
boolean |
true |
Lock document scroll while the modal alert dialog is open. |
closeOnEscape |
boolean |
true |
Let Escape request dismissal. |
closeOnPointerDownOutside |
boolean |
false |
Let outside pointer-down request dismissal. |
closeOnFocusOutside |
boolean |
false |
Let outside focus movement request dismissal. |
ariaLabel |
string |
undefined |
Accessible name when no visible title supplies one. |
ariaLabelledby |
string | null |
undefined |
Space-separated ids that label the alert dialog. null omits the default title id. |
ariaDescribedby |
string | null |
undefined |
Space-separated ids that describe the alert dialog. null omits the default description id. |
Events
| Event |
Payload |
Description |
open-auto-focus |
[event: DialogAutoFocusEvent] |
Fired before automatic entry focus is applied. |
close-auto-focus |
[event: DialogAutoFocusEvent] |
Fired before automatic focus restoration is applied. |
escape-key-down |
[event: DismissableLayerEscapeKeyDownEvent] |
Fired before Escape requests dismissal. |
pointer-down-outside |
[event: DismissableLayerPointerDownOutsideEvent] |
Fired before an outside pointer-down requests dismissal. |
focus-outside |
[event: DismissableLayerFocusOutsideEvent] |
Fired before outside focus movement requests dismissal. |
interact-outside |
[event: DismissableLayerInteractOutsideEvent] |
Fired before outside pointer or focus interaction requests dismissal. |
dismiss |
[event: DismissableLayerDismissEvent] |
Fired after an unprevented dismissal request. |
Slots
| Slot |
Slot props |
Description |
default |
AlertDialogSlotState |
AlertDialog content. Receives the current open and modal state. |
Exposed
| Member |
Type |
Description |
open |
boolean |
Whether the dialog content is currently visible and interactive. |
modal |
boolean |
Whether outside content is inert, focus-contained, and scroll-locked. |
state |
DialogState |
Stable state token for styling and tests. |
element |
HTMLDivElement | null |
Rendered dialog content element. |
focusFirst |
() => HTMLElement | null |
Focus the first eligible descendant in the dialog content. |
focusContent |
(options?: FocusOptions) => void |
Move focus to the content fallback target. |
AlertDialogDescription
Source: src/families/overlays/dialog/dialog-description.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned description id. null and undefined use the Dialog default. |
as |
PrimitiveAs |
"p" |
Native element, custom element, or component to render. |
Slots
| Slot |
Slot props |
Description |
default |
— |
Visible Dialog description. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
AlertDialogOverlay
Source: src/families/overlays/dialog/dialog-overlay.vue
Props
| Prop |
Type |
Default |
Description |
forceMount |
boolean |
false |
Keep the overlay mounted while the dialog is closed. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState |
Optional overlay contents. Receives the current Dialog state. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
modal |
— |
|
open |
— |
|
state |
— |
|
AlertDialogPortal
Source: src/families/overlays/dialog/dialog-portal.vue
Props
| Prop |
Type |
Default |
Description |
to |
string | HTMLElement |
"body" |
CSS selector or element the dialog layer is moved into. |
disabled |
boolean |
false |
Render in place instead of teleporting. |
defer |
boolean |
true |
Keep content in place until the target exists, avoiding SSR mismatch. |
forceMount |
boolean |
false |
Keep the portal host mounted while the dialog is closed. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState |
Portalled Dialog layer contents. |
Exposed
| Member |
Type |
Description |
modal |
— |
|
open |
— |
|
present |
— |
|
state |
— |
|
AlertDialogTitle
Source: src/families/overlays/dialog/dialog-title.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned title id. null and undefined use the Dialog default. |
as |
PrimitiveAs |
"h2" |
Native element, custom element, or component to render. |
Slots
| Slot |
Slot props |
Description |
default |
— |
Visible Dialog title. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
AlertDialogTrigger
Source: src/families/overlays/dialog/dialog-trigger.vue
Props
| Prop |
Type |
Default |
Description |
type |
"button" | "reset" | "submit" |
"button" |
Native button submission behavior. |
disabled |
boolean |
false |
Remove the trigger from activation and sequential keyboard focus. |
ariaLabel |
string |
undefined |
Accessible name when no visible label supplies one. |
Events
| Event |
Payload |
Description |
click |
[nativeEvent: MouseEvent] |
Fired before the trigger requests opening. Call preventDefault() to keep state unchanged. |
Slots
| Slot |
Slot props |
Description |
default |
DialogSlotState & { readonly disabled: boolean } |
Trigger contents. Receives the current Dialog state and trigger availability. |
Exposed
| Member |
Type |
Description |
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
focus |
— |
|
Behavior
Normative state x input -> outcome table for alert-dialog-content.vue
(@vizejs/ui/alert-dialog). Every row is proven by the named mounted-DOM, SSR,
or compile-time test.
| Surface |
Contract |
| Root |
AlertDialogRoot reuses Dialog controlled/uncontrolled state, deterministic ids, modal defaults, and slot/expose state. |
| Content |
AlertDialogContent renders Dialog content with fixed role="alertdialog" and publishes an alert-dialog-content styling wrapper. |
| Dismissal |
Outside pointer and focus dismissal are disabled by default; Escape and explicit action/cancel buttons may request closing. |
| Labelling |
Title and description aliases keep Dialog deterministic id wiring for aria-labelledby and aria-describedby. |
| Styling |
No component CSS is emitted beyond a scoped empty block; data-vize-ui, part, and data-state are the contract. |
| Packaging |
Root and subpath consumers retain only AlertDialog plus required Dialog overlay utilities with zero CSS. |
| State x input |
Outcome |
Proven by |
| trigger click |
Opens modal content with native role="alertdialog" and title/description id wiring. |
opens as a labelled modal alertdialog with explicit close actions |
| outside pointer-down by default |
Leaves the alert dialog open so destructive confirmations are not dismissed by backdrop accidents. |
opens as a labelled modal alertdialog with explicit close actions |
| cancel or action click |
Uses Dialog close semantics and restores focus to the trigger. |
opens as a labelled modal alertdialog with explicit close actions |
| opted-in outside pointer-down |
Emits the preventable outside event and closes when the event is not canceled. |
can opt into outside pointer dismissal |
| SSR/hydration |
Server markup is deterministic and contains no document-controller listeners or scroll-lock effects. |
renders deterministic alertdialog markup on the server |
| public types and consumer bundle |
TypeScript rejects a custom role, while root and subpath imports emit equivalent zero-CSS bundles. |
src/families/overlays/alert-dialog/alert-dialog.types.test-d.ts, scripts/check-tree-shaking.mjs |