Chain Rule Stepper
Walks through differentiating h(x) = f(g(x)) one step at a time. The canonical 4-step walkthrough is: (1) identify the outer f and inner g, (2) compute g'(x), (3) compute f'(g(x)), (4) multiply through to get h'(x) = f'(g(x)) · g'(x). Each step highlights the relevant subterm. Built for teaching the chain rule rigorously to ML students who need it for backpropagation.
Step 1 of 4.
Chain rulestep 01 / 04
Step 1
sin(x²)
Outer function f(u) = sin(u); inner function g(x) = x².
Customize
Cursor
1 / 4
Playback
Installation
npx shadcn@latest add https://craftbits.dev/r/chain-rule-stepper.jsonUsage
import { ChainRuleStepper } from "@craft-bits/core";
<ChainRuleStepper defaultCurrentStep={0} />Customise the function labels (still using the abstract 4-step walkthrough):
<ChainRuleStepper outerLabel="σ" innerLabel="w·x + b" variableLabel="x" />Provide concrete steps for a specific function — e.g. h(x) = sin(x²):
import { ChainRuleStepper, type ChainRuleStep } from "@craft-bits/core";
const steps: readonly ChainRuleStep[] = [
{
label: "Identify outer and inner",
expression: <span>sin(x²)</span>,
explanation: "Outer: sin. Inner: x².",
},
{
label: "Differentiate the inner",
expression: <span>g'(x) = 2x</span>,
},
{
label: "Differentiate the outer",
expression: <span>f'(g(x)) = cos(x²)</span>,
},
{
label: "Multiply through",
expression: <span>h'(x) = cos(x²) · 2x</span>,
},
];
<ChainRuleStepper
outerLabel="sin"
innerLabel="x²"
composedExpression={<span>sin(x²)</span>}
steps={steps}
/>Control the cursor from the outside:
const [step, setStep] = useState(0);
const [playing, setPlaying] = useState(false);
<ChainRuleStepper
currentStep={step}
onCurrentStepChange={setStep}
playing={playing}
onPlayingChange={setPlaying}
playSpeed={1500}
/>Understanding the component
- Four canonical steps by default. When
stepsis omitted, the component generates the abstract four-step walkthrough fromouterLabel/innerLabel/variableLabel: identify, differentiate inner, differentiate outer, multiply. - Custom steps for concrete examples. Pass any
ChainRuleStep[]to override. Each step carries a shortlabelfor the step indicator, anexpressionrendered in the focus card, and an optionalexplanationparagraph. - Header expression is overridable. The default header is
h(x) = f(g(x)). For concrete examples (sin(x²),e^{w·x+b}, …) passcomposedExpressionso the header doesn't render nonsense likesin(x²(x)). - Step indicator highlights the active step. Numbered pills (1..N) act as a
role="tablist"; the active one is accent-coloured. Clicking a pill jumps to that step and pauses autoplay. - Focus card morphs between steps.
AnimatePresencewithmode="popLayout"cross-fades the expression and explanation.SPRINGS.smoothfor card transitions,SPRINGS.snapfor the step-indicator scale. - Transport: prev / play / next / scrub. A range input scrubs across the steps; the play button autoplays at
playSpeed(default1200ms). Reaching the last step in autoplay wraps back to the start. - Controlled and uncontrolled, twice. Both
currentStepandplayingcan be controlled (pair withonCurrentStepChange/onPlayingChange) or left to internal state viadefaultCurrentStep/defaultPlaying. - Reduced-motion friendly.
prefers-reduced-motion: reducecollapses all transitions to instant and disables autoplay.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
outerLabel | string | "f" | Label for the outer function. |
innerLabel | string | "g" | Label for the inner function. |
variableLabel | string | "x" | Label for the input variable. |
steps | readonly ChainRuleStep[] | canonical 4-step walkthrough | Custom step list. |
composedExpression | ReactNode | abstract composition | Header override for concrete examples. |
currentStep | number | — | Controlled step index. |
defaultCurrentStep | number | 0 | Uncontrolled initial step. |
onCurrentStepChange | (step: number) => void | — | Fires on every step change. |
playing | boolean | — | Controlled play state. |
defaultPlaying | boolean | false | Uncontrolled initial play state. |
onPlayingChange | (playing: boolean) => void | — | Fires on play / pause flip. |
playSpeed | number | 1200 | Milliseconds between autoplay step advances. |
transition | Transition | SPRINGS.smooth | Spring for the expression card. |
className | string | — | Merged onto the root <div> via cn(). |
Accessibility
- The figure is
role="figure"witharia-label="Chain rule walkthrough for h(x) = f(g(x))". - An
aria-live="polite"summary announces the current step number whenever it changes. - The step indicator is a
role="tablist"ofrole="tab"buttons, each taggedaria-selectedanddata-state="active" | "inactive". - The focus card is a
role="tabpanel"linked back to its tab viaaria-controls. - Prev / next / play buttons carry explicit
aria-labels; play usesaria-pressedso screen readers track the toggle state. - The scrubber input has its own
aria-label="Step cursor". - Animation respects
prefers-reduced-motion: reduce— transitions collapse to instant and autoplay is disabled.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/math/ChainRuleStepper.tsx). Reframed the lesson primitive (which tracked nudge counts through a phase state machine ofobserve/propagating/chain/insightwith colored ripples, narration heuristics, and a Δx preset slider) into a general step-by-step walkthrough primitive: controlled / uncontrolled state pairs oncurrentStepandplaying, custom step lists via aChainRuleStep[]prop, a configurable header expression, and a setInterval-driven autoplay loop.