@@ -201,8 +201,6 @@ const edgeTypes: EdgeTypes = {
201201const defaultEdgeOptions = { type : 'custom' }
202202
203203const reactFlowStyles = [
204- '[&_.react-flow__edges]:!z-0' ,
205- '[&_.react-flow__node]:z-[21]' ,
206204 '[&_.react-flow__handle]:!z-[30]' ,
207205 '[&_.react-flow__edge-labels]:!z-[1001]' ,
208206 '[&_.react-flow__pane]:select-none' ,
@@ -2478,6 +2476,7 @@ const WorkflowContent = React.memo(
24782476
24792477 // Local state for nodes - allows smooth drag without store updates on every frame
24802478 const [ displayNodes , setDisplayNodes ] = useState < Node [ ] > ( [ ] )
2479+ const [ lastInteractedNodeId , setLastInteractedNodeId ] = useState < string | null > ( null )
24812480
24822481 const selectedNodeIds = useMemo (
24832482 ( ) => displayNodes . filter ( ( node ) => node . selected ) . map ( ( node ) => node . id ) ,
@@ -2489,6 +2488,14 @@ const WorkflowContent = React.memo(
24892488 syncPanelWithSelection ( selectedNodeIds )
24902489 } , [ selectedNodeIdsKey ] )
24912490
2491+ // Keep the most recently selected block on top even after deselection, so a
2492+ // dragged block doesn't suddenly drop behind other overlapping blocks.
2493+ useEffect ( ( ) => {
2494+ if ( selectedNodeIds . length > 0 ) {
2495+ setLastInteractedNodeId ( selectedNodeIds [ selectedNodeIds . length - 1 ] )
2496+ }
2497+ } , [ selectedNodeIdsKey ] )
2498+
24922499 useEffect ( ( ) => {
24932500 // Check for pending selection (from paste/duplicate), otherwise preserve existing selection
24942501 if ( pendingSelection && pendingSelection . length > 0 ) {
@@ -3723,18 +3730,51 @@ const WorkflowContent = React.memo(
37233730 [ removeEdge , edges , blocks , addNotification , activeWorkflowId ]
37243731 )
37253732
3733+ // Elevate nodes using React Flow's native zIndex so selected/recent blocks
3734+ // always sit above edges and other blocks.
3735+ //
3736+ // Z-index layers (regular blocks):
3737+ // 21 — default
3738+ // 22 — last interacted (dragged/selected, now deselected) so it stays on
3739+ // top of siblings until another block is touched
3740+ // 31 — currently selected (above connected edges at z-22 and handles at z-30)
3741+ //
3742+ // Subflow container nodes are skipped — they use depth-based zIndex for
3743+ // correct parent/child layering and must not be bumped.
3744+ // Child blocks inside containers already carry zIndex 1000 and are bumped by
3745+ // +10 when selected so they stay above their sibling child blocks.
3746+ const nodesForRender = useMemo ( ( ) => {
3747+ return displayNodes . map ( ( node ) => {
3748+ if ( node . type === 'subflowNode' ) return node
3749+ const base = node . zIndex ?? 21
3750+ const target = node . selected
3751+ ? base + 10
3752+ : node . id === lastInteractedNodeId
3753+ ? Math . max ( base , 22 )
3754+ : base
3755+ if ( target === node . zIndex ) return node
3756+ return { ...node , zIndex : target }
3757+ } )
3758+ } , [ displayNodes , lastInteractedNodeId ] )
3759+
37263760 /** Transforms edges to include selection state and delete handlers. Memoized to prevent re-renders. */
37273761 const edgesWithSelection = useMemo ( ( ) => {
37283762 const nodeMap = new Map ( displayNodes . map ( ( n ) => [ n . id , n ] ) )
3763+ const elevatedNodeIdSet = new Set (
3764+ lastInteractedNodeId ? [ ...selectedNodeIds , lastInteractedNodeId ] : selectedNodeIds
3765+ )
37293766
37303767 return edgesForDisplay . map ( ( edge ) => {
37313768 const sourceNode = nodeMap . get ( edge . source )
37323769 const targetNode = nodeMap . get ( edge . target )
37333770 const parentLoopId = sourceNode ?. parentId || targetNode ?. parentId
37343771 const edgeContextId = `${ edge . id } ${ parentLoopId ? `-${ parentLoopId } ` : '' } `
3772+ const connectedToElevated =
3773+ elevatedNodeIdSet . has ( edge . source ) || elevatedNodeIdSet . has ( edge . target )
37353774
37363775 return {
37373776 ...edge ,
3777+ zIndex : connectedToElevated ? 22 : 0 ,
37383778 data : {
37393779 ...edge . data ,
37403780 isSelected : selectedEdges . has ( edgeContextId ) ,
@@ -3745,7 +3785,14 @@ const WorkflowContent = React.memo(
37453785 } ,
37463786 }
37473787 } )
3748- } , [ edgesForDisplay , displayNodes , selectedEdges , handleEdgeDelete ] )
3788+ } , [
3789+ edgesForDisplay ,
3790+ displayNodes ,
3791+ selectedNodeIds ,
3792+ selectedEdges ,
3793+ handleEdgeDelete ,
3794+ lastInteractedNodeId ,
3795+ ] )
37493796
37503797 /** Handles Delete/Backspace to remove selected edges or blocks. */
37513798 useEffect ( ( ) => {
@@ -3885,7 +3932,7 @@ const WorkflowContent = React.memo(
38853932 { showTrainingModal && < TrainingModal /> }
38863933
38873934 < ReactFlow
3888- nodes = { displayNodes }
3935+ nodes = { nodesForRender }
38893936 edges = { edgesWithSelection }
38903937 onNodesChange = { onNodesChange }
38913938 onEdgesChange = { onEdgesChange }
@@ -3952,7 +3999,7 @@ const WorkflowContent = React.memo(
39523999 onNodeDragStart = { effectivePermissions . canEdit ? onNodeDragStart : undefined }
39534000 snapToGrid = { snapToGrid }
39544001 snapGrid = { snapGrid }
3955- elevateEdgesOnSelect = { true }
4002+ elevateEdgesOnSelect = { false }
39564003 onlyRenderVisibleElements = { false }
39574004 deleteKeyCode = { null }
39584005 elevateNodesOnSelect = { false }
0 commit comments