Reduction Tree Animator
A binary-tree reduction visualisation tuned for teaching parallel sum and tree all-reduce. N workers sit at the leaves; at each level, adjacent pairs combine into one value, halving the active worker count: N → N/2 → N/4 → … → 1. After log₂ N levels every worker's contribution has been folded into the root. Where RingAllReduceViz shows the ring-topology variant used by NCCL, this is the tree variant — use it in lessons that introduce reduction as a divide-and-conquer pattern before discussing ring-based scheduling.
Reduction tree. 8 leaves, log₂ 8 = 3 levels.
Reduction treelevel 00 / 03
Customize
Tree
8
0
Playback
800ms
Installation
npx shadcn@latest add https://craftbits.dev/r/reduction-tree-animator.jsonUsage
import { ReductionTreeAnimator } from "@craft-bits/core";
<ReductionTreeAnimator numLeaves={8} />Pass your own per-worker values:
<ReductionTreeAnimator
numLeaves={8}
values={[3.2, 1.5, 4.8, 0.9, 2.1, 5.3, 1.7, 3.6]}
/>Drive playback from outside the component:
const [level, setLevel] = useState(0);
<ReductionTreeAnimator
numLeaves={8}
currentLevel={level}
onCurrentLevelChange={setLevel}
playing={false}
/>Understanding the component
- One cursor, one wavefront.
currentLevelindexes0 … log₂(numLeaves). Level0shows just the leaves; levellshows every node up to depthl. Pairs freshly combined at the active level light up in--cb-accent; already-swept levels stay tinted; not-yet-swept levels stay dimmed. - Edges are the wavefront. Active edges (those feeding the current level) use the
boldstroke and--cb-accentcolour. Already-swept edges stay at a tinted opacity so the user can see the trail; not-yet-swept edges hold a low opacity so the diagram never goes blank. - Snap to power of two.
numLeavesis rounded down to the nearest power of two (clamped to[2, 64]). Binary reduction is only clean on powers of two — rather than pretend otherwise, the component normalises silently. - Synthesised values when shape-only. Pass
numLeaves={8}withoutvaluesand the component renders deterministic placeholder leaves (sine-phased). The diagram never renders blank, but you should pass real values when you have them. SPRINGS.smoothon the active edge / node. Level transitions use the smooth spring from@craft-bits/core/motionso the wavefront settles between levels rather than snapping.- Reduced-motion fallback. With
prefers-reduced-motion: reduce, the tree renders fully reduced on mount with no autoplay and no per-level animation. - Auto layout from
numLeavesalone. Every internal node sits horizontally above the midpoint of its two children; levels are evenly spaced vertically. ChangenumLeavesand the tree re-flows.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
numLeaves | number | 8 | Number of leaf workers. Rounded down to the nearest power of two in [2, 64]. |
values | readonly number[] | — | Per-leaf values (length matches numLeaves). Synthesised if omitted. |
currentLevel | number | — | Controlled cursor in [0, log₂(numLeaves)]. Pair with onCurrentLevelChange. |
defaultCurrentLevel | number | 0 | Uncontrolled initial cursor. |
onCurrentLevelChange | (level) => void | — | Fires on tick and on manual scrub. |
playing | boolean | — | Controlled play state. Pair with onPlayingChange. |
defaultPlaying | boolean | false | Uncontrolled initial play state. |
onPlayingChange | (playing) => void | — | Fires when play / pause flips. |
playSpeed | number | 800 | Milliseconds between level advances during autoplay. |
transition | Transition | SPRINGS.smooth | Spring for active-edge / node transitions. |
className | string | — | Merged onto the root <div> via cn(). |
Accessibility
- The figure is
role="figure"witharia-label="Reduction tree visualization". - An
aria-live="polite"summary announces the active level, the number of active workers, and the final root value when reduction completes. - The play / pause button is
aria-pressed; the label flips between "Play reduction" and "Pause reduction". - The scrubber is a native
<input type="range">with an explicitaria-label, so keyboard arrows nudge the cursor and screen readers narrate the value. - Colour is never the only signal — level counter and per-node value labels are textual.
prefers-reduced-motion: reducerenders the tree fully reduced on mount and disables autoplay.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/ReductionTreeAnimator.tsx). The source was a multi-mode lesson widget (max / sum / Welford reduction, plus a "break the barrier" pedagogical toggle, plus an embedded Explore / Predict mode strip with quiz pool and DoneCard). Stripped the predict mode, the mode strip, the Welford struct, the barrier-break demo, the narration helpers, theChallengeBtn/TogglePillchrome, and theusePredictRoundsdependency. Generalised the surviving binary-tree reduction into the public surface: a flatnumLeaves/valuespair with controlled / uncontrolled cursor and play state, sum-only aggregation (the cleanest teaching default), and--cb-accentsemantic colour wired throughSVG_TOKENS. Architecture mirrorsForwardPassAnimator(auto layout from a single shape argument, level cursor sweeping a wavefront) so the two compose cleanly in side-by-side lessons.