Transformer Block Viz
A stage-by-stage visualisation of the canonical transformer block: LayerNorm → MultiHead Attention → Add → LayerNorm → Feed-Forward → Add, with two curved residual bypass lines drawn alongside. A single cursor walks through the six stages; whichever residual currently spans the cursor brightens to full accent.
Current stage: LayerNorm. Step 1 of 6.
Transformer blockstep 01 / 06
- LayerNormNormalize input
- MultiHead AttentionTokens attend to tokens
- AddResidual + attention
- LayerNormNormalize again
- Feed-ForwardPer-token MLP
- AddResidual + FFN
Customize
Cursor
0
Layout
vertical
Playback
Installation
npx shadcn@latest add https://craftbits.dev/r/transformer-block-viz.jsonUsage
import { TransformerBlockViz } from "@craft-bits/core";
<TransformerBlockViz />Override stages to teach a post-norm block or any custom architecture:
<TransformerBlockViz
stages={[
{ id: "mha", label: "MultiHead Attention" },
{ id: "add1", label: "Add" },
{ id: "ln1", label: "LayerNorm" },
{ id: "ffn", label: "Feed-Forward" },
{ id: "add2", label: "Add" },
{ id: "ln2", label: "LayerNorm" },
]}
residuals={[
{ from: 0, to: 1 },
{ from: 2, to: 4 },
]}
/>Drive playback from outside the component:
const [step, setStep] = useState(0);
<TransformerBlockViz
currentStage={step}
onCurrentStageChange={setStep}
playing={false}
/>Understanding the component
- One cursor through the whole block. A single
currentStageindex drives the active highlight, the past / future styling, and which residual bypass is "lit" — there is no per-stage state machine. - Stages are cards; edges are arrows. Each stage renders as a bordered card with a step-number badge, label, and optional description. Edges between adjacent stages share a rail and an arrow-head glyph that points down (vertical) or right (horizontal).
- Residuals are curved bypasses. Each entry in
residualsis drawn as a cubic Bézier from the centre offromto the centre ofto, bowing outward along the residual side. Any residual that currently spans the cursor brightens to full accent. SPRINGS.smoothfor the stage cursor. The active card scales to1.02and brightens via a smooth spring from@craft-bits/core/motion.- Reduced-motion fallback. With
prefers-reduced-motion: reduce, the block renders fully lit on mount, autoplay pauses, and residual opacity transitions collapse to an instant swap. - Two orientations, same component.
vertical(default — transformers are usually drawn top-to-bottom) andhorizontal.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
stages | readonly TransformerBlockStage[] | LayerNorm → MHA → Add → LayerNorm → FFN → Add | Block stages in order. |
currentStage | number | — | Controlled active index. Pair with onCurrentStageChange. |
defaultCurrentStage | number | 0 | Uncontrolled initial active stage. |
onCurrentStageChange | (stage) => void | — | Fires on autoplay tick and manual scrub. |
playing | boolean | — | Controlled play state. Pair with onPlayingChange. |
defaultPlaying | boolean | true | Uncontrolled initial play state. |
onPlayingChange | (playing) => void | — | Fires when play / pause flips. |
playSpeed | number | 1500 | Milliseconds between stage advances. |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout direction. |
residuals | readonly TransformerBlockResidual[] | two canonical skips | Curved bypass connections. Pass [] to suppress. |
showResiduals | boolean | true | Render residual bypass lines at all. |
transition | Transition | SPRINGS.smooth | Spring for the stage cursor and residual opacity. |
className | string | — | Merged onto the root via cn(). |
Accessibility
- The root is
role="figure"witharia-labelledbypointing at the "Transformer block" heading andaria-describedbyat a visually-hiddenaria-live="polite"summary. - The summary announces the current stage and step counter whenever the cursor advances.
- Stages are rendered in a semantic
<ol>witharia-current="step"on the active card. - The play / pause button uses
aria-pressed; the label flips between "Play block" and "Pause block". - The scrubber is a native
<input type="range">with anaria-labelso keyboard arrows nudge the cursor and screen readers narrate the value. - Color is never the only signal — stage labels, descriptions, step-number badges, and the step counter are all textual.
prefers-reduced-motion: reducerenders the block fully lit on mount, suppresses cursor / residual transitions, and disables autoplay.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/TransformerBlockViz.tsx). Stripped the explore / predict / challenge mode strips, the pre-norm vs post-norm toggle, the Widget chrome with history-undo and bookmarks, the cell-tensor colour swatches, and the question-and-answer flow. Generalised to an arbitrarystages: TransformerBlockStage[]array with optionalresiduals, controlled / uncontrolled state pairs, and a horizontal layout option.