Resources

Migration from v1

Step-by-step guide to upgrading from @kolirt/vue-modal v1 to v2.

Migration from v1

v2 is a ground-up rewrite. The imperative promise-based approach stays, but nearly every API surface changed. Plan an afternoon — the migration is mechanical, not architectural.

Breaking changes at a glance

Areav1v2
Source layoutlib/ flatpackages/core/src/
Plugin optionscreateModal(Options) (animation, style)createModal({ groups }) (behavior per group)
Groupsoptional 'default' implicitmandatory; declared via ModalGroupRegistry
openModal signatureopenModal(Component, props, options?)openModal(Component, options?) — props inside options.props
Confirm / close inside modalglobal confirmModal(data) / closeModal()useModalContext().confirm(data) / .close()
Event bus$on / $off / $emit from event.tsremoved; replaced by options.on map and ModalHandle.on/off
Template component<ModalTarget group="…"> + scoped slot / BaseModal<ModalTarget group="…"> wrapping your <ModalRoot>…<ModalContent>
Built-in layoutSimpleModal shippedremoved; headless only
TypeScript groupsuntyped stringsdeclare module '@kolirt/vue-modal' { interface ModalGroupRegistry { … } }
Peer depsnonereka-ui >=2, vue >=3.4

Step-by-step checklist

1. Install the new peer dependency

npm install reka-ui@^2

2. Update the plugin registration

import { createModal } from '@kolirt/vue-modal'

app.use(createModal({
  transitionTime: 300,
  animationType: 'slideDown',
  modalStyle: { align: 'center' }
}))

Animation and style options are removed. Apply CSS transitions directly on <ModalContent>.

3. Declare groups in TypeScript

Add a global augmentation file (e.g., src/modal-groups.d.ts):

import type { DefineGroups } from '@kolirt/vue-modal'

declare module '@kolirt/vue-modal' {
  interface ModalGroupRegistry extends DefineGroups<['default', 'confirm']> {}
}

Every group value in openModal, <ModalTarget>, and createModal is now checked at compile time.

4. Update openModal call sites

await openModal(ConfirmDialog, { title: 'Delete?' }, { group: 'confirm' })

Props are now inside options.props. The standalone second argument is gone.

5. Replace confirmModal / closeModal inside modal components

import { confirmModal, closeModal } from '@kolirt/vue-modal'

async function onConfirm() {
  await confirmModal(true)
}
async function onCancel() {
  await closeModal()
}

6. Replace $on / $off event bus usage

import { $on, $off } from '@kolirt/vue-modal'
import { Events } from '@kolirt/vue-modal'

$on(Events.Closed, handler)

The global event bus ($on, $off, $emit, Events enum) is removed.

7. Rewrite modal template components

v1 used BaseModal internally with a scoped slot. v2 is fully headless — you compose <ModalRoot><ModalContent> yourself.

<ModalTarget group="default">
  <template #default="{ modal, close }">
    <div class="modal-wrapper">
      <component :is="modal.component" v-bind="modal.props" @close="close" />
    </div>
  </template>
</ModalTarget>

The <ModalTarget> in v2 renders modals automatically from the <ModalRoot> / <ModalContent> in each modal component. No scoped slot needed.

Modal components must now include <ModalRoot> and <ModalContent>:

MyModal.vue — v2
<script setup lang="ts">
import { ModalContent, ModalRoot, useModalContext } from '@kolirt/vue-modal'

defineOptions({ modalGroup: 'default' })

const modal = useModalContext<boolean>()
</script>

<template>
  <ModalRoot>
    <ModalContent>
      <button @click="modal.confirm(true)">OK</button>
      <button @click="modal.close()">Cancel</button>
    </ModalContent>
  </ModalRoot>
</template>

8. Remove SimpleModal

SimpleModal was the only built-in layout in v1. It is not included in v2. Copy its template into your own component or use a design-system dialog.

9. Replace useLock

useLock (scroll lock composable) is no longer exported. Scroll locking is automatic — <ModalTarget> handles it via useScrollLock. If you needed it for other purposes, implement it with document.body.style.overflow.


Quick reference — renamed / removed exports

v1 exportv2 equivalent
openModal(C, props, opts)openModal(C, { props, ...opts })
closeModal()useModalContext().close() or closeModal({ group })
confirmModal(data)useModalContext().confirm(data)
closeAllModals()closeAllModals() ✓ (same name)
ModalTargetModalTarget ✓ (different behavior)
BaseModalModalRoot + ModalContent
SimpleModalremoved
useLockremoved (automatic)
$on / $off / $emithandle.on / handle.off
Events enumremoved
modalsmodals ✓ (same name, computed ref)
isOpenedisOpened
TypeScript note. v1 typed openModal with a bare props argument; v2 infers props from options.props. If you hit Type … is not assignable to type 'never', check that your group is declared in ModalGroupRegistry and that the augmentation file is included in tsconfig.json.
Copyright © 2026