Composables
Composables
useModal<T, C>(component, defaults?)
Bind a single modal component to the current scope. Returns reactive isOpen, persistent event listeners that survive across multiple .open() calls, and auto-cleanup on scope unmount (configurable).
Signature
function useModal<T = unknown, C extends Component = Component>(
component: C,
defaults?: UseModalDefaults<C>
): {
open(options?: OpenModalOptions<C>): Promise<T>
close(opts?: CloseFlags): void
on(event: string, handler: (...args: any[]) => void): void
off(event: string, handler: (...args: any[]) => void): void
isOpen: ComputedRef<boolean>
isTop: ComputedRef<boolean>
instanceId: Ref<number | null>
}
interface UseModalDefaults<C extends Component> extends OpenModalOptions<C> {
closeOnUnmount?: boolean
}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
component | C extends Component | yes | The Vue component bound to this controller. All .open() calls mount this same component. |
defaults | UseModalDefaults<C> | no | Defaults applied to every .open() call: inherits all of OpenModalOptions<C> (props, on, group, instantEnter) plus closeOnUnmount. |
Type parameters identical to openModal.
Per-call merge. When you call .open(opts), defaults.props and opts.props are shallow-merged (per-call wins); listeners from both sources fire. group and instantEnter follow override semantics — per-call wins.
When to reach for useModal vs openModal
| Need | Use |
|---|---|
| One-off call from a function/handler | openModal |
| Same modal opened multiple times from a component | useModal |
Reactive isOpen for binding to a button's disabled | useModal |
| Persistent event listeners across open calls | useModal |
| Auto-close when the calling component unmounts | useModal |
Example
<script setup lang="ts">
import { useModal } from '@kolirt/vue-modal'
import EditDialog from './EditDialog.vue'
const editModal = useModal<{ value: string }>(EditDialog, {
group: 'default',
props: { mode: 'inline' },
on: {
progress: (percent) => console.log(percent)
},
closeOnUnmount: true // default
})
async function edit(id: number) {
const data = await editModal.open({ props: { id } }).catch(() => null)
if (data) console.log('saved', data.value)
}
</script>
<template>
<button :disabled="editModal.isOpen.value" @click="edit(42)">Edit</button>
</template>
open() merges defaults with the per-call options: props are shallow-merged (per-call wins), listeners from both sources fire. See Types for OpenModalOptions<C>.
Defaults
Same as OpenModalOptions<C> plus:
| Field | Type | Default | Description |
|---|---|---|---|
closeOnUnmount | boolean | true | When the calling scope is disposed, close the open instance with ignoreGuard: true, instantExit: true. |
Returned API
| Field | Type | Description |
|---|---|---|
open(options?) | (opts?: OpenModalOptions<C>) => Promise<T> | Merge defaults + options (props shallow-merged with per-call wins, listeners merged), call openModal, await. |
close(opts?) | (opts?: { ignoreGuard?, instantExit? }) => void | Close current instance with success: false. No-op if not open. |
on(event, handler) | (event, handler) => void | Add a persistent listener (survives across open calls). |
off(event, handler) | (event, handler) => void | Remove a persistent listener. |
isOpen | ComputedRef<boolean> | instanceId !== null — true while this instance is mounted in the stack (regardless of position). |
isTop | ComputedRef<boolean> | True only when this instance is the topmost in the global stack. |
instanceId | Ref<number | null> | Current open instance id, or null. |
useModalContext<T>()
Called inside a modal component (the one opened via openModal/useModal). Gives access to the close API, before-close guards, and effective behavior options.
Signature
function useModalContext<T = unknown>(): {
id: number
group: ModalGroup
isClosing: ComputedRef<boolean>
isTopmost: ComputedRef<boolean>
isTopmostGlobal: ComputedRef<boolean>
effectiveOptions: ComputedRef<ModalEffectiveOptions>
close(opts?: CloseFlags): void
confirm(data: T, opts?: CloseFlags): void
onBeforeClose(handler: BeforeCloseHandler): void
}
Parameters
useModalContext takes no parameters. The single type parameter T (default unknown) describes the value confirm(data) resolves the modal's promise with — pass the same type you used when opening (openModal<T>(...) / useModal<T>(...)).
<script setup lang="ts">
import { useModalContext } from '@kolirt/vue-modal'
const { close, confirm, onBeforeClose, isTopmost, effectiveOptions } = useModalContext<boolean>()
onBeforeClose(async () => {
if (formIsDirty.value) return await askConfirm()
})
</script>
Returned API
| Field | Type | Description |
|---|---|---|
id | number | Modal instance id. |
group | ModalGroup | This modal's group. |
isClosing | ComputedRef<boolean> | true from the moment close starts until DOM removal. |
isTopmost | ComputedRef<boolean> | Topmost in this modal's group. |
isTopmostGlobal | ComputedRef<boolean> | Topmost across all groups (last entry of modals). |
effectiveOptions | ComputedRef<ModalEffectiveOptions> | Resolved positive-form options for this modal's group. |
close(opts?) | (opts?: { ignoreGuard?: boolean; instantExit?: boolean }) => void | Reject the handle promise with ModalClosedError. |
confirm(data, opts?) | (data: T, opts?: { ignoreGuard?: boolean; instantExit?: boolean }) => void | Resolve the handle promise with data. |
onBeforeClose(handler) | (handler: BeforeCloseHandler) => void | Register a guard. Return false (or Promise<false>) to block close. Auto-unregistered on the component's onBeforeUnmount lifecycle hook. |
effectiveOptions shape
interface ModalEffectiveOptions {
interactOutside: boolean // false in modal mode
closeOnInteractOutside: boolean // close on click outside the region
closeOnInteractOverlay: boolean // close on click in the overlay/empty area
lockBodyScroll: boolean
closeOnEscape: boolean
}
Throws
If called outside a modal component (one opened via openModal/useModal). Exact message: [@kolirt/vue-modal] useModalContext() must be called inside a modal component (opened via openModal/useModal).
See Types for ModalEffectiveOptions, BeforeCloseHandler, and CloseModalOptions<T>.
