Transaction Flow
A custom, dependency-free directed graph — no react-flow, no canvas. FlowNodeCards are placed on a column/row grid over a pure-SVG connector layer of smooth cubic beziers, colored only from the --ch-* token scale. Connector status tints the path (confirmed → success, pending → warning, failed → danger); pending dashes flow and freeze under reduced motion. Click or focus any node to highlight its neighborhood.
Worked example — inputs → tx → outputs
Two spent UTXOs fund one transaction that pays a recipient and returns change. The tx hub carries the aurum emphasis ring; every leg is confirmed, so connectors read success-green with amount captions at each midpoint. Fee = 0.5700 in − 0.5680 out = 0.0020 BTC. Click a node to trace only its neighborhood.
Transaction flow: 5 nodes, 4 connections. UTXO 0.4200 to Transaction (confirmed); UTXO 0.1500 to Transaction (confirmed); Transaction 0.5000 to Recipient (confirmed); Transaction 0.0680 to Change (confirmed).
const nodes: FlowNode[] = [
{ id: "in-1", kind: "input", label: "UTXO", amount: "0.4200 BTC", column: 0, row: 0 },
{ id: "in-2", kind: "input", label: "UTXO", amount: "0.1500 BTC", column: 0, row: 2 },
{ id: "tx", kind: "tx", label: "Transaction", column: 1, row: 1, emphasis: true },
{ id: "out-1", kind: "output", label: "Recipient", amount: "0.5000 BTC", column: 2, row: 0 },
{ id: "out-2", kind: "output", label: "Change", amount: "0.0680 BTC", column: 2, row: 2 },
];
const edges: FlowEdge[] = [
{ id: "c-e1", from: "in-1", to: "tx", amount: "0.4200" },
{ id: "c-e3", from: "tx", to: "out-1", amount: "0.5000" },
];
<TransactionFlow nodes={nodes} edges={edges} />--ch-viz-1--ch-success--ch-border--ch-surface--ch-accent
Nodes place on a 3-column grid; the tx sits on the middle row so it centers between its two inputs.
Pending — flowing dashes
A deposit routes through a CoinJoin round to a fresh output. Pending legs render dashed in warning-amber and animate strokeDashoffset for a flowing effect — the animation freezes to a static dash under prefers-reduced-motion.
Transaction flow: 3 nodes, 2 connections. Deposit 0.2500 to CoinJoin (pending); CoinJoin 0.2499 to Fresh UTXO (pending).
<TransactionFlow
nodes={[{ id: "p-in", kind: "input", … }, { id: "p-cj", kind: "coinjoin", emphasis: true, … }, { id: "p-out", kind: "output", … }]}
edges={[{ id: "p-e1", from: "p-in", to: "p-cj", amount: "0.2500", status: "pending" }, …]}
/>--ch-warning--ch-border--ch-viz-1
Both connectors are status:'pending' — dashed + flowing.
Failed — a reverted leg
Funding reaches an exchange hot wallet (confirmed), but the withdrawal is reverted — that connector reads danger-red with a 'reverted' caption. Statuses are per-edge, so a single graph can mix confirmed, pending, and failed legs.
Transaction flow: 3 nodes, 2 connections. Funding 1.0000 to Exchange (confirmed); Exchange to Withdrawal (failed).
<TransactionFlow
nodes={[{ id: "f-in", kind: "input", … }, { id: "f-ex", kind: "exchange", … }, { id: "f-out", kind: "address", … }]}
edges={[
{ id: "f-e1", from: "f-in", to: "f-ex", amount: "1.0000", status: "confirmed" },
{ id: "f-e2", from: "f-ex", to: "f-out", label: "reverted", status: "failed" },
]}
/>--ch-danger--ch-border--ch-viz-1
The second edge is status:'failed'; its label overrides the amount caption.
Node gallery — every kind
Each kind maps to a lucide glyph and a tone: input=primary, output=accent, tx=fg, address=muted, exchange=info, coinjoin=warning. Emphasis (shown on the tx) draws the aurum accent ring. Optional mono amount sits under the title.
Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-input", kind: "input", label: "UTXO" }]} edges={[]} />Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-output", kind: "output", label: "Recipient" }]} edges={[]} />Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-tx", kind: "tx", label: "Transaction", emphasis: true }]} edges={[]} />Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-address", kind: "address", label: "Address" }]} edges={[]} />Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-exchange", kind: "exchange", label: "Exchange" }]} edges={[]} />Transaction flow: 1 nodes, 0 connections.
<TransactionFlow nodes={[{ id: "g-coinjoin", kind: "coinjoin", label: "CoinJoin" }]} edges={[]} />Connector tokens
Connectors and node chrome read only from the --ch-* token scale, so the graph re-themes with the rest of the system across dark, light, and Harbor Mode. Status maps straight to the semantic tokens; node tints ride viz-1 (input / primary), accent (output), and border/surface for the card frame.
--ch-viz-1--ch-success--ch-warning--ch-danger--ch-border