Trie Viz

A top-down trie (prefix-tree) visualization. Inserts a set of words into a shared-prefix tree and renders each node as a labeled circle joined to its parent. End-of-word nodes carry a concentric inner ring marker — node = letter, inner ring = word ends here. Search-path highlighting lights up the trail of nodes traversed when looking up a prefix; dimUnrelated fades branches off the path.

caprtdogTrie of: cat, car, cap, dog
Customize
Words
cat, car, cap, dog
Search
2

Installation

npx shadcn@latest add https://craftbits.dev/r/trie-viz.json

Usage

import { TrieViz } from "@craft-bits/core";
 
<TrieViz words={["cat", "car", "cap", "dog"]} />

Trace the lookup for a prefix and fade the rest of the tree:

<TrieViz
  words={["cat", "car", "cap", "dog"]}
  searchPath="car"
  dimUnrelated
/>

Understanding the component

  1. Words in, trie out. The component builds the trie internally from words — order-independent and deterministic. Each child id is ${parentId}-${char} so re-inserting the same word always lands on the same node (idempotent ids let you target them via nodeStyles).
  2. Top-down auto-layout. Each node's y is depth * rowHeight. For x, every parent gives each child a horizontal slice proportional to its leaf-count (a variant of the Reingold-Tilford "every leaf gets one column" heuristic). Children at each level sort by character so the layout doesn't depend on insertion order.
  3. Concentric end-of-word marker. A node that completes a word renders a second, inner circle at ~60% of the outer radius. The outer ring still carries the character so the marker reads visually without needing a separate badge.
  4. Search-path highlighting. searchPath="car" walks the trie one character at a time from the root, lighting every node it can reach as "highlight" and thickening the matching edges to SVG_TOKENS.edge.bold in the accent color. Partial prefixes work — the walk halts when a character isn't a child.
  5. Optional dimUnrelated. When true alongside searchPath, every node and edge that isn't on the path drops to the "dimmed" style (low-opacity fg fills). This is the "follow the trail" mode.
  6. Reduced motion. usePrefersReducedMotion() short-circuits every transition to { duration: 0 } and skips the staggered fade-in entirely.

Props

PropTypeDefaultDescription
wordsreadonly string[]requiredWords to insert into the trie. Order-independent.
searchPathstringPrefix to trace from the root. Reached nodes render as highlight.
dimUnrelatedbooleanfalseWhen true alongside searchPath, off-path nodes / edges render as dimmed.
nodeStylesRecord<string, "default" | "highlight" | "visited" | "dimmed">Per-node override keyed by node id. Wins over searchPath / dimUnrelated.
compactbooleanfalseSmaller node radius + tighter rows / cols.
classNamestringMerged onto the outer <svg>.

Accessibility

  • The outer <svg> is role="img" with an aria-label listing the inserted words and the active search prefix when present ("Trie of words: cat, car, cap, dog. Search path: car").
  • End-of-word markers are visual chrome — the readable narrative lives in aria-label.
  • Every node carries data-state and data-is-end so consumer CSS or test selectors don't have to inspect computed styles.
  • Color is never the only signal — letter labels render at every state, and the concentric inner ring marks end-of-word nodes without depending on hue.
  • Motion respects prefers-reduced-motion: node entries and edge draws collapse to instant when the user has opted out.

Credits

  • Extracted from: algoflashcards (src/lessons/primitives/viz/TrieViz.tsx). The original was a rich curriculum widget bundled with cascade explosions, reveal flips, trail-edge shatter states, ghost / mystery badges, and tappable trace overlays. The library extract is the trie primitive itself: layout + nodes + edges + end-of-word markers + search-path highlighting.