Chain Rule Flow Viz

Shows the chain rule as a flow. A row of boxes lays out a composition like x → g(x) → f(g(x)) left-to-right, with forward arrows carrying their local derivatives between them. Curved arcs above the row sweep right-to-left, one edge at a time, to show how the chain-rule product is assembled by multiplying local derivatives along the backward pass.

Backward edge 1 of 2 highlighted — gradient flowing from link 3 back to link 2.
Chain rule flowedge 01 / 02
g'(x) = 2xf'(g(x)) = cos(x²)xg(x) = x²f(g(x)) = sin(x²)
Customize
Cursor
1 / 2 (backward)
Playback

Installation

npx shadcn@latest add https://craftbits.dev/r/chain-rule-flow-viz.json

Usage

import { ChainRuleFlowViz, type ChainRuleFlowLink } from "@craft-bits/core";
 
const chain: readonly ChainRuleFlowLink[] = [
  { id: "x", label: "x" },
  { id: "g", label: "g(x) = x²", derivative: "g'(x) = 2x" },
  { id: "f", label: "f(g(x)) = sin(x²)", derivative: "f'(g(x)) = cos(x²)" },
];
 
<ChainRuleFlowViz chain={chain} />

Drive autoplay through the playing prop:

<ChainRuleFlowViz chain={chain} defaultPlaying playSpeed={1200} />

Control the cursor from the outside — e.g. tie the highlighted edge to a parent step indicator:

const [edge, setEdge] = useState(chain.length - 2);
 
<ChainRuleFlowViz
  chain={chain}
  currentEdge={edge}
  onCurrentEdgeChange={setEdge}
/>

Understanding the component

  1. Edges, not steps. The cursor is currentEdge, not currentStep. Edge i is the link chain[i] → chain[i + 1]. For a chain of length 3 there are exactly 2 edges, numbered 0 and 1.
  2. Backward sweep. Autoplay starts at the last edge (closest to the output) and walks back toward the input, mirroring how gradients propagate during backpropagation. When the cursor reaches edge 0 it wraps back to the last edge.
  3. Derivative belongs to the destination link. A link's derivative labels the incoming edge — it's the local derivative that multiplies into the chain at that link. The first link has no incoming edge and so ignores its derivative.
  4. Forward + backward simultaneously. The forward composition row and the backward arc share the same highlight; only the active edge is solid + bold, the inactive ones are dashed at low alpha.
  5. Controlled and uncontrolled, twice. Both currentEdge and playing can be controlled (onCurrentEdgeChange / onPlayingChange) or left to internal state via defaultCurrentEdge / defaultPlaying.
  6. Scrubber matches the flow direction. The transport scrubber's right edge corresponds to "fresh from the output" (the start of the backward sweep) and the left edge to "all the way back at the input" — dragging right-to-left mirrors the gradient's actual travel.
  7. Reduced motion friendly. prefers-reduced-motion: reduce collapses transitions to instant and disables autoplay.

Props

PropTypeDefaultDescription
chainreadonly ChainRuleFlowLink[]Composition in forward order.
currentEdgenumberControlled edge cursor (0..N-2).
defaultCurrentEdgenumberchain.length - 2Uncontrolled initial edge.
onCurrentEdgeChange(edge: number) => voidFires on every cursor advance.
playingbooleanControlled play state.
defaultPlayingbooleanfalseUncontrolled initial play state.
onPlayingChange(playing: boolean) => voidFires on play / pause flip.
playSpeednumber900Milliseconds between backward-sweep advances.
transitionTransitionSPRINGS.smoothSpring for highlight transitions.
classNamestringMerged onto the root <div> via cn().

Accessibility

  • The figure is role="figure" with aria-label="Chain rule flow visualization".
  • An aria-live="polite" summary announces the current backward edge whenever it changes.
  • The play / pause button carries an explicit aria-label and aria-pressed.
  • The scrubber input is labelled "Backward edge cursor".
  • Animation respects prefers-reduced-motion: reduce — transitions collapse to instant and autoplay is disabled.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/viz/ChainRuleFlowViz.tsx). Reframed the lesson harness (Explore / Predict modes, narration heuristics, x slider, wiggle, deadness check on f'(g(x)) · g'(x) for f = sin, g = x²) as a general chain-as-flow primitive: an arbitrary chain of links with optional derivative labels and a backward sweep that animates the gradient travelling right-to-left across the edges, complementing ChainRuleStepper which steps through the symbolic derivation.