fix: disable pointer events on non-visible DOM widget overlays

When a node is collapsed, DOM widget overlays could intercept pointer
events during the timing gap between canvas state update and Vue DOM
update. Adding !widgetState.visible to the pointerEvents condition
in composeStyle() prevents this by immediately setting pointer-events
to none when the widget becomes invisible.

Also restores click-to-expand in the E2E test, removing the
programmatic workaround from PR #10967.

Fixes #11006
This commit is contained in:
bymyself
2026-04-10 05:33:00 +00:00
parent 0132c77c7d
commit b8c6dc882c
3 changed files with 24 additions and 11 deletions

View File

@@ -351,16 +351,9 @@ test.describe('Node Interaction', () => {
await expect(comfyPage.canvas).toHaveScreenshot(
'text-encode-toggled-off.png'
)
// Re-expand: clicking the canvas toggler on a collapsed node is
// unreliable because DOM widget overlays may intercept the pointer
// event. Use programmatic collapse() for the expand step.
// TODO(#11006): Restore click-to-expand once DOM widget overlay pointer interception is fixed
await comfyPage.page.evaluate((nodeId) => {
const node = window.app!.graph.getNodeById(nodeId)!
node.collapse()
window.app!.canvas.setDirty(true, true)
}, targetNode.id)
await comfyPage.nextFrame()
await comfyPage.canvas.click({
position: togglerPos
})
await expect.poll(() => targetNode.isCollapsed()).toBe(false)
// Move mouse away to avoid hover highlight differences.
await comfyPage.canvasOps.moveMouseToEmptyArea()

View File

@@ -114,4 +114,21 @@ describe('DomWidget disabled style', () => {
expect(root.style.pointerEvents).toBe('none')
expect(root.style.opacity).toBe('0.5')
})
it('disables pointer events when widget is not visible', async () => {
const widgetState = createWidgetState(false)
widgetState.visible = false
const { container } = render(DomWidget, {
props: {
widgetState
}
})
widgetState.zIndex = 3
await nextTick()
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
const root = container.querySelector('.dom-widget') as HTMLElement
expect(root.style.pointerEvents).toBe('none')
})
})

View File

@@ -113,7 +113,10 @@ function composeStyle() {
...positionStyle.value,
...(enableDomClipping.value ? clippingStyle.value : {}),
zIndex: widgetState.zIndex,
pointerEvents: widgetState.readonly || isDisabled ? 'none' : 'auto',
pointerEvents:
!widgetState.visible || widgetState.readonly || isDisabled
? 'none'
: 'auto',
opacity: isDisabled ? 0.5 : 1
}
}