DAG Renderer
A directed acyclic graph. Pass a flat list of nodes and directed edges and the component lays them out by topological rank (Kahn's algorithm). Every node at depth k shares the same coordinate on the layout axis, so dependencies read cleanly left-to-right (default) or top-to-bottom. Ideal for narrating topological sort, dependency graphs, computation graphs, and build pipelines.
Customize
Layout
Highlight
build
Installation
npx shadcn@latest add https://craftbits.dev/r/dag-renderer.jsonUsage
import { DAGRenderer, type DAGEdge, type DAGNode } from "@craft-bits/core";
const nodes: DAGNode[] = [
{ id: "install", label: "install" },
{ id: "lint", label: "lint" },
{ id: "test", label: "test" },
{ id: "build", label: "build" },
{ id: "deploy", label: "deploy" },
];
const edges: DAGEdge[] = [
{ from: "install", to: "lint" },
{ from: "install", to: "test" },
{ from: "lint", to: "build" },
{ from: "test", to: "build" },
{ from: "build", to: "deploy" },
];
<DAGRenderer
nodes={nodes}
edges={edges}
nodeStyles={{ build: "highlight" }}
/>Top-down direction for tall stack-like reveals:
<DAGRenderer nodes={nodes} edges={edges} direction="top-down" />Understanding the component
- Topological rank via Kahn's algorithm. Each render computes one rank per node by repeatedly peeling off zero-indegree nodes. The rank is the longest path from any source — a node with parents at ranks 1 and 3 lands at rank 4, not rank 2 — so edges flow forward by construction.
- Cycles throw. A DAG must be acyclic by contract. If Kahn's pass leaves nodes unresolved, the component throws with the unresolved ids in the message so the caller can pinpoint the offending edges.
- Auto-layout, two axes. Nodes at the same rank share the main-axis coordinate (x for
top-down, y forleft-right) and spread along the cross axis. Within a rank, nodes are sorted by their position in thenodesarray so the layout is deterministic across re-renders. - Curved edges for rank skips. In
left-rightmode, edges that span more than one rank draw as quadratic Bézier arcs viacurvedEdgePath. Adjacent-rank edges stay straight.top-downmode draws all edges straight. - Stagger by rank. Node and edge entry animations stagger by topological rank (
delay = rank * STAGGER). The graph reveals layer by layer, mirroring the algorithm's frontier expansion. - Four node styles + shared markers.
"default"/"highlight"/"visited"/"dimmed"map onto the canonical algorithmic states. Arrowheads come from the shared<SvgDefs>block, so geometry stays consistent across every graph component in the library. - Reduced motion.
usePrefersReducedMotion()short-circuits every transition to{ duration: 0 }— nodes and edges snap into place when the user has opted out.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
nodes | readonly { id: string; label: string }[] | required | Nodes in the graph. Order seeds within-rank slot order. |
edges | readonly { from: string; to: string }[] | required | Directed edges. Must form an acyclic graph. |
nodeStyles | Record<string, "default" | "highlight" | "visited" | "dimmed"> | — | Per-node visual override keyed by node id. |
direction | "top-down" | "left-right" | "left-right" | Layout axis. |
compact | boolean | false | Squeeze padding ~20%. |
className | string | — | Merged onto the outer <svg>. |
Accessibility
- The outer
<svg>isrole="img"with anaria-labelsummarizing the graph ("Directed acyclic graph with 5 nodes: install, lint, test, build, deploy."). - Every node renders its label as a child
<text>, so the four node styles (highlight,visited,dimmed,default) layer on top of readable text — color is never the only signal. - Motion respects
prefers-reduced-motion: node entries, edge draws, and the rank-stagger reveal all collapse to instant when the user has opted out.
Credits
- Extracted from:
algoflashcards(src/lessons/primitives/viz/DAGRenderer.tsx). The original took pre-positioned{ x, y }node coordinates plus ahexaccent and a five-state set (in-degree badges, ready/processed/spotlight sets, highlightEdges). The library version inverts the contract — callers describe the graph, the component computes the layout — and consolidates the state palette to four canonical styles.