fix: avoid Sankey nodes overlapping skipped-depth links#7471
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughAdds a Bezier-based link–node collision resolution algorithm ( ChangesSankey node–link collision resolution
Sequence Diagram(s)No sequence diagram generated: the changes are primarily geometric/collision-resolution logic and data structure extensions rather than multi-component request/response flows. Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/chart/Sankey.tsx (1)
521-538: 💤 Low valueConsider: backward pass may push nodes into obstacles above.
When the backward pass shifts nodes up to fit within
height, it doesn't re-verify collision with fixed obstacles positioned above the shifted node. In edge cases with multiple stacked obstacles and constrained height, a node could end up overlapping an obstacle.For the scoped fix targeting "fully contained" nodes (issue
#5559), this is likely acceptable since such complex configurations are rare. If broader collision handling is needed later, consider iterating until stable or using a constraint solver.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/chart/Sankey.tsx` around lines 521 - 538, The backward pass loop iterating from items.length - 1 to 0 shifts nodes upward to fit within the height constraint, but it does not re-verify collision with fixed obstacles positioned above the shifted node. To fully address this, you would need to check each shifted node against all fixed obstacles above it, or implement an iterative approach that repeats until the layout stabilizes, or use a constraint solver. However, since this fix is scoped to "fully contained" nodes per issue `#5559` where such complex stacked configurations are rare, add a code comment near the dy calculation in the backward pass loop documenting this known limitation so future maintainers understand the collision handling scope.test/chart/Sankey.spec.tsx (1)
27-55: 💤 Low valueConsider validating coordinate array length for clearer test failures.
If the SVG path format changes or is malformed, the destructuring will produce
undefinedvalues leading toNaNcalculations. Adding a guard would provide a clearer error message:🛡️ Optional defensive check
if (coordinates == null) { throw new Error('Expected Sankey link path to have coordinates'); } + + if (coordinates.length < 8) { + throw new Error(`Expected Sankey link path to have at least 8 coordinates, got ${coordinates.length}`); + } const [sourceX, sourceY, sourceControlX, sourceControlY, targetControlX, targetControlY, targetX, targetY] =🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/chart/Sankey.spec.tsx` around lines 27 - 55, The getLinkYAtX function validates that coordinates exist but does not validate that the coordinates array has the expected length of 8 elements. If the SVG path format changes or is malformed, the destructuring will silently assign undefined values leading to NaN calculations. Add a length check after the null check to ensure the coordinates array contains exactly 8 elements, and throw a descriptive error if it does not, improving the clarity of test failures when the path format is unexpected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/chart/Sankey.tsx`:
- Around line 521-538: The backward pass loop iterating from items.length - 1 to
0 shifts nodes upward to fit within the height constraint, but it does not
re-verify collision with fixed obstacles positioned above the shifted node. To
fully address this, you would need to check each shifted node against all fixed
obstacles above it, or implement an iterative approach that repeats until the
layout stabilizes, or use a constraint solver. However, since this fix is scoped
to "fully contained" nodes per issue `#5559` where such complex stacked
configurations are rare, add a code comment near the dy calculation in the
backward pass loop documenting this known limitation so future maintainers
understand the collision handling scope.
In `@test/chart/Sankey.spec.tsx`:
- Around line 27-55: The getLinkYAtX function validates that coordinates exist
but does not validate that the coordinates array has the expected length of 8
elements. If the SVG path format changes or is malformed, the destructuring will
silently assign undefined values leading to NaN calculations. Add a length check
after the null check to ensure the coordinates array contains exactly 8
elements, and throw a descriptive error if it does not, improving the clarity of
test failures when the path format is unexpected.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 94fc690a-3eec-4bf0-870c-63de92db610d
📒 Files selected for processing (2)
src/chart/Sankey.tsxtest/chart/Sankey.spec.tsx
Bundle ReportChanges will decrease total bundle size by 34.96kB (-0.62%) ⬇️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: recharts/bundle-treeshaking-cartesianAssets Changed:
view changes for bundle: recharts/bundle-es6Assets Changed:
view changes for bundle: recharts/bundle-cjsAssets Changed:
view changes for bundle: recharts/bundle-treeshaking-polarAssets Changed:
view changes for bundle: recharts/bundle-umdAssets Changed:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7471 +/- ##
==========================================
+ Coverage 88.25% 88.43% +0.17%
==========================================
Files 607 602 -5
Lines 14102 13978 -124
Branches 3544 3532 -12
==========================================
- Hits 12446 12361 -85
+ Misses 1469 1434 -35
+ Partials 187 183 -4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Screenshots and/or a VR test would be welcome here |
|
Thanks for the note. This PR now includes both a VR case for the skipped-depth Sankey overlap and the generated Chromium/Firefox/WebKit snapshots, plus a unit-level geometry assertion for the same overlap case. I also rechecked the targeted verification locally:
Could you please take another look when you have a chance? |

Description
Fixes a Sankey layout case where a high-value link can skip over an intermediate depth and visually cover smaller nodes in that depth.
This keeps the existing node sizing and
nodePaddingbehavior unchanged. After the normal Sankey relaxation and collision passes complete, the layout now checks links that span across intermediate depth columns. If an intermediate node is fully contained inside one of those skipped-depth link bands, that link is treated as a fixed local obstacle and the affected depth is adjusted once.Related Issue
Fixes #5559.
Motivation and Context
The workaround discussed in the issue is to increase
nodePadding, but that does not scale well when a Sankey chart has many nodes. The root problem is that normal node collision handling only considers nodes in the same depth, while a link that skips a depth can still occupy visual space in that column.The fix is intentionally scoped to the overlap case from the issue, so normal Sankey layouts are not rescaled and existing coordinate-sensitive behavior is preserved.
How Has This Been Tested?
npm run test-lib -- test/chart/Sankey.spec.tsx -t "should keep intermediate nodes out of links that skip over their depth"npm run test-lib -- test/chart/Sankey.spec.tsxnpm exec eslint src/chart/Sankey.tsx test/chart/Sankey.spec.tsxnpm run check-types-libnpm run check-types-testScreenshots (if appropriate):
Not included. The regression test checks that the intermediate nodes no longer sit inside the skipped-depth link band.
Types of changes
Checklist:
Summary by CodeRabbit
Bug Fixes
Tests