Interactive SVGs in 85 lines
A static diagram is a picture. Click a node and watch its neighbors light up while everything else fades, and suddenly it's a tool. Code Explorer adds this to every diagram with 85 lines of TypeScript. No D3. No React. Just the DOM.
The contract
The renderer and the interaction code never talk to each other directly. They communicate through data attributes on the SVG elements:
<!-- Nodes -->
<g class="graph-node" data-node-id="UserService">...</g>
<!-- Edges -->
<path class="graph-edge"
data-edge-from="UserService"
data-edge-to="Database" />
That's the entire interface. The renderer can change layout, colors,
shapes, whatever it wants. As long as nodes have data-node-id
and edges have data-edge-from / data-edge-to,
interaction keeps working.
One click handler
Instead of attaching listeners to every node, one handler on the SVG catches
everything. closest(".graph-node") walks up to find which node
was clicked:
svg.addEventListener("click", (e) => {
const node = e.target.closest(".graph-node");
if (node) highlight(node.getAttribute("data-node-id"));
else clearHighlight();
});
The highlight function collects connected node IDs from the edge attributes, sets full opacity on the selected node and its neighbors, and dims everything else to 12%. A 150ms CSS transition makes it smooth.
Why not a library
D3 is 80KB minified. Code Explorer's entire interaction module is
85 lines. The SVG is already in the DOM (the renderer puts it there).
The DOM already has event delegation, closest(), attribute
selectors, and CSS transitions. There's nothing left for a library to do.
The data-attribute contract also means the renderer and the interaction code can evolve independently. New diagram types get interactivity for free as long as they tag their elements. Code Explorer has three diagram types. All three share the same 85-line file.
code-explorer — try it live