Gradient Field Viz
A 2-D heatmap of every layer's gradient magnitude at every training step. Rows are layers (top = output-side, bottom = deeper). Columns are training steps (left → right). Cell intensity encodes |grad|. A vertical column outline highlights the current step; hovering or focusing a cell reveals its exact (step, layer, value) triple. Use it to show the canonical vanishing- and exploding-gradient signatures unfold over training.
Gradient field heatmap. 8 layers across 60 training steps. Current step 60 of 60.
Gradient fieldstep 60 / 60
current step 60 / 60
Customize
Field
vanishing
Display
accent
Installation
npx shadcn@latest add https://craftbits.dev/r/gradient-field-viz.jsonUsage
import { GradientFieldViz } from "@craft-bits/core";
<GradientFieldViz gradients={field} />Scrub the heatmap from a parent controller (controlled mode):
<GradientFieldViz
gradients={field}
currentStep={step}
onCurrentStepChange={setStep}
/>Show the sign of the gradient with the diverging ramp:
<GradientFieldViz gradients={signedField} colorScheme="diverging" />Understanding the component
- Cell layout. Input is
gradients: number[][]shapednumSteps × numLayers. Each rowiis a training step; each columnjinside that row is the gradient magnitude (or signed gradient, under the diverging scheme) at layerj. Rows aren't required to be the same length — shorter rows are right-padded with0so a half-finished training run still renders cleanly without throwing. - Two ramps, one job.
accent(the default) maps|value| / max(|value|)to an alpha ramp on--cb-accent.divergingkeeps the same magnitude mapping but switches the hue with the sign: negatives →--cb-info, positives →--cb-error. Both ramps share the same dynamic range so cross-scheme comparisons stay honest. - Current-step column. A vertical
motion.rectoutlined in--cb-accentfloats over the cursor column. It springs to its new x oncurrentStepchange underSPRINGS.snap; reduced-motion users get an instant snap with no spring. - Controlled+uncontrolled cursor.
currentStep(controlled) anddefaultCurrentStep(uncontrolled) mirror the Radix pattern. Uncontrolled defaults tonumSteps − 1so first paint lands on end-of-training, which is what most callers want to inspect. - Hover tooltip. Pointer-enter on a cell pops a small
L<n> · step <m> · <value>label hugging the top edge of the chart. The same triple is mirrored in an inline readout under the chart and announced througharia-live="polite"so screen-reader users hear the diagnosis. - Keyboard scrub. Focus the SVG and press
←/→to move the cursor one step at a time,Home/Endto jump to the bounds. Clicking any cell sets the cursor to that step.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
gradients | readonly (readonly number[])[] | — | numSteps × numLayers field. Non-finite values render as muted bg. |
currentStep | number | — | Controlled cursor step. Clamped to [0, numSteps − 1]. |
defaultCurrentStep | number | numSteps − 1 | Uncontrolled initial cursor. |
onCurrentStepChange | (step: number) => void | — | Fires on keyboard scrub and cell click. |
colorScheme | 'accent' | 'diverging' | 'accent' | Cell-fill ramp. |
transition | Transition | SPRINGS.snap | Spring for the column-highlight transition. |
className | string | — | Merged onto the root <div> via cn(). |
Accessibility
- The figure is
role="figure"with anaria-labelledbythat names the chart "Gradient field," and anaria-describedbythat updates whenever the cursor or the hovered cell changes. - The SVG accepts focus (
tabIndex=0) and exposes a visiblefocus-visiblering so keyboard users can find it. Arrow keys move the cursor one step at a time;Home/Endsnap to the bounds. - An
aria-live="polite"summary announces the layer / step / value of the hovered cell, or the current step when no cell is hovered — so screen-reader users hear the same readout the chart shows visually. - All decorative axis labels, tick labels, layer labels, the column-highlight
<rect>, and the floating tooltip carryaria-hiddenso they don't double-announce. prefers-reduced-motion: reducesnaps the column highlight instead of springing.- Color is never the only signal: the floating tooltip and the inline readout both spell out the value, and the cursor column is outlined as well as filled.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/GradientFieldViz.tsx). The source was a 2-D function-surface visualizer — a heatmap off(x, y)with overlaid gradient arrows and a draggable point that decomposed∇finto∂f/∂xand∂f/∂y— built as a single-purpose teaching artefact for the partial-derivatives lesson (Explore / Predict / Challenge modes, narration, bookmarks, sin·cos / saddle / bowl preset picker). The library variant reframes the slot entirely to match the Backprop sidebar's pedagogical need: a 1-D-per-layer gradient field over training steps (rows = layers, cols = steps, intensity =|grad|). The shared phrase "gradient field" is the only structural overlap; everything else is rebuilt as a generic primitive —gradients: number[][], controlled+uncontrolledcurrentStep,accent/divergingramps, keyboard scrub, hover tooltip, and anaria-livesummary. Stripped the Explore / Predict / Challenge modes, function presets, draggable point, arrow-field overlay, per-axis decomposition, bookmarks, and every Widget / ChallengeBtn / FeedbackBadge dependency.