Vue Final Modal 5 rebuilds useModal() on vue-use-template and keeps the 4.x API. createVfm(), <ModalsContainer />, useModal() with open() / close(), useVfm(), useModalSlot(), $vfm, and the props, events and slots of <VueFinalModal> all work as before, so for most apps the upgrade is a version bump.
Highlights
<VueFinalDialog>: a headless modal built on the native<dialog>element. See VueFinalDialog.useModalLifecycle(): build your own modal component foruseModal(). See useModalLifecycle().- Reactive options:
attrs,propsandemitsofuseModal()accept aref,computedor getter, and the modal stays in sync. - SSR: a modal opened while a component sets up is part of the server HTML and hydrates already open, with no enter transition on the first paint.
- Promises that always settle:
open()andclose()resolve with'opened'or'closed'once the transition has finished, or with the reason they did not get there, such as'stopped'or'destroyed'. - Status:
useModal(),vfm.get(modalId)anduseModalLifecycle()report'closed','opening','opened'or'closing'. - CommonJS build:
require('vue-final-modal')loads a CommonJS build with its own.d.ctstypes. The UMD build is still there for CDNs.
<VueFinalDialog> and useModalLifecycle() are opt-in: <VueFinalModal> stays the default component of useModal().
Breaking changes
- Peer dependencies:
@vueuse/core,@vueuse/integrationsandfocus-trapare peer dependencies, and Vue 3.3 or later is required. npm and pnpm install them for you; with Yarn, add them yourself. - Nuxt module:
@vue-final-modal/nuxtis no longer published. Remove it and usemodules: ['vue-final-modal/nuxt']. The module now auto-imports the components and composables; if another module or your owncomposables/uses the same names, setvueFinalModal: { autoImports: false }. - Removed APIs:
vfm.dynamicModals,useModal().options,patchOptions()andgetModalExposed(). Use reactiveattrsinstead ofpatchOptions(), and a separateuseModal()instead of swapping thecomponentof an existing modal. - Promise results:
'[Vue Final Modal] modal is already opened.'and'[Vue Final Modal] modal is already closed.'are now'already-opened'and'already-closed', and anopen()called while the modal is opening waits for that opening. focusTrap: your options are merged over{ allowOutsideClick: true, escapeDeactivates: false }instead of replacing the defaults.- Scroll lock: @hunterliu/scroll-lock replaces the vendored body-scroll-lock and also locks the scroll container a modal is rendered in.
- Server:
open()outside any app context is ignored with a warning, and a modal opened from a Nuxt plugin or route middleware opens in the browser once the app has mounted. A server that polyfillswindowcallsmarkServer()before it renders; the Nuxt module does this for you.
The migration guide walks through each change with code examples.
vue-use-template and @hunterliu/scroll-lock are now developed in this repository, next to vue-final-modal.