Vize

use-confirm-dialog

Promise-based confirm dialog state machine (idle → revealed → idle), independent of any dialog markup.

Package @vizejs/composable/use-confirm-dialog
Own the source vize lib pull composable:use-confirm-dialog
Runtime exports useConfirmDialog
Gzip budget 2304 B

Minimal setup

Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).

vp install @vizejs/composable

Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.

import { useConfirmDialog } from "@vizejs/composable/use-confirm-dialog";

Try it

Confirm before deleting a draft

Await the reader's decision in the middle of an action instead of splitting it across callbacks.

Open the interactive example

What to observe: Delete draft reveals the confirmation. Keep draft reports Kept the draft; Delete reports Deleted the draft.

reveal() returns a promise for { isCanceled, data }. Render the dialog yourself; the composable only manages its state.

Compare the initial and interacted states
Confirm before deleting a draft: initial state
Initial state
Confirm before deleting a draft: state after the verified interactions
After the verified interactions

Copy the example

Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.

<script setup lang="ts">
import { ref } from "vue";
import { useConfirmDialog } from "@vizejs/composable/use-confirm-dialog";

const { isRevealed, reveal, confirm, cancel } = useConfirmDialog();
const message = ref("The draft is saved.");

async function deleteDraft() {
  const { isCanceled } = await reveal();
  message.value = isCanceled ? "Kept the draft." : "Deleted the draft.";
}
</script>

<template>
  <div class="composable-example">
    <p>Ask before a destructive action and continue with the reader's answer.</p>
    <button type="button" :disabled="isRevealed" @click="deleteDraft">Delete draft</button>
    <div v-if="isRevealed" role="alertdialog" aria-label="Delete the draft?">
      <p>Delete the draft? This cannot be undone.</p>
      <div class="example-actions">
        <button type="button" @click="() => confirm()">Delete</button>
        <button type="button" @click="() => cancel()">Keep draft</button>
      </div>
    </div>
    <output aria-live="polite">{{ message }}</output>
  </div>
</template>

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
useConfirmDialog state experimental safe stable reactive-scope web, server, worker, native, desktop, terminal — createEventHook

API

useConfirmDialog

Promise-based confirm dialog state machine (idle → revealed → idle), independent of any dialog markup. reveal() resolves with a discriminated result, so if (!result.isCanceled) narrows data to the confirm payload. Payload types are declared as type parameters; void payloads take no argument. Pair it with a native <dialog> or any headless dialog. Synchronous state: SSR-safe; listeners registered inside a scope are removed with it.

function useConfirmDialog< RevealData = void, ConfirmData = void, CancelData = void, >(): ConfirmDialog<RevealData, ConfirmData, CancelData>
const dialog = useConfirmDialog<{ name: string }, "keep" | "delete">();
const result = await dialog.reveal({ name: file.name });
if (!result.isCanceled && result.data === "delete") remove(file);

useConfirmDialog

function useConfirmDialog(): ConfirmDialog<unknown, unknown, unknown>

Types

ConfirmDialog

Dialog state machine returned by useConfirmDialog.

Member Type Description
state Readonly<ShallowRef<ConfirmDialogState>> "revealed" between reveal() and confirm()/cancel().
isRevealed Readonly<ShallowRef<boolean>> Shorthand for state === "revealed".
reveal ( ...payload: ConfirmDialogPayload<RevealData> ) => Promise<ConfirmDialogResult<ConfirmData, CancelData>> Open the dialog. While already revealed, returns the pending promise without re-firing onReveal.
confirm (...payload: ConfirmDialogPayload<ConfirmData>) => boolean Confirm the revealed dialog.
cancel (...payload: ConfirmDialogPayload<CancelData>) => boolean Cancel the revealed dialog.
onReveal ( listener: EventHookListener<ConfirmDialogPayload<RevealData>>, ) => EventHookSubscription Listen for reveals.
onConfirm ( listener: EventHookListener<ConfirmDialogPayload<ConfirmData>>, ) => EventHookSubscription Listen for confirmations.
onCancel ( listener: EventHookListener<ConfirmDialogPayload<CancelData>>, ) => EventHookSubscription Listen for cancellations.