From 0faf2220b8680ae344059c30884e8c05bd47b8ef Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Wed, 28 Jan 2026 23:18:23 -0800 Subject: [PATCH] fix: dragging (e.g., when selecting text) in Markdown note causes node to drag (#8413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary When attempting to select text inside Vue node Markdown widget's textarea (edit mode), the node would drag instead of text being selected. Root cause: WidgetMarkdown.vue's Textarea only had @click.stop and @keydown.stop, but was missing pointer event modifiers. The pointerdown event bubbled up to LGraphNode.vue which initiated node drag. *Fix*: Add @pointerdown.capture.stop, @pointermove.capture.stop, and @pointerup.capture.stop to match the pattern used in WidgetTextarea.vue. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8413-fix-dragging-e-g-when-selecting-text-in-Markdown-note-causes-node-to-drag-2f76d73d3650816dbf9bdf893775c3d4) by [Unito](https://www.unito.io) Co-authored-by: Subagent 5 Co-authored-by: Amp --- .../widgets/components/WidgetMarkdown.test.ts | 54 +++++++++++++++++++ .../widgets/components/WidgetMarkdown.vue | 3 ++ 2 files changed, 57 insertions(+) diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.test.ts b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.test.ts index ee788cc4db..8daebc5161 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.test.ts +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.test.ts @@ -206,6 +206,60 @@ describe('WidgetMarkdown Dual Mode Display', () => { expect(clickSpy).not.toHaveBeenCalled() expect(keydownSpy).not.toHaveBeenCalled() }) + + describe('Pointer Event Propagation', () => { + it('stops pointerdown propagation to prevent node drag during text selection', async () => { + const widget = createMockWidget('# Test') + const wrapper = mountComponent(widget, '# Test') + + await clickToEdit(wrapper) + + const textarea = wrapper.find('textarea') + expect(textarea.exists()).toBe(true) + + const parentPointerdownHandler = vi.fn() + const wrapperEl = wrapper.element as HTMLElement + wrapperEl.addEventListener('pointerdown', parentPointerdownHandler) + + await textarea.trigger('pointerdown') + + expect(parentPointerdownHandler).not.toHaveBeenCalled() + }) + + it('stops pointermove propagation during text selection', async () => { + const widget = createMockWidget('# Test') + const wrapper = mountComponent(widget, '# Test') + + await clickToEdit(wrapper) + + const textarea = wrapper.find('textarea') + + const parentPointermoveHandler = vi.fn() + const wrapperEl = wrapper.element as HTMLElement + wrapperEl.addEventListener('pointermove', parentPointermoveHandler) + + await textarea.trigger('pointermove') + + expect(parentPointermoveHandler).not.toHaveBeenCalled() + }) + + it('stops pointerup propagation after text selection', async () => { + const widget = createMockWidget('# Test') + const wrapper = mountComponent(widget, '# Test') + + await clickToEdit(wrapper) + + const textarea = wrapper.find('textarea') + + const parentPointerupHandler = vi.fn() + const wrapperEl = wrapper.element as HTMLElement + wrapperEl.addEventListener('pointerup', parentPointerupHandler) + + await textarea.trigger('pointerup') + + expect(parentPointerupHandler).not.toHaveBeenCalled() + }) + }) }) describe('Value Updates', () => { diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue index 28247859ed..845e905b19 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue @@ -21,6 +21,9 @@ } }" data-capture-wheel="true" + @pointerdown.capture.stop + @pointermove.capture.stop + @pointerup.capture.stop @click.stop @keydown.stop />