Vue Final Modal
Use Cases

Modal in a Dialog

Open a <VueFinalModal> confirm from inside a <VueFinalDialog>.

A modal <dialog> makes everything outside it inert, so a <VueFinalModal> teleported to the <body> could not be used on top of it. A <VueFinalModal> that opens while a <VueFinalDialog> is open is rendered inside the dialog instead, so the confirm below just works:

  • Change the name and click Discard: the confirm from Await a Confirm opens on top of the dialog. Confirm drops the change, and Save keeps it.
  • Press Esc: only the confirm closes. Press it again to close the dialog.

See Next to <VueFinalModal> for the details.

Preview

Name: Hunter
Preview.vue
  <script setup lang="ts">
  import { VueFinalDialog } from 'vue-final-modal'

  const initialName = 'Hunter'
  const name = ref(initialName)
  const draft = ref('')
  const show = ref(false)
  const confirm = useConfirm()

  function edit() {
    draft.value = name.value
    show.value = true
  }

  function save() {
    name.value = draft.value
    show.value = false
  }

  async function discard() {
    if (draft.value === name.value || await confirm('Discard your changes?'))
      show.value = false
  }
  </script>

  <template>
    <div class="flex flex-wrap items-center justify-center gap-3">
      <VButton @click="edit">
        Edit Profile
      </VButton>
      <output class="inline-flex items-center gap-1.5 rounded-md border border-default px-2 py-1 text-sm text-muted">
        Name: <span class="font-medium text-highlighted">{{ name }}</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="name === initialName" @click="name = initialName">
        Reset
      </button>
    </div>

    <VueFinalDialog
      v-model="show"
      aria-labelledby="modal-in-dialog-title"
      class="m-auto w-[calc(100%-2rem)] max-w-md p-4 rounded-lg border bg-white text-gray-900 dark:bg-gray-900 dark:text-white dark:border-gray-700 backdrop:bg-black/50"
    >
      <div class="flex flex-col gap-2">
        <h2 id="modal-in-dialog-title" class="text-xl">
          Edit profile
        </h2>
        <input v-model="draft" aria-label="Name" class="px-2 py-1 border rounded-lg bg-transparent">
        <div class="flex justify-end gap-2">
          <button type="button" class="px-2 border rounded-lg" @click="discard">
            Discard
          </button>
          <button type="button" class="px-2 border rounded-lg" @click="save">
            Save
          </button>
        </div>
      </div>
    </VueFinalDialog>
  </template>
Copyright © 2026