Skip to content

fix(apollo-react): improve stage return-edge snapping - #1030

Open
jevinkosasih wants to merge 5 commits into
mainfrom
fix/stage-return-edge-snap
Open

fix(apollo-react): improve stage return-edge snapping#1030
jevinkosasih wants to merge 5 commits into
mainfrom
fix/stage-return-edge-snap

Conversation

@jevinkosasih

@jevinkosasih jevinkosasih commented Aug 9, 2026

Copy link
Copy Markdown

Summary

  • make the StageNode bottom target use the standard 24px top/bottom hit window and let xyflow connection validity control pointer interaction
  • render persisted and preview stage edges from the actual selected handle coordinates
  • keep the connection preview above stage nodes while dragging

Connection compatibility remains consumer-owned through isValidConnection; this change does not restrict bottom handles to specific target handles.

Testing

  • focused existing ButtonHandle and StageNode tests: 107 passed
  • typecheck passed
  • Apollo React lint passed
  • Apollo React build passed
  • format check passed

Copilot AI lite review requested due to automatic review settings August 9, 2026 05:35
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Apollo Coded App preview deployments are ready.

Project Status Preview Updated (PT)
apollo-design Ready Preview · Logs Aug 08, 2026, 11:24:21 PM
apollo-docs Ready Preview · Logs Aug 08, 2026, 11:24:21 PM
apollo-landing Ready Preview · Logs Aug 08, 2026, 11:24:21 PM
apollo-vertex Ready Preview · Logs Aug 08, 2026, 11:24:21 PM

@github-actions github-actions Bot added the size:L 100-499 changed lines. label Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Dependency License Review

  • 1950 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 2 package(s) excluded (see details below)
License distribution
License Packages
MIT 1720
ISC 89
Apache-2.0 55
BSD-3-Clause 27
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 4
MIT-0 3
CC0-1.0 3
MIT OR Apache-2.0 2
(MIT OR Apache-2.0) 2
Unlicense 2
LGPL-3.0-or-later 1
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.3.2 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage + size by package

Per-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.

Package Coverage New-line coverage Packed (gzip) Unpacked vs main
@uipath/apollo-core 43.84 MB 57.45 MB ±0
@uipath/apollo-react 39.1% 33.3% (1/3) 7.51 MB 28.87 MB −365 B
@uipath/apollo-wind 420.6 KB 2.73 MB +8 B
@uipath/ap-chat 85.8% 43.46 MB 56.06 MB ±0

"Coverage" is each package's own coverage.include scope (e.g. apollo-core instruments only scripts/). "Packed"/"Unpacked" come from npm pack --dry-run and only cover built packages — "—" means not measured this run (package not affected / not built). "vs main" is the packed (gzipped) delta against the last successful main build (the package-sizes artifact from the Release workflow); "—" there means no main baseline was available this run. The baseline is main's latest build, not this PR's exact merge-base, so it includes any drift since the branch diverged. Packages with no vitest config are omitted.

This comment was marked as resolved.

Copilot AI review requested due to automatic review settings August 9, 2026 05:42
@github-actions github-actions Bot added size:M 30-99 changed lines. and removed size:L 100-499 changed lines. labels Aug 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/apollo-react/src/canvas/components/StageNode/StageNodeHandles.tsx:24

  • selectIsConnecting now standardizes “connecting” detection on state.connection.inProgress (avoids the stuck connectionClickStartHandle case noted in NodeUtils), but there are still components (e.g. TriggerNode) using !!state.connectionClickStartHandle. That leaves the stuck-handles behavior in place for those nodes and makes connecting UI behavior inconsistent across node types. Consider switching remaining call sites to selectIsConnecting (and updating any related mocks/tests) so all nodes follow the same, non-sticky connecting signal.
  const isConnecting = useStore(selectIsConnecting);
  const connectedHandleIds = useConnectedHandles(id);
  const hasConnections = connectedHandleIds.size > 0;

Copilot AI review requested due to automatic review settings August 9, 2026 05:50
geometry: StageEdgeGeometry;
}

function stageEdgeGeometryEquality(previous: StageEdgeGeometry, next: StageEdgeGeometry): boolean {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed because this equality helper only supported the useStore selector that rebuilt fixed upper-right and upper-left node geometry. StageEdge now consumes the live sourceX, sourceY, targetX, and targetY coordinates React Flow calculates from the registered handles, then memoizes that geometry object for StageEdgeInnerMemo. With no local store selector remaining, the custom equality function is unused dead code and React Flow remains responsible for updating the edge when a handle or node moves.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (1)

packages/apollo-react/src/canvas/styles/reactflow-reset.css:55

  • The z-index layering comment above the hovered-node rule is now inaccurate: it claims this hover bump clears the connection-line z-index (1001), but the new rule sets the connection line to 1003, which will render above hovered nodes (1002). Please update the comment to reflect the new layering so future changes don’t rely on outdated assumptions.
/* Keep the temporary drag-to-connect edge visible as it crosses stage nodes. */
svg.react-flow__connectionline {
  z-index: 1003 !important;
}

Copilot AI review requested due to automatic review settings August 9, 2026 05:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Comment on lines -176 to -186
const geometry = useStore((state: ReactFlowState): StageEdgeGeometry => {
const sourceNode = state.nodeLookup.get(rest.source);
const targetNode = state.nodeLookup.get(rest.target);

return {
sourceX: sourceNode ? sourceNode.position.x + (sourceNode.measured?.width ?? 0) : sourceX,
sourceY: sourceNode ? sourceNode.position.y + 32 : sourceY,
targetX: targetNode?.position.x ?? targetX,
targetY: targetNode ? targetNode.position.y + 32 : targetY,
};
}, stageEdgeGeometryEquality);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed because this selector discarded the handle coordinates supplied in EdgeProps and rebuilt every stage edge as upper-right header to upper-left header: source x plus width and y plus 32, then target x and y plus 32. That made bottom-to-bottom return edges render from the header even though React Flow had registered the correct bottom-handle coordinates. React Flow already updates sourceX, sourceY, targetX, and targetY when handles or nodes move, so StageEdge now memoizes those supplied values and no longer needs a direct nodeLookup subscription.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Storybook visual diff

⚠️ Visual changes detected: 14 changed (of 302 compared, 288 unchanged). View report

Baseline is the deployed main Storybook, so changes merged to main after this branch was last updated can also appear here. Logs

Updated (PT): Aug 08, 2026, 11:40:05 PM

Copilot AI review requested due to automatic review settings August 9, 2026 06:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Comment on lines -35 to -39
const sourceX = fromNode ? fromNode.position.x + (fromNode.measured?.width ?? 0) : fromX;
const sourceY = fromNode?.position.y ? fromNode.position.y + 32 : fromY;

const targetX = toNode ? toNode.position.x : toX;
const targetY = toNode ? toNode.position.y + 32 : toY;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed because these calculations forced the connection preview from the source stage upper-right header to the target stage upper-left header whenever node objects were available, regardless of which handles were active. For a bottom-to-bottom return edge, React Flow already provides the exact registered bottom-handle coordinates through fromX, fromY, toX, and toY; overriding them here made the ghost edge originate and land at the header. Passing those coordinates directly preserves the selected handles, the live cursor or snapped target position, and also avoids the position.y equals zero truthiness issue.

@jevinkosasih

Copy link
Copy Markdown
Author

PO.Frontend integration note: Case Management uses Apollo StageNode and its handles, but it does not use Apollo StageEdge or StageConnectionEdge. Persisted case-management edges are rendered by PO.Frontend through CaseManagementTransitionEdge and CaseManagementEdge, while the drag preview uses PreviewConnectAndReconnectEdge and PreviewEdgePath. That is why production edges could render correctly even though Apollo own edge components always reconstructed upper-right to upper-left header geometry.

For the original bottom-handle locking issue, the production-relevant fix is in ButtonHandle and StageNodeHandles: visible handles no longer force pointer events over xyflow connection-state handling, so the overlapping bottom source cannot intercept the pointer from the bottom target; the target also gets a centered 24 by 24 hit area. The connection-line z-index applies to PO custom preview as well. The StageEdge and StageConnectionEdge coordinate changes correct Apollo Storybook and direct consumers, but PO currently bypasses those renderers.

Once this change is released and PO.Frontend bumps to the published Apollo version containing it, the bottom target should lock correctly without the PO inline handle workaround. The consumer workaround should be removed when validating the bump so the Apollo behavior is tested directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:apollo-react size:M 30-99 changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants