Level Work Bars
A row-per-level visualization of the work done at every depth of a divide-and-conquer recursion tree. Each level draws count bars whose individual widths encode workPerNode, so the row totals reveal whether the per-level work grows, shrinks, or stays constant — the geometric structure that makes the Master Theorem (and the O(n log n) total work of merge sort) visible rather than algebraic.
T(n)
1×8= 8
T(n/2)
2×4= 8
T(n/4)
4×2= 8
T(1)
8×1= 8
32
Customize
Highlight
none
Annotations
Installation
npx shadcn@latest add https://craftbits.dev/r/level-work-bars.jsonUsage
import { LevelWorkBars } from "@craft-bits/core";
const levels = [
{ count: 1, workPerNode: 8, label: "T(n)" },
{ count: 2, workPerNode: 4, label: "T(n/2)" },
{ count: 4, workPerNode: 2, label: "T(n/4)" },
{ count: 8, workPerNode: 1, label: "T(1)" },
];
<LevelWorkBars levels={levels} />Highlight one specific level to draw the eye to a recurrence step:
<LevelWorkBars levels={levels} highlightLevel={1} />Understanding the component
- One row per recursion level. Index
0is the root; deeper indices are deeper subproblems. Each row drawscountbars whose widths are proportional toworkPerNode, so a row's total bar width tracks the work performed at that level. - Widths normalised to the largest
workPerNode. The merge-sort root doesnwork in a single bar; the leaves do1work each, innbars. The widths reflect per-node cost — not per-level total — so the depth/fan-out/cost relationship is preserved. layoutIdper bar. When the caller animates between two recurrences (e.g.T(n) = 2T(n/2) + nvsT(n) = 4T(n/2) + n), bars glide viaSPRINGS.smoothinstead of cross-fading.- Highlighted level scales 1.03 + accent fill. Pass
highlightLevel={k}to single out a row; the others drop to the muted scale. - Optional running totals.
showTotalsadds acount × work = totalchip on the right of each row;showSumadds a sigma row underneath summing the work across every level. - Reduced motion. Layout transitions and bar entrances collapse to
{ duration: 0 }so the final state is reachable without animation.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
levels | readonly { count: number; workPerNode: number; label?: string }[] | required | One entry per recursion level. Returns null when empty. |
highlightLevel | number | -1 | Index of the level to render in the accent color. -1 shows every level equally. |
showTotals | boolean | true | Render the count × work = total chip on the right of each row. |
showSum | boolean | true | Render a sigma-total row below the level rows. |
className | string | — | Merged onto the outer <div> via cn(). |
Accessibility
- The root is
role="img"with anaria-labelthat flattens every level into a readable trail and reports the grand total. - Color is never the only signal — highlighted and muted rows are distinguishable by scale, opacity, and the per-row total.
- Bars carry
aria-hidden="true"; the row's textual content carries the screen-reader meaning. - Motion respects
prefers-reduced-motion: layout transitions and bar entrances collapse to{ duration: 0 }.
Credits
- Extracted from:
algoflashcards(src/lessons/primitives/viz/LevelWorkBars.tsx). The original was a one-bar-per-level chart driven by a singleworkPerLevel: number[]plus a precomputedmaxWork, used to land the "every level isncomparisons" insight for merge sort. The library version reframes the structure around the recurrence itself — every level iscount × workPerNode— supports ahighlightLevelaccent, an optional sigma-total row, and sharedlayoutId-driven transitions between recurrences.