Concepts

Groups

Why modals belong to named groups and what isolation that provides.

Groups

Every modal belongs to exactly one group. A group is a named bucket that pairs a stack with a mount point — 'default', 'confirm', 'panel', whatever you declare.

There is no implicit 'default' group. openModal without a resolvable group throws at runtime. See Installation for registration mechanics.

What a group gives you

  • A separate stack. Modals in one group don't interfere with another group's Esc routing or stack sequencing.
  • A separate DOM mount point. Each group has its own <ModalTarget>, placeable anywhere in your template — main view, sidebar, drawer.
  • Per-group behavior. Scroll lock, Esc, overlay-click, and interact-outside can be tuned per group at registration. See Behavior options.

When to use multiple groups

Most apps start with a single 'default' group and add more only when behavior or layout needs to differ.

Use caseWhy a separate group
Confirm dialog above a form modalDistinct overlay, can disable Esc/overlay-click independently
Side panelNon-modal mode, no body scroll lock, different position
Notifications / toastsDoesn't trap focus or block the page

A confirm-on-top-of-form flow does not require a separate group — same-group stacking handles that. Reach for a new group when you need a different <ModalTarget> placement, different behavior flags, or visually distinct overlay/animation.

Default group on a component

If a modal is always opened in the same group, declare it on the component:

SettingsDialog.vue
<script setup lang="ts">
defineOptions({ modalGroup: 'default' })
</script>

Callers can then omit group:

openModal(SettingsDialog)                     // uses 'default'
openModal(SettingsDialog, { group: 'panel' }) // overrides
Async components don't pick up defineOptions({ modalGroup }). The group lookup happens synchronously when openModal is called — the inner component hasn't loaded yet. Pass group explicitly:
openModal(defineAsyncComponent(() => import('./HeavyDialog.vue')), {
  group: 'default'
})

Inspecting group state

import { groupModals, isGroupOpen } from '@kolirt/vue-modal'

groupModals('confirm').value  // ModalItem[] currently open in this group
isGroupOpen('confirm').value  // boolean

Both are computed refs — reactive in templates and watchers.

Copyright © 2026