Skip to content

fix(canvas): correct z-index layering for selected blocks and connected edges#3698

Merged
waleedlatif1 merged 5 commits intostagingfrom
fix/z
Mar 21, 2026
Merged

fix(canvas): correct z-index layering for selected blocks and connected edges#3698
waleedlatif1 merged 5 commits intostagingfrom
fix/z

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Selected blocks now appear above all other blocks and edges using React Flow's native `zIndex` property instead of CSS classes that were being overridden by React Flow's inline styles
  • Edges connected to a selected (or recently interacted) block are elevated to z-22, sitting above regular blocks (z-21) but below the selected block itself (z-31) — so the edge is visible over other blocks but never overlaps the block it connects to
  • The most recently dragged/selected block stays elevated (z-22) after deselection so it doesn't drop behind overlapping blocks unexpectedly
  • Disabled `elevateEdgesOnSelect` (which had a hard-coded minimum z-index floor of 1000, always placing connected edges above the selected node)
  • Subflow/parallel/loop container nodes are explicitly excluded from z-index adjustments to preserve their depth-based layering

Type of Change

  • Bug fix

Testing

Tested manually — selected blocks, dragged them, deselected, verified edge and block layering across regular blocks, overlapping blocks, and subflow containers

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Mar 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 21, 2026 5:05pm

Request Review

@cursor
Copy link

cursor bot commented Mar 21, 2026

PR Summary

Medium Risk
Changes ReactFlow rendering/z-index behavior for nodes and edges; while UI-only, it can subtly affect selection/drag visuals and layering (especially in nested subflows).

Overview
Workflow canvas layering is reworked to rely on React Flow’s native zIndex instead of CSS overrides, keeping selected (and most-recently interacted) blocks visually on top.

Edges connected to selected/recent blocks are now conditionally elevated via computed edge.zIndex, and elevateEdgesOnSelect is disabled to avoid React Flow’s high z-index floor; subflow container nodes are excluded from these z-index bumps to preserve depth-based layering.

Separately, multiple workspace loading.tsx skeleton tables normalize border utility ordering (styling-only, no behavior change).

Written by Cursor Bugbot for commit 80b269f. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 21, 2026

Greptile Summary

This PR fixes z-index layering on the workflow canvas by replacing CSS class overrides (which were silently losing to React Flow's inline styles) with React Flow's native zIndex node/edge prop, establishing a clear layering contract: regular blocks at 21, last-interacted block at 22, selected block at 31, and connected edges derived from their endpoints' z-index.

Key changes:

  • Introduces lastInteractedNodeId state so a dragged/selected block stays elevated after deselection, preventing it from suddenly dropping behind overlapping blocks.
  • Adds nodesForRender memo that elevates nodes without mutating displayNodes, keeping drag-frame state and z-index state cleanly separated.
  • Addresses the previously-flagged subflow edge regression by deriving elevatedZIndex from Math.max(22, sourceNode.zIndex + 1, targetNode.zIndex + 1), so edges inside subflows (child nodes at z-1000) stay above their sibling child blocks.
  • Fixes the early-return guard with target === (node.zIndex ?? 21) so regular blocks (whose zIndex is undefined) correctly short-circuit and avoid unnecessary object allocations on every recomputation.
  • Disables elevateEdgesOnSelect (which had a hard-coded z-1000 floor that always placed connected edges above the selected node, contrary to the intended layering).
  • The 8 loading.tsx changes are unrelated cosmetic Tailwind class reorderings (likely from a formatter run) bundled into the same PR.

Confidence Score: 4/5

  • Safe to merge; the primary canvas layering bug is correctly fixed and the two previously-raised regressions have been addressed in follow-up commits.
  • Both prior review concerns (subflow edge z-index regression and the redundant object allocation) are resolved. Remaining comments are non-blocking style suggestions. The loading.tsx changes are cosmetic. No tests were added, but the change is UI/visual-only and not easily unit-testable.
  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx — specifically the stale lastInteractedNodeId after node deletion and the selectedNodeIds redundancy in edgesWithSelection.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx Core canvas fix: introduces nodesForRender memo and lastInteractedNodeId state to manage z-index layering via React Flow's native zIndex prop; addresses previously-raised edge/subflow regression concerns.
apps/sim/app/workspace/[workspaceId]/files/loading.tsx Cosmetic-only Tailwind class reordering (border-b border-[...]border-[...] border-b); no functional change.
apps/sim/app/workspace/[workspaceId]/knowledge/loading.tsx Cosmetic-only Tailwind class reordering; no functional change.
apps/sim/app/workspace/[workspaceId]/logs/loading.tsx Cosmetic-only Tailwind class reordering; no functional change.
apps/sim/app/workspace/[workspaceId]/tables/loading.tsx Cosmetic-only Tailwind class reordering; no functional change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Node in displayNodes] --> B{node.type === 'subflowNode'?}
    B -- Yes --> C[Return node unchanged\ndepth-based zIndex preserved]
    B -- No --> D[base = node.zIndex ?? 21]
    D --> E{node.selected?}
    E -- Yes --> F[target = base + 10\ne.g. regular: 31, child: 1010]
    E -- No --> G{node.id === lastInteractedNodeId?}
    G -- Yes --> H[target = Math.max\u0028base + 1, 22\u0029\ne.g. regular: 22, child: 1001]
    G -- No --> I[target = base\ne.g. regular: 21, child: 1000]
    F --> J{target === node.zIndex ?? 21?}
    H --> J
    I --> J
    J -- Yes --> K[Return same node reference\nno allocation]
    J -- No --> L[Return spread node with\nnew zIndex]

    M[Edge in edgesForDisplay] --> N{source or target\nin elevatedNodeIdSet?}
    N -- Yes --> O[elevatedZIndex = Math.max\u002822, srcZ+1, tgtZ+1\u0029\nUsing displayNodes zIndex]
    N -- No --> P[zIndex = 0]
    O --> Q[zIndex = elevatedZIndex\ne.g. regular edge: 22\nsubflow edge: 1001]
Loading

Last reviewed commit: "fix(canvas): ensure ..."

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@waleedlatif1 waleedlatif1 merged commit cb3cc37 into staging Mar 21, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/z branch March 21, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant