Skip to content

feat(ui): dagre layered service map — routed edges, level-of-detail, draggable#113

Merged
aksOps merged 2 commits into
mainfrom
ui/reactflow-premium
Jun 18, 2026
Merged

feat(ui): dagre layered service map — routed edges, level-of-detail, draggable#113
aksOps merged 2 commits into
mainfrom
ui/reactflow-premium

Conversation

@aksOps

@aksOps aksOps commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Reworks the React Flow service map to scale to ~120 services without edges disappearing under nodes.

What changed

  • Layout → dagre layered (@dagrejs/dagre, MIT): crossing-minimised, left→right, with edge-routing waypoints. Replaces the radial/phyllotaxis layout. Computed synchronously — deterministic and identical in every browser.
  • Routed edges: drawn through the dagre waypoints with endpoints pinned to each node's border (toward the adjacent waypoint), so links meet the chip edge — not the centre — and follow a dragged node. Capped-thin stroke, native animated flow; failing edges carry --crit.
  • Level-of-detail: chips collapse to status dots below 0.62 zoom (edges switch to centre-to-centre) so the 168px boxes stop occluding the field at scale.
  • Draggable nodes: useNodesState reconcile re-seeds on a fresh layout / topology change; on a metric-only poll it keeps drags + React Flow's measured dims (no full re-measure).
  • Right side-panel autosize: fit-content (capped) to the service names, fixing the phantom horizontal scrollbar from the fixed 300px + overflow-y:auto promotion.

Trade-off

dagre runs synchronously, so a ~120-service layout would block the main thread ~0.5–1.2s on mount / topology change (imperceptible at normal scale). A Web Worker is the eventual fix — deferred until the scale demands it (an earlier worker attempt was reverted for cross-browser fragility).

Validation

tsc 0 · eslint 0 · 377 vitest · build + budgets (ConstellationHome 72.7/76 KB gz) · jscpd 0.44% · go build + go vet · headless screenshots confirm 7 services render, edges meet borders, a dragged node's edge follows.

Follow-up (not in this PR): radialLayout.ts + layoutGraph are now unused — pruned separately in #112.

🤖 Generated with Claude Code

…draggable

Replace the radial/phyllotaxis layout with a dagre layered layout
(@dagrejs/dagre, MIT) for the React Flow service map: crossing-minimised,
left→right, with edge-routing waypoints so links thread between ranks and
meet node borders instead of disappearing under boxes at scale. Computed
synchronously — deterministic, instant at normal scale, identical in every
browser.

- Edges route through the dagre waypoints; endpoints pinned to each node's
  border (toward the adjacent waypoint) so they meet the chip edge and follow
  a dragged node. Capped-thin, native animated flow; failing edges carry --crit.
- Level-of-detail: chips collapse to status dots below 0.62 zoom (edges switch
  to centre-to-centre) so the 168px boxes stop occluding the field at ~120
  services.
- Draggable nodes: useNodesState reconcile re-seeds on a fresh layout / topology
  change, and on a metric-only poll keeps drags + React Flow's measured dims.
- Right side-panel autosizes to the service names (fit-content, capped), fixing
  the phantom horizontal scrollbar.

Trade-off: dagre runs synchronously, so a ~120-service layout would block the
main thread ~0.5–1.2s on mount/topology change (imperceptible at normal scale);
a Web Worker is the eventual fix, deferred until needed.

Verified: tsc, eslint, 377 vitest, build + budgets (ConstellationHome 72.7/76 KB
gz), jscpd 0.44%, go build + vet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDQVJrixs2nJoea67a8pEG
@socket-security

socket-security Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​dagrejs/​dagre@​3.0.01001007686100

View full report

- S2871 (reliability bug): give the shape-hash edge-key sort an explicit
  localeCompare comparator (a bare .sort() is an unreliable UTF-16 sort).
- S7755: use Array.prototype.at(-1)/at(-2) instead of [length - n].
- S3735: drop the `void` operator on the fitView calls (block-body arrows).

No behaviour change. tsc 0, eslint 0, 9 map tests, build + budgets green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LDQVJrixs2nJoea67a8pEG
@sonarqubecloud

Copy link
Copy Markdown

@aksOps aksOps merged commit 9b92240 into main Jun 18, 2026
17 checks passed
@aksOps aksOps deleted the ui/reactflow-premium branch June 18, 2026 07:42
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