Loading page…
Loading page…
A custom directed graph with pure-SVG connectors. Drag any node from its grip to re-route the layout; onNodeMove persists coordinates upstream. Click a card to open its morphing detail dialog. Identifier text remains independently selectable inside the node.
Two spent UTXOs fund one transaction that pays a recipient and returns change. Drag grips reposition nodes. Click card chrome to open details; select/copy full address or txid text without opening it.
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-accentThe canvas spans the full specimen width while the fixed graph stays centered in the available space. Nodes place on a 3-column grid; the tx sits on the middle row between its two inputs.
Node selection highlights one-hop neighbors. Node activation opens a centered morphing dialog with identifier, amount, structured detail rows, and an optional renderNodeDetails extension.
<TransactionFlow
nodes={nodes}
edges={edges}
draggable
onNodeMove={(id, position) => savePosition(id, position)}
onNodeOpen={(node) => audit(node.id)}
renderNodeDetails={(node) => <ProviderEvidence node={node} />}
/>--ch-focus--ch-surface-raised--ch-shadow-floatA 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-1Both connectors are status:'pending' — dashed + flowing.
Funding reaches an exchange hot wallet (confirmed), but the withdrawal is reverted — that connector reads danger-red with a 'reverted' caption, and an animated return arrow arcs below the flow back to the origination address, its dashes streaming backward while the origin card pulses a danger keyline. returnTo picks the return target (defaults to the flow's first node); both animations freeze under prefers-reduced-motion.
Transaction flow: 3 nodes, 2 connections. Funding 1.0000 to Exchange (confirmed); Exchange to Withdrawal (failed, returned to Funding).
<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", returnTo: "f-in" },
]}
/>--ch-danger--ch-border--ch-viz-1The second edge is status:'failed' with returnTo:'f-in' — red forward leg plus the animated return arc to Funding.
Each kind maps to a lucide glyph, a tone, and a silhouette: tx keeps the square baseline card; input/output carry a 2px directional accent edge (left = value in, right = value out); address softens with rounded corners; exchange draws a double keyline (inset hairline); coinjoin frames dashed. 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={[]} />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