ui: improve topology graph readability (#136) - #153
Merged
antoncxx merged 1 commit intoAug 10, 2026
Conversation
Adds a matrix (adjacency-grid) view alongside the existing layered mode, and reworks layered-mode edge routing to stop cutting through unrelated nodes and labels: - Layered mode: multi-layer-spanning edges (a proxy hop straight into a service several dependency-layers deep, a deep service-to-service edge, or an egress hop back to a distant proxy) now reserve a dummy waypoint slot in every intermediate layer, so the crossing-reduction sweep pushes real nodes out of the way instead of letting the edge draw a raw curve through them. Default edge labels anchor to that same reserved slot rather than the raw (and potentially occupied) endpoint midpoint. - Mutual pairs (A->B and B->A between the same two nodes, e.g. a two-node cycle) get separated into two parallel tracks - their curves and labels used to be geometrically identical and fully overlap. - Node highlighting is click-only (selectedNodeId), not hover. - Matrix mode: adjacency grid ordered proxies-then-services, filled cell = edge, independent row/column hover highlighting (previously a single shared index meant only the diagonal could ever highlight). Also adds a /debug/topology page (unauthenticated, not in the sidebar) that renders a pasted or file-loaded GraphJson through the real topology components with no backend, for iterating on layout math against arbitrary topologies. Star, radial, and grouped layout modes were explored and implemented along the way but ultimately dropped in favor of layered + matrix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Dense service meshes made the layered Topology view hard to read: edges
routinely cut straight through unrelated nodes and labels, egress edges swept
diagonally across the whole diagram to reach the proxy, and a cycle between
two nodes could draw both directions as literally the same overlapping curve
and label. This PR fixes the routing itself rather than just adding another
view on top of it, and adds an adjacency-matrix view as a genuinely different
way to read a dense graph.
What changed
Layered mode — long-edge routing
Any edge that spans more than one layer (a proxy hop straight into a service
several dependency-layers deep, a deep service-to-service edge, or an egress
hop back to a distant proxy) now reserves a dummy waypoint slot in every
intermediate layer it crosses. The existing crossing-reduction sweep treats
those slots like real nodes, so it pushes actual nodes out of the way instead
of letting the edge draw a raw curve through them. Default edge labels anchor
to that same reserved slot instead of the raw endpoint midpoint, which — for
a waypoint-routed edge — could land squarely on top of an unrelated node.
Mutual-pair separation
A→BandB→Abetween the same two nodes (e.g. a two-node cycle) hit amidpoint-symmetric formula: both directions computed the identical curve and
the identical label position, so one fully occluded the other. They now
separate into two parallel tracks — a modest bow for the curves, a larger
offset for the labels since text needs more clearance than a stroke does.
Egress edges
Previously bowed a fixed 46px past the source's own right edge before
curving to the proxy — fine when the proxy is close, but since it usually
sits far to one side, the curve had to sweep across the whole diagram to
reach it. Layer-skipping egress edges now use the same reserved-lane
mechanism as the long-edge fix above instead of a special-cased bow.
Node highlighting
Reverted to click-only (
selectedNodeId). It previously highlighted anode's connections on hover, which dimmed the rest of the graph on every
mouse pass.
New: matrix view
An adjacency-grid alternative to the node-link diagram — rows/columns
ordered proxies-then-services, a filled cell means an edge exists. Row and
column hover highlighting track independently (a node's row and its column
are usually different indices for an actual edge — an earlier iteration
shared one index for both, which meant only the diagonal could ever
highlight).
New:
/debug/topologypageUnauthenticated, not linked from the sidebar. Paste or load a
GraphJsonfile and it renders through the exact same components the real Topology page
uses, with no backend involved — for iterating on layout math against
arbitrary topologies without a running stack.
Explored and dropped
Star (hub-and-spoke) and radial (ego-network) hub-focused layouts, and a
grouped (connected-components) layout, were implemented and evaluated
alongside the above but ultimately removed — layered (now fixed) plus matrix
covered the actual need better than either.
Relates to #136 .