Modal Imperative API Guide
Recommended: @lobehub/ui/base-ui
New code should use the base-ui modal stack (headless primitives, not antd Modal):
createModal,confirmModal,ModalHostfrom@lobehub/ui/base-uiuseModalContextfrom@lobehub/ui/base-uiinside modal content
Body slot: pass content (or children; runtime uses content ?? children).
Global ModalHost (required)
Base-ui createModal renders through a separate host from the root package. The app must mount ModalHost from @lobehub/ui/base-ui once near the root (e.g. next to other global hosts). Without it, createModal calls will not appear.
If the project only mounts ModalHost from @lobehub/ui, add a second lazy ModalHost from @lobehub/ui/base-ui until all imperative modals are migrated.
Why imperative?
File structure
1. Content (MyFeatureContent.tsx)
2. createModal (index.tsx)
3. Usage
i18n
- Content:
useTranslationin components. createModaloptions:import { t } from 'i18next'where hooks are unavailable.
useModalContext
Closing: which callback actually fires
close() — from useModalContext() inside the content, or from the returned
ModalInstance — only flips the stack entry to open: false. It does not go
through base-ui's dismissal path, so:
Put caller-side cleanup (clearing an editing flag, resetting the provider's
open state) on onOpenChangeComplete. Wiring it to onOpenChange looks
correct until a footer button closes the modal, and then the caller never learns
it went away — typically leaving a flag set so the modal cannot be reopened.
createModal only ever completes with false (the imperative renderer supplies
the argument itself and never forwards the prop to base-ui), but still guard on
it — other base-ui primitives such as DropdownMenu do report both directions,
and the guard keeps the call site from depending on that difference:
Common options (base-ui)
ImperativeModalProps builds on BaseModalProps: title, width, maskClosable, open, onOpenChange, footer, styles / classNames (keys: backdrop, popup, header, title, close, content, …).
Confirm
Legacy: @lobehub/ui (root)
createModal from the root @lobehub/ui entry is typed as antd Modal props (children, allowFullscreen, getContainer, destroyOnHidden, styles.body, etc.). App code no longer imports it; do not reintroduce it — use @lobehub/ui/base-ui.
Examples
- Base-ui (preferred): follow sections above; ensure base-ui
ModalHostis mounted. - Base-ui call sites:
src/features/SkillStore/index.tsx,src/features/LibraryModal/CreateNew/index.tsx


