From 15d71b93e780af7b375234c2a9bf26440481a1bd Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 28 Nov 2024 02:09:47 +0300 Subject: [PATCH 1/3] fix(bubble-menu): add focusout handler for floating element --- packages/extension-bubble-menu/src/bubble-menu-plugin.ts | 6 ++++++ packages/react/src/BubbleMenu.tsx | 2 +- packages/vue-2/src/BubbleMenu.ts | 2 +- packages/vue-3/src/BubbleMenu.ts | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/extension-bubble-menu/src/bubble-menu-plugin.ts b/packages/extension-bubble-menu/src/bubble-menu-plugin.ts index d6d0428cf53..dc62152861f 100644 --- a/packages/extension-bubble-menu/src/bubble-menu-plugin.ts +++ b/packages/extension-bubble-menu/src/bubble-menu-plugin.ts @@ -123,6 +123,7 @@ export class BubbleMenuView { } this.element.addEventListener('mousedown', this.mousedownHandler, { capture: true }) + this.element.addEventListener('focusout', this.floatingFocusoutHandler) this.view.dom.addEventListener('dragstart', this.dragstartHandler) this.editor.on('focus', this.focusHandler) this.editor.on('blur', this.blurHandler) @@ -132,6 +133,10 @@ export class BubbleMenuView { this.element.style.visibility = 'visible' } + floatingFocusoutHandler = (event: FocusEvent) => { + this.blurHandler({ event }) + } + mousedownHandler = () => { this.preventHide = true } @@ -303,6 +308,7 @@ export class BubbleMenuView { } this.tippy?.destroy() this.element.removeEventListener('mousedown', this.mousedownHandler, { capture: true }) + this.element.removeEventListener('focusout', this.floatingFocusoutHandler) this.view.dom.removeEventListener('dragstart', this.dragstartHandler) this.editor.off('focus', this.focusHandler) this.editor.off('blur', this.blurHandler) diff --git a/packages/react/src/BubbleMenu.tsx b/packages/react/src/BubbleMenu.tsx index 6628655708f..0ab34330e6a 100644 --- a/packages/react/src/BubbleMenu.tsx +++ b/packages/react/src/BubbleMenu.tsx @@ -50,7 +50,7 @@ export const BubbleMenu = (props: BubbleMenuProps) => { }, [props.editor, currentEditor, element]) return ( -
+
{props.children}
) diff --git a/packages/vue-2/src/BubbleMenu.ts b/packages/vue-2/src/BubbleMenu.ts index 44112e14199..181b468e9cb 100644 --- a/packages/vue-2/src/BubbleMenu.ts +++ b/packages/vue-2/src/BubbleMenu.ts @@ -61,7 +61,7 @@ export const BubbleMenu: Component = { }, render(this: BubbleMenuInterface, createElement: CreateElement) { - return createElement('div', { style: { visibility: 'hidden' } }, this.$slots.default) + return createElement('div', { style: { visibility: 'hidden' }, attrs: { tabIndex: -1 } }, this.$slots.default) }, beforeDestroy(this: BubbleMenuInterface) { diff --git a/packages/vue-3/src/BubbleMenu.ts b/packages/vue-3/src/BubbleMenu.ts index 841da013912..3f7063c44bc 100644 --- a/packages/vue-3/src/BubbleMenu.ts +++ b/packages/vue-3/src/BubbleMenu.ts @@ -66,6 +66,6 @@ export const BubbleMenu = defineComponent({ editor.unregisterPlugin(pluginKey) }) - return () => h('div', { ref: root }, slots.default?.()) + return () => h('div', { ref: root, tabindex: -1 }, slots.default?.()) }, }) From ed32a1da3c41c3d32056da55b00c616229f6ad71 Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 28 Nov 2024 02:09:47 +0300 Subject: [PATCH 2/3] fix(bubble-menu): add focusout handler for floating element --- .changeset/twelve-turtles-cry.md | 8 ++++++++ packages/extension-bubble-menu/src/bubble-menu-plugin.ts | 6 ++++++ packages/react/src/BubbleMenu.tsx | 2 +- packages/vue-2/src/BubbleMenu.ts | 2 +- packages/vue-3/src/BubbleMenu.ts | 2 +- 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 .changeset/twelve-turtles-cry.md diff --git a/.changeset/twelve-turtles-cry.md b/.changeset/twelve-turtles-cry.md new file mode 100644 index 00000000000..3bc1f1db393 --- /dev/null +++ b/.changeset/twelve-turtles-cry.md @@ -0,0 +1,8 @@ +--- +"@tiptap/extension-bubble-menu": patch +"@tiptap/react": patch +"@tiptap/vue-2": patch +"@tiptap/vue-3": patch +--- + +Fix the bug where the bubble menu does not hide diff --git a/packages/extension-bubble-menu/src/bubble-menu-plugin.ts b/packages/extension-bubble-menu/src/bubble-menu-plugin.ts index d6d0428cf53..dc62152861f 100644 --- a/packages/extension-bubble-menu/src/bubble-menu-plugin.ts +++ b/packages/extension-bubble-menu/src/bubble-menu-plugin.ts @@ -123,6 +123,7 @@ export class BubbleMenuView { } this.element.addEventListener('mousedown', this.mousedownHandler, { capture: true }) + this.element.addEventListener('focusout', this.floatingFocusoutHandler) this.view.dom.addEventListener('dragstart', this.dragstartHandler) this.editor.on('focus', this.focusHandler) this.editor.on('blur', this.blurHandler) @@ -132,6 +133,10 @@ export class BubbleMenuView { this.element.style.visibility = 'visible' } + floatingFocusoutHandler = (event: FocusEvent) => { + this.blurHandler({ event }) + } + mousedownHandler = () => { this.preventHide = true } @@ -303,6 +308,7 @@ export class BubbleMenuView { } this.tippy?.destroy() this.element.removeEventListener('mousedown', this.mousedownHandler, { capture: true }) + this.element.removeEventListener('focusout', this.floatingFocusoutHandler) this.view.dom.removeEventListener('dragstart', this.dragstartHandler) this.editor.off('focus', this.focusHandler) this.editor.off('blur', this.blurHandler) diff --git a/packages/react/src/BubbleMenu.tsx b/packages/react/src/BubbleMenu.tsx index 6628655708f..0ab34330e6a 100644 --- a/packages/react/src/BubbleMenu.tsx +++ b/packages/react/src/BubbleMenu.tsx @@ -50,7 +50,7 @@ export const BubbleMenu = (props: BubbleMenuProps) => { }, [props.editor, currentEditor, element]) return ( -
+
{props.children}
) diff --git a/packages/vue-2/src/BubbleMenu.ts b/packages/vue-2/src/BubbleMenu.ts index 44112e14199..181b468e9cb 100644 --- a/packages/vue-2/src/BubbleMenu.ts +++ b/packages/vue-2/src/BubbleMenu.ts @@ -61,7 +61,7 @@ export const BubbleMenu: Component = { }, render(this: BubbleMenuInterface, createElement: CreateElement) { - return createElement('div', { style: { visibility: 'hidden' } }, this.$slots.default) + return createElement('div', { style: { visibility: 'hidden' }, attrs: { tabIndex: -1 } }, this.$slots.default) }, beforeDestroy(this: BubbleMenuInterface) { diff --git a/packages/vue-3/src/BubbleMenu.ts b/packages/vue-3/src/BubbleMenu.ts index 841da013912..3f7063c44bc 100644 --- a/packages/vue-3/src/BubbleMenu.ts +++ b/packages/vue-3/src/BubbleMenu.ts @@ -66,6 +66,6 @@ export const BubbleMenu = defineComponent({ editor.unregisterPlugin(pluginKey) }) - return () => h('div', { ref: root }, slots.default?.()) + return () => h('div', { ref: root, tabindex: -1 }, slots.default?.()) }, }) From 32c4b2b7f6e62a473560432c88e2f02d3fdbeaba Mon Sep 17 00:00:00 2001 From: Egor <59088961+cairon666@users.noreply.github.com> Date: Sun, 1 Dec 2024 02:39:00 +0300 Subject: [PATCH 3/3] Update changeset Co-authored-by: bdbch <6538827+bdbch@users.noreply.github.com> --- .changeset/twelve-turtles-cry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twelve-turtles-cry.md b/.changeset/twelve-turtles-cry.md index 3bc1f1db393..25f800d1534 100644 --- a/.changeset/twelve-turtles-cry.md +++ b/.changeset/twelve-turtles-cry.md @@ -5,4 +5,4 @@ "@tiptap/vue-3": patch --- -Fix the bug where the bubble menu does not hide +Added a `focusout` event listener to handle blur events on the bubble menu element, ensuring the menu closes properly when blurred.