ueberdosis/tiptap
View on GitHubTiptap/vue-2 both menus have error: Error in callback for immediate watcher "editor": "TypeError: Cannot read properties of undefined (reading 'style')"
Open
#7167 opened on Nov 4, 2025
area: editorarea: ui-componentsgood first issuestatus: triagetype: help-wanted
Description
Affected Packages
@tiptap/vue-2
Version(s)
3.10.1
Bug Description
The menus are always visible and don't change there positions with user interaction.
Bubble menu and floating menu in tiptap/vue-2 package can't read style from this.$el in watcher because at the time of execution element is undefined. It helps to add setTimeout in watcher but there is probably better solution.
Browser Used
Chrome
Code Example URL
https://codesandbox.io/p/sandbox/quirky-mccarthy-9qjprq
Expected Behavior
Menus from tiptap/vue-2 package to work right out of the box without errors.
Additional Context (Optional)
Solution I made in my project to handle this bug for now .
//Bubble Menu
<template>
<div ref="customBubbleMenu">
<slot />
</div>
</template>
<script>
import { BubbleMenuPlugin } from '@tiptap/extension-bubble-menu';
export default {
name: 'BubbleMenu',
props: {
pluginKey: {
type: [String, Object],
default: 'bubbleMenu',
},
editor: {
type: Object,
required: true,
},
updateDelay: {
type: Number,
default: 250,
},
options: {
type: Object,
default: () => {},
},
resizeDelay: {
type: Number,
default: 100,
},
appendTo: {
type: [Object, Function],
default: undefined,
},
shouldShow: {
type: Function,
default: null,
},
getReferencedVirtualElement: {
type: Function,
default: null,
},
},
mounted() {
this.$refs.customBubbleMenu.style.visibility = 'hidden';
this.$refs.customBubbleMenu.style.position = 'absolute';
this.$refs.customBubbleMenu.remove();
this.$nextTick(() => {
this.editor.registerPlugin(
BubbleMenuPlugin({
updateDelay: this.updateDelay,
resizeDelay: this.resizeDelay,
options: this.options,
editor: this.editor,
element: this.$refs.customBubbleMenu,
pluginKey: this.pluginKey,
appendTo: this.appendTo,
shouldShow: this.shouldShow,
getReferencedVirtualElement: this.getReferencedVirtualElement,
})
);
});
},
beforeDestroy() {
this.editor.unregisterPlugin(this.pluginKey);
},
};
</script>
//Floating Menu
<template>
<div ref="customFloatingMenu">
<slot />
</div>
</template>
<script>
import { FloatingMenuPlugin } from '@tiptap/extension-floating-menu';
export default {
name: 'CustomFloatingMenu',
props: {
pluginKey: {
type: [String, Object],
default: 'bubbleMenu',
},
editor: {
type: Object,
required: true,
},
options: {
type: Object,
default: () => {},
},
appendTo: {
type: [Object, Function],
default: undefined,
},
shouldShow: {
type: Function,
default: null,
},
},
mounted() {
this.$refs.customFloatingMenu.style.visibility = 'hidden';
this.$refs.customFloatingMenu.style.position = 'absolute';
this.$refs.customFloatingMenu.remove();
this.$nextTick(() => {
this.editor.registerPlugin(
FloatingMenuPlugin({
editor: this.editor,
element: this.$refs.customFloatingMenu,
pluginKey: this.pluginKey,
options: this.options,
appendTo: this.appendTo,
shouldShow: this.shouldShow,
})
);
});
},
beforeDestroy() {
this.editor.unregisterPlugin(this.pluginKey);
},
};
</script>
Dependency Updates
- Yes, I've updated all my dependencies.