Behavior options
Behavior options
By default modals work as proper ARIA dialogs in modal mode: focus trap, body inert, scroll locked, close on Esc, close on overlay click. You opt out of pieces you don't need.
The five flags
All available on <ModalTarget> (per-target), createModal({ groups: { x: {...} } }) (per-group), or both — props override the registered config.
| Flag | Default | Effect when true |
|---|---|---|
enableInteractOutside | false | Switch to non-modal mode: no focus trap, body NOT inert, background text-selectable, aria-modal="false". |
disableCloseOnInteractOutside | false | Click outside the <ModalTarget> region does NOT close. (Relevant when the region is smaller than viewport.) |
disableCloseOnInteractOverlay | false | Click in the empty area around the card (inside the region) does NOT close. |
disableLockBodyScroll | false | Body scroll is NOT locked. |
disableCloseOnEscape | false | Pressing Esc does NOT close the topmost modal of the group. |
The asymmetric prefixes (enable* vs disable*) are intentional: every flag's false matches the modal-mode default. You only ever set a flag to true to opt out.
Default behavior in detail
When all flags are at their false defaults:
- Focus trap — Tab and Shift+Tab cycle within the dialog.
- Body inert — background elements are not focusable; assistive tech sees only the dialog.
body { overflow: hidden }+paddingRightcompensation for vanished scrollbar.body { user-select: none }— text selection blocked outside the modal (released on close).- Esc closes the topmost modal of any active group.
- Click outside card closes — both inside and outside the region (when applicable).
Common configurations
Confirmation dialog (strict)
User must explicitly choose — no Esc, no outside-click escape.
createModal({
groups: {
confirm: {
disableCloseOnEscape: true,
disableCloseOnInteractOverlay: true,
disableCloseOnInteractOutside: true
}
}
})
Side panel (non-modal)
Doesn't trap focus, doesn't lock scroll — used like a navigator on the side.
createModal({
groups: {
panel: {
enableInteractOutside: true,
disableLockBodyScroll: true
}
}
})
Per-target override
<!-- Group base config from createModal applied -->
<ModalTarget group="confirm" />
<!-- Same group, Esc re-enabled for this specific target -->
<ModalTarget :disableCloseOnEscape="false" group="confirm" />
Reading effective options inside a modal
useModalContext() returns effectiveOptions in the positive form for ergonomic reading:
const { effectiveOptions } = useModalContext()
effectiveOptions.value.interactOutside // boolean
effectiveOptions.value.closeOnInteractOutside // boolean
effectiveOptions.value.closeOnInteractOverlay // boolean
effectiveOptions.value.lockBodyScroll // boolean
effectiveOptions.value.closeOnEscape // boolean
The translation negative→positive happens once at <ModalTarget> boundary.
Custom close guards
Block close attempts from inside the modal via onBeforeClose — return false to veto. Callers can bypass guards with { ignoreGuard: true }. See Modal context for the full pattern.
