Derivative Explorer
A curve sits on a coordinate plane. A draggable marker rides the curve and trails its tangent line, whose slope is read live from the analytical derivative f'(x). An optional dashed secant overlay connects (x, f(x)) to (x + Δx, f(x + Δx)) — as Δx shrinks, the secant converges on the tangent, putting the limit definition of the derivative in motion.
Derivative explorer for y = x².
Slope2.00at x = 1.00
y = x². x = 1.00, slope f'(x) = 2.00.Secant line
Customize
Curve
x²
Position
1.00
Secant
0.50
Installation
npx shadcn@latest add https://craftbits.dev/r/derivative-explorer.jsonUsage
Uncontrolled — the component owns curve, x, secant, and Δx:
import { DerivativeExplorer } from "@craft-bits/viz/derivative-explorer";
<DerivativeExplorer />Start on the cubic with the secant on:
<DerivativeExplorer
defaultActiveCurve="x³"
defaultShowSecant
defaultDeltaX={0.8}
/>Controlled — let a parent stage own the state:
const [x, setX] = useState(1);
const [curve, setCurve] = useState<"x²" | "x³" | "sin(x)">("x²");
<DerivativeExplorer
activeCurve={curve}
onActiveCurveChange={setCurve}
x={x}
onXChange={setX}
/>Hide the chrome (curve picker + secant controls) when the chart is embedded inside a larger composition:
<DerivativeExplorer hideCurvePicker hideSecantControls />Understanding the component
- The plot. A
520 × 380SVG rendersx ∈ [−3, 3],y ∈ [−2, 9]with a faint grid and axis labels. The curve is sampled at 201 points and resamples whenever the active curve flips. - The marker. A glowing accent dot rides the curve at
(x, f(x)). Its position springs viaSPRINGS.snapso drag feels crisp and arrow-key nudges land with a quick, contained settle. - Tangent line. Drawn through
(x, f(x))with slopef'(x)clipped to the visible x-domain. It recolours green when the slope is positive, amber when negative, neutral at zero — sign before number. - Secant overlay. Toggling secant on draws a dashed warning-coloured line from
(x, f(x))to(x + Δx, f(x + Δx)). Shrinking Δx makes the secant converge on the tangent; the readout shows both slopes side by side. - Slope readout. A pill below the chart prints the live slope in tabular-num mono, recolouring with the tangent. When the secant is on, it also prints the secant slope for comparison.
- Curve picker. A
radiogroupof three chips fory = x²,y = x³,y = sin(x). Picking a curve preserves x. - Controlled + uncontrolled, four times.
activeCurve,x,showSecant, anddeltaXeach accept a controlled value (with a matchingonChange) or adefault…uncontrolled initialiser.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
activeCurve | "x²" | "x³" | "sin(x)" | — | Controlled active curve. |
defaultActiveCurve | "x²" | "x³" | "sin(x)" | "x²" | Uncontrolled initial curve. |
onActiveCurveChange | (c) => void | — | Fires when the curve changes. |
x | number | — | Controlled x position (clamped to [-3, 3]). |
defaultX | number | 1 | Uncontrolled initial x. |
onXChange | (x) => void | — | Fires on every drag / keyboard nudge. |
showSecant | boolean | — | Controlled secant flag. |
defaultShowSecant | boolean | false | Uncontrolled initial secant flag. |
onShowSecantChange | (show) => void | — | Fires when the toggle flips. |
deltaX | number | — | Controlled Δx (clamped to (0, 1]). |
defaultDeltaX | number | 0.5 | Uncontrolled initial Δx. |
onDeltaXChange | (Δx) => void | — | Fires when Δx changes. |
hideCurvePicker | boolean | false | Hide the curve chips. |
hideSecantControls | boolean | false | Hide the secant toggle + Δx slider row. |
transition | Transition | SPRINGS.snap | Spring for the marker + slope readout. |
className | string | — | Merged onto the root <div> via cn(). |
Accessibility
- The SVG is
role="img"with anaria-labelsummarising curve, x, and slope. - The drag handle is
role="slider"with full keyboard support:←/→nudge0.1,Shift+←/Shift+→nudge0.5,HomeandEndjump to the domain bounds. - An
aria-live="polite"summary mirrors the visible slope (and the secant slope when active) so screen-reader users get the same readout. - The curve picker is a
role="radiogroup"of threerole="radio"chips withdata-state="on" | "off". - The secant toggle is
aria-pressedwithdata-state="on" | "off". - Colour is never the only signal — slope is announced numerically in the live region.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/DerivativeExplorer.tsx). The source bundled the chart with aWidgetlesson chrome, a three-mode strip (Explore / Predict / Challenge), prediction inputs with feedback badges, target-slope mini-challenges, bookmark presets, and an undo / redo history — none of which generalise outside the lesson. The viz extract keeps the underlying interactive primitive (curve picker, draggable marker, tangent, optional secant), drops the lesson scaffolding, swaps the project-specificSvgLabel/ChallengeBtn/LabeledSliderfor raw<text>+ token-styled chips + a native<input type="range">, remaps the colour palette from--color-accent-500/--color-ink-*/--color-warn-500to our--cb-accent/--cb-fg-muted/--cb-warningsemantic tokens, and re-keys every spring toSPRINGS.snap.