Skip to content

Z-Index 与浮层挂载

编辑器所有全局浮层(bubble menu、BlockPicker、mention 建议、AI popover、Ant Design Dropdown / Select / Popover / Modal / Tooltip、自建 Toast / Notice 等)统一挂载在 EditorShell 根节点内的 overlay portal.yaniv-editor__overlay-portal),禁止挂到 document.body。这样浮层始终在 .yaniv-editor 作用域内,能正确继承 --ye-z-* CSS token。

例外(非视觉浮层):

  • HTML5 拖拽预览节点(setDragImage
  • 隐藏的 <input type="file">

宿主配置

YanivEditorYanivInlineEditor 均支持 zIndexBase prop(默认 1000)。Shell 会将其写入编辑器根节点的 --ye-z-base

vue
<YanivEditor :z-index-base="1500" />
<YanivInlineEditor v-model:content="html" :z-index-base="1500" />

该 prop 不触发 session 重建

何时需要调整

场景建议
编辑器为主内容,用户正常编辑保持默认 1000
宿主有 fixed header / sidebar(z-index ~100–500)默认即可
宿主全局 Modal / Drawer 需盖住编辑器浮层宿主弹层 z-index > 1100(见下表),或降低编辑器 zIndexBase
编辑器嵌在宿主 Modal 内提高 zIndexBase,或确保宿主 Modal 层级高于编辑器

要完全盖住编辑器所有浮层(含编辑器内 Modal),宿主 UI 需高于 zIndexBase + 100(默认 1100)。

Token 层级(variables.css

颜色字面量定义在 :rootz-index 与派生别名定义在 .yaniv-editor

派生别名(值形如 var(--ye-X) 的 token,如 --ye-toolbar-border--ye-table-border) 不能留在 :root:自定义属性在声明它的元素上求值,而改基础 token 的三条路径 ——外观类 .appearance-word[data-color-mode="dark"]custom-appearance-vars 的内联变量 ——全都落在编辑器根节点上。别名声明在祖先 :root 就跟不上这些覆盖 (详见 ARCHITECTURE 不变量 26)。

z-index token:

Token计算(默认 base=1000)用途
--ye-z-content1文档内基础层
--ye-z-content-overlay2表格选区等
--ye-z-content-control10图片列宽手柄等
--ye-z-editor-ui20拖拽手柄
--ye-z-editor-rail30大纲栏
--ye-z-chrome40顶栏 / 底栏
--ye-z-overlay-backdropbase块选择器遮罩
--ye-z-bubble-menubase + 10链接 / 图片 / 表格 bubble
--ye-z-floating-menubase + 20选中文本浮动菜单
--ye-z-picker-menubase + 30BlockPicker、mention、AI popover
--ye-z-drag-menubase + 40拖拽块菜单
--ye-z-drag-submenubase + 41拖拽子菜单
--ye-z-dropdownbase + 50Ant Design 下拉
--ye-z-tooltipbase + 60portal 内 Ant Design Tooltip
--ye-z-toastbase + 80自建 Toast / Notice
--ye-z-modalbase + 100编辑器内 Modal

浮层相对顺序:modal > toast > tooltip > dropdown > drag-menu > picker-menu > floating-menu > bubble-menu > backdrop

Toast / Notice

禁止使用 Ant Design 静态 message / notification(全局单例,默认挂 document.body,多实例不安全)。

统一入口(均在 src/core/overlayFeedback.ts / src/composables/useOverlayFeedback.ts):

场景入口定位 portal 的方式
Vue 组件useOverlayFeedback()useOverlayMountTarget()(inject 到 portal)
Tiptap 扩展showEditorToast / showEditorNoticeresolveOverlayPortalFromNode(editor.view.dom)
已持有 portalshowOverlayToast / showOverlayNotice直接传入 HTMLElement

showEditorToast / showEditorNoticeshowOverlayToast / showOverlayNotice 的便捷包装(先从 editor DOM 反查 portal)。三者最终都挂载到当前编辑器的 overlay portal。默认时长:toast 2.5s,notice 3s。

其中只有 useOverlayFeedback 在包的公共导出里;showOverlayToast / showEditorToast 等目前仅供库内使用。

实现要点(自定义 Shell)

若自建 Shell 而非使用 EditorShell,须保证:

  1. 根节点带 yaniv-editor class;
  2. 根内包含 .yaniv-editor__overlay-portal(见 src/styles/overlay-portal.css);
  3. 调用 provideEditorRoot / provideOverlayPortalsrc/core/editorContext.ts);
  4. 所有 teleport / BubbleMenu appendTo / Ant Design getPopupContainer / getContainer 指向 overlay portal;
  5. JS 侧通过 getYeZIndex(token, root) 读取 portal token(src/utils/zIndex.ts),必须传入编辑器根节点,无全局 fallback。

库内统一入口:

  • useOverlayMountTarget() — Ant Design getPopupContainer / Modal getContainer
  • useOverlayBubbleMenu() — Tiptap 3 BubbleMenu(Floating UI)的 appendTo + options
  • useOverlayFeedback() / showOverlayToast / showOverlayNotice — Toast / Notice

自建 Shell 目前需要 fork

上表中 provideEditorRoot / provideOverlayPortal / getYeZIndex没有@yanivjs/yaniv-editor 导出(公共导出里只有 useOverlayMountTarget / useOverlayBubbleMenu / useOverlayFeedback)。因此完整替换 EditorShell 需要 fork 仓库;在现有编辑器之上写自定义工具组件不受影响。

相关