Vue Final Modal
Use Cases

Await a Confirm

Ask for a confirmation with useModal() and await the answer.

A useConfirm() composable wraps useModal(), so await confirm('Delete this item?') gives true or false. The answer comes once the modal has closed: Confirm, Cancel, Esc and a click outside all end in closed. open() always resolves, with 'opened' or a message, so a confirm that did not open answers false.

Preview

Result: not asked yet
Preview.vue
  <script setup lang="ts">
  const initialResult = 'not asked yet'
  const confirm = useConfirm()
  const result = ref(initialResult)

  async function deleteItem() {
    result.value = await confirm('Delete this item?') ? 'Deleted' : 'Kept'
  }
  </script>

  <template>
    <div class="flex flex-wrap items-center justify-center gap-3">
      <VButton @click="deleteItem">
        Delete Item
      </VButton>
      <output class="inline-flex items-center gap-1.5 rounded-md border border-default px-2 py-1 text-sm text-muted">
        Result: <span class="font-medium text-highlighted">{{ result }}</span>
      </output>
      <button type="button" class="rounded-md border border-default px-2 py-1 text-sm text-muted hover:bg-elevated/50 hover:text-highlighted disabled:pointer-events-none disabled:opacity-50" :disabled="result === initialResult" @click="result = initialResult">
        Reset
      </button>
    </div>
  </template>

useConfirm() composable

  import { useModal } from 'vue-final-modal'
  import ModalAwaitConfirm from '~/components/content/ModalAwaitConfirm.vue'

  export function useConfirm() {
    const title = ref('')
    let confirmed = false
    let answer: (confirmed: boolean) => void = () => {}

    const { open, close } = useModal({
      component: ModalAwaitConfirm,
      attrs: {
        title,
        onConfirm() {
          confirmed = true
          close()
        },
        onCancel() {
          close()
        },
        onClosed() {
          answer(confirmed)
        },
      },
    })

    return async function confirm(message: string): Promise<boolean> {
      title.value = message
      confirmed = false
      const answered = new Promise<boolean>(resolve => answer = resolve)
      if (await open() !== 'opened')
        return false
      return answered
    }
  }
Copyright © 2026