Activation Curve Inline

Inline activation-function explorer designed to sit in prose flow. No widget chrome, no borders on the plot — just the curves, a draggable vertical probe, and a thin row of readout cards.

Plots one or more of six built-in activations (ReLU, Sigmoid, Tanh, LeakyReLU, ELU, GELU) on a shared axis with an optional dashed derivative overlay, optional dead-zone (|f′(x)| < 0.005) and saturation-zone (0.005 ≤ |f′(x)| < 0.1) washes, and a draggable probe that springs to the pointer and reads out f(x) and f′(x) per function.

Activation curve explorer for ReLU.
ReLU
f(0.0) = 0.0000
f′(0.0) = 0.0000
Customize
Functions
Overlays
Probe
0.0

Installation

npx shadcn@latest add https://craftbits.dev/r/activation-curve-inline.json

Usage

import { ActivationCurveInline } from "@craft-bits/viz/activation-curve-inline";
 
<ActivationCurveInline functions={["ReLU"]} />

Compare two activations with their derivatives:

<ActivationCurveInline functions={["ReLU", "Sigmoid"]} showDerivative />

Teach the dying-ReLU phenomenon:

<ActivationCurveInline functions={["ReLU"]} showDerivative highlightDead />

Teach sigmoid saturation:

<ActivationCurveInline
  functions={["Sigmoid", "Tanh"]}
  showDerivative
  highlightSaturation
/>

Understanding the component

  1. Six built-in activations. Each defines both f(x) and df(x) — five analytical, one (GELU) via central finite differences against the tanh approximation.
  2. Shared axis. All selected functions render on the same x ∈ [−5, 5], y ∈ [−2, 4] plot at 200 samples each, with output clipped to the visible y-domain so the curve never escapes the frame.
  3. Grid dots, not grid lines. Subtle 1px dots at integer ticks keep the plot visually quiet so the curves and probe dominate. The origin row gets brighter dots.
  4. Probe spring. A useMotionValue tracks the raw pixel-x; useSpring against SPRINGS.snap produces the visible position. Drag updates the raw value; the spring chases.
  5. Dead / saturation washes. When enabled, the component pre-scans the visible domain for the relevant gradient-magnitude band of each activation and renders a low-opacity rect over every contiguous span.
  6. Per-curve glow. Each function has its own SVG glow filter so the curve hue carries an emissive halo without bleeding between functions.
  7. Readout cards. A thin uppercase-mono label plus tabular-num values of f(x) (and f′(x) if enabled) per function. The current value transitions opacity on update so the eye registers the change.

Props

PropTypeDefaultDescription
functionsreadonly ActivationCurveInlineFnName[]One or more activations to plot.
showDerivativebooleanfalseOverlay the analytical f′(x) curve as a dashed line.
initialXnumber0Initial probe position. Clamped to [−5, 5].
highlightDeadbooleanfalseWash the SVG red wherever |f′(x)| < 0.005.
highlightSaturationbooleanfalseWash the SVG amber wherever 0.005 ≤ |f′(x)| < 0.1.
captionReactNodeCaption rendered below the readout cards.
transitionTransitionSPRINGS.snapOverride the spring used by the probe and value dots.
onXChange(x: number) => voidFires on every probe move (drag or keyboard).
classNamestringMerged onto the root via cn().

Accessibility

  • The plot SVG is role="img" with an aria-label listing the selected functions and current probe position.
  • The drag surface is role="slider" with aria-valuemin / aria-valuemax / aria-valuenow / aria-valuetext reflecting the probe.
  • Keyboard: / nudge by 0.1, Shift+← / Shift+→ nudge by 0.5, Home / End jump to the bounds.
  • Decorative shapes (grid dots, washes, dashed lines, value labels, legend) are tagged aria-hidden.
  • Colour is never the only signal — the readout cards print the numeric values in tabular monospace.
  • Motion respects prefers-reduced-motion: reduce automatically — useSpring from motion/react snaps to target instead of animating.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/viz/ActivationCurveInline.tsx). Dropped the lesson chrome (SvgLabel), remapped per-lesson palette tokens to var(--cb-*) semantic tokens so consumer themes repaint freely, swapped the project-local SPRINGS.snug for the canonical SPRINGS.snap, replaced ELU's hardcoded lesson colour with a token mix, added Home / End keyboard bounds, an onXChange callback, and a transition override prop.