Browse Source
Disable pointer-events on node images and content during pan/drag
Browser hit-testing against large base64 <img> elements is expensive
even when no React state updates occur. Two CSS-level fixes:
1. pointer-events: none on all .react-flow__node img — images never
need direct mouse events (parent containers handle clicks)
2. .canvas-interacting class on <html> during pan/drag disables
pointer-events on all node content via CSS descendant selector,
toggled via direct DOM access (zero React overhead)
https://claude.ai/code/session_01MvD1n4QeXutgwUpKJuDGHa
handoff-20260429-1057
Claude
4 months ago
Failed to extract signature
2 changed files with
17 additions and
4 deletions
src/app/globals.css
src/components/WorkflowCanvas.tsx
@ -40,6 +40,19 @@ body {
font-family : inherit ;
}
/ * Skip hit-testing on images inside nodes — parent containers handle all
click / hover events . Prevents expensive bitmap decoding during mouse movement . * /
. react-flow__node img {
pointer-events : none ;
}
/ * During active panning or node dragging , disable pointer events on all node
content to eliminate expensive browser hit-testing against the DOM tree .
The class is toggled on < html > via direct DOM access ( no React re-render ) . * /
. canvas-interacting . react-flow__node > * {
pointer-events : none ;
}
/* Remove default React Flow styling for output nodes to match custom nodes */
. react-flow__node-output {
border : none ! important ;
@ -1964,10 +1964,10 @@ export function WorkflowCanvas() {
onEdgesChange = { onEdgesChange }
onConnect = { handleConnect }
onConnectEnd = { handleConnectEnd }
onMoveStart = { ( ) = > { isPanningRef . current = true ; setHoveredNodeId ( null ) ; } }
onMoveEnd = { ( ) = > { isPanningRef . current = false ; } }
onNodeDragStart = { ( ) = > { isDraggingNodeRef . current = true ; } }
onNodeDragStop = { ( event , node ) = > { isDraggingNodeRef . current = false ; handleNodeDragStop ( event , node ) ; } }
onMoveStart = { ( ) = > { isPanningRef . current = true ; setHoveredNodeId ( null ) ; document . documentElement . classList . add ( "canvas-interacting" ) ; } }
onMoveEnd = { ( ) = > { isPanningRef . current = false ; document . documentElement . classList . remove ( "canvas-interacting" ) ; } }
onNodeDragStart = { ( ) = > { isDraggingNodeRef . current = true ; document . documentElement . classList . add ( "canvas-interacting" ) ; } }
onNodeDragStop = { ( event , node ) = > { isDraggingNodeRef . current = false ; document . documentElement . classList . remove ( "canvas-interacting" ) ; handleNodeDragStop ( event , node ) ; } }
onSelectionChange = { handleSelectionChange }
nodeTypes = { nodeTypes }
edgeTypes = { edgeTypes }