Forward Pass Animator

A feed-forward neural-network visualisation tuned for teaching the forward pass on its own. One layer cursor drives a left → right wavefront: the active layer's neurons light up in --cb-accent, the edges feeding into them pulse on, past layers stay tinted, future layers stay dimmed. Where BackpropFlow shows the round trip (forward + backward), this is the forward-only sibling — use it in lessons that introduce the forward pass before the chain rule.

Forward pass. Layer 1 of 4 activation highlighted.
Forward passlayer 01 / 04
0.330.390.27inputhidden 1hidden 2output
Customize
Architecture
3-4-4-2
Wavefront
0
Playback

Installation

npx shadcn@latest add https://craftbits.dev/r/forward-pass-animator.json

Usage

import { ForwardPassAnimator } from "@craft-bits/core";
 
<ForwardPassAnimator layers={[3, 4, 4, 2]} />

Pass your own activations from a real forward pass:

<ForwardPassAnimator
  layers={[3, 4, 2]}
  activations={[
    [0.1, 0.5, 0.9],
    [0.3, 0.7, 0.2, 0.8],
    [0.6, 0.4],
  ]}
/>

Drive playback from outside the component:

const [layer, setLayer] = useState(0);
 
<ForwardPassAnimator
  layers={[3, 4, 2]}
  currentLayer={layer}
  onCurrentLayerChange={setLayer}
  playing={false}
/>

Understanding the component

  1. One cursor, one wavefront. currentLayer indexes 0 … layers.length - 1. The component lights the layer at that index, the edges feeding into it, and every layer to the left of it (already-computed activations). Past the active layer everything stays dimmed.
  2. Edges are the wavefront. Active edges (those feeding the current layer) use the bold stroke and --cb-accent colour. 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.
  3. Synthesised activations when shape-only. Pass layers={[3, 4, 2]} without activations and the component renders deterministic placeholder values that trend up toward the output — the diagram never renders blank, but you should pass real values when you have them.
  4. SPRINGS.smooth on the active edge / node. Layer transitions use the smooth spring from @craft-bits/core/motion so the wavefront settles between layers rather than snapping.
  5. Reduced-motion fallback. With prefers-reduced-motion: reduce, the network renders fully lit on mount with no autoplay and no per-layer animation.
  6. Auto layout from layers alone. Node positions are derived from the layer-shape array — change the architecture and the diagram re-flows. No coordinates to maintain.

Props

PropTypeDefaultDescription
layersreadonly number[]Neuron count per layer (left → right). Required.
activationsreadonly (readonly number[])[]Forward-pass values per layer. Synthesised if omitted.
currentLayernumberControlled cursor in [0, layers.length - 1]. Pair with onCurrentLayerChange.
defaultCurrentLayernumber0Uncontrolled initial cursor.
onCurrentLayerChange(layer) => voidFires on tick and on manual scrub.
playingbooleanControlled play state. Pair with onPlayingChange.
defaultPlayingbooleantrueUncontrolled initial play state.
onPlayingChange(playing) => voidFires when play / pause flips.
playSpeednumber600Milliseconds between layer advances during autoplay.
transitionTransitionSPRINGS.smoothSpring for active-edge / node transitions.
classNamestringMerged onto the root <div> via cn().

Accessibility

  • The figure is role="figure" with aria-label="Forward pass visualization".
  • An aria-live="polite" summary announces the active layer whenever the cursor advances.
  • The play / pause button is aria-pressed; the label flips between "Play forward pass" and "Pause forward pass".
  • The scrubber is a native <input type="range"> with an explicit aria-label, so keyboard arrows nudge the cursor and screen readers narrate the value.
  • Colour is never the only signal — active-layer count and value labels are textual.
  • prefers-reduced-motion: reduce renders the network fully lit on mount and disables autoplay.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/viz/ForwardPassAnimator.tsx). The source was a single-neuron x → · M → + B widget hard-wired to a slider; this extraction generalises the concept to an arbitrary layers: number[] feed-forward network so the same component covers the full forward-pass lesson family. Architecture mirrors BackpropFlow (auto layout from layers, controlled / uncontrolled state pairs) so the two compose cleanly in side-by-side lessons.