fix(frontend): render editor popups inside modal dialog top-layer
Native <dialog> elements opened with showModal() render in the browser's top-layer. Popups appended to document.body end up behind the dialog regardless of z-index, which broke the slash-command menu and the user mention suggestion inside the task detail modal. Append the popups to the nearest open <dialog> ancestor of the editor (falling back to document.body) so they join the same top-layer stacking context.
This commit is contained in:
parent
a1fbc277be
commit
91d5cfb1c0
|
|
@ -3,6 +3,7 @@ import { computePosition, flip, shift, offset, autoUpdate } from '@floating-ui/d
|
|||
import type { Editor } from '@tiptap/core'
|
||||
|
||||
import MentionList from './MentionList.vue'
|
||||
import { getPopupContainer } from '../popupContainer'
|
||||
import ProjectUserService from '@/services/projectUsers'
|
||||
import { fetchAvatarBlobUrl, getDisplayName } from '@/models/user'
|
||||
import type { IUser } from '@/modelTypes/IUser'
|
||||
|
|
@ -113,7 +114,8 @@ export default function mentionSuggestionSetup(projectId: number) {
|
|||
popupElement.style.left = '0'
|
||||
popupElement.style.zIndex = '4700'
|
||||
popupElement.appendChild(component.element!)
|
||||
document.body.appendChild(popupElement) // Update virtual reference
|
||||
getPopupContainer(props.editor).appendChild(popupElement)
|
||||
// Update virtual reference
|
||||
const rect = props.clientRect()
|
||||
if (rect) {
|
||||
virtualReference.getBoundingClientRect = () => rect
|
||||
|
|
@ -179,7 +181,7 @@ export default function mentionSuggestionSetup(projectId: number) {
|
|||
cleanupFloating()
|
||||
}
|
||||
if (popupElement) {
|
||||
document.body.removeChild(popupElement)
|
||||
popupElement.remove()
|
||||
popupElement = null
|
||||
}
|
||||
component.destroy()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import type {Editor} from '@tiptap/core'
|
||||
|
||||
// Native <dialog> elements opened with showModal() render in the browser's
|
||||
// top-layer, so popups appended to document.body end up visually behind them
|
||||
// regardless of z-index. Appending to the open dialog itself lifts the popup
|
||||
// into the same top-layer stacking context.
|
||||
export function getPopupContainer(editor?: Editor): HTMLElement {
|
||||
const editorEl = editor?.view?.dom as HTMLElement | undefined
|
||||
const dialog = editorEl?.closest('dialog[open]') as HTMLElement | null
|
||||
return dialog ?? document.body
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import {VueRenderer} from '@tiptap/vue-3'
|
|||
import {computePosition, flip, shift, offset, autoUpdate} from '@floating-ui/dom'
|
||||
|
||||
import CommandsList from './CommandsList.vue'
|
||||
import {getPopupContainer} from './popupContainer'
|
||||
|
||||
type TranslateFunction = (key: string) => string
|
||||
|
||||
|
|
@ -206,7 +207,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
|||
popupElement.style.left = '0'
|
||||
popupElement.style.zIndex = '4700'
|
||||
popupElement.appendChild(component.element!)
|
||||
document.body.appendChild(popupElement)
|
||||
getPopupContainer(props.editor).appendChild(popupElement)
|
||||
|
||||
// Update virtual reference
|
||||
const rect = props.clientRect()
|
||||
|
|
@ -266,7 +267,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
|||
cleanupFloating()
|
||||
}
|
||||
if (popupElement) {
|
||||
document.body.removeChild(popupElement)
|
||||
popupElement.remove()
|
||||
popupElement = null
|
||||
}
|
||||
component.destroy()
|
||||
|
|
|
|||
Loading…
Reference in New Issue