Power Rule Builder
Click-to-differentiate walkthrough of the power rule for monomials. The exponent of xⁿ drops down to become the coefficient while a new n − 1 fades in at the superscript, and the assembled derivative nxⁿ⁻¹ settles into a result strip beneath the monomial.
The component cycles through a six-step example bank by default (x⁵, x³, x⁷, x², x¹, x⁰) including the textbook special cases. Advance it with the built-in action button, or drive phase / exampleIndex from a parent to embed it inside a larger lesson stepper.
Click d/dx to differentiate x⁵. Watch what happens to the exponent — it has two jobs to do simultaneously.
Installation
npx shadcn@latest add https://craftbits.dev/r/power-rule-builder.jsonUsage
import { PowerRuleBuilder } from "@craft-bits/viz/power-rule-builder";
<PowerRuleBuilder />Drive the walkthrough from a parent:
const [phase, setPhase] = useState<PowerRuleBuilderPhase>("ready");
const [index, setIndex] = useState(0);
<PowerRuleBuilder
phase={phase}
onPhaseChange={setPhase}
exampleIndex={index}
onExampleIndexChange={setIndex}
/>Bring your own example bank:
<PowerRuleBuilder
examples={[
{ n: 4, resultLabel: "4x³", readyText: "...", resultText: "..." },
{ n: 2, resultLabel: "2x", readyText: "...", resultText: "..." },
]}
/>Render a custom action button instead of the built-in one:
<PowerRuleBuilder
hideAction
renderAction={({ label, disabled, onClick }) => (
<MyButton onClick={onClick} disabled={disabled}>{label}</MyButton>
)}
/>Hide the narration when embedding inside an article that already explains the rule:
<PowerRuleBuilder hideNarration />Understanding the component
- Two simultaneous transformations. The power rule
d/dx xⁿ = nxⁿ⁻¹does two things at once — multiplies by the exponent, and decrements it. The component splits these into two co-running animations so the learner sees both jobs happen together. - Exponent drops on a bouncy arc. On click, the exponent text node animates
(x, y, font-size)from the superscript position down to the coefficient slot onSPRINGS.bouncy. A glow trail (stdDeviation=6Gaussian blur) tracks it and pulses on arrival. - New exponent cross-fades in. A pre-rendered
n−1ghost (warning-tone) sits invisible at the superscript and fades in onSPRINGS.snap~120 ms after the drop begins — late enough that the eye reads them as separate events, early enough that they feel co-ordinated. - The "x" shifts to make room. For typical cases the base italic
xslides right 4 px onSPRINGS.smoothso the coefficient has breathing room. Forn = 0thexinstead fades to 20 % opacity since the derivative collapses to a plain0. - Result strip assembles last. A dashed connector, a success-tinted background, the canonical rule annotation, and the assembled derivative string (
5x⁴,2x,1,0, …) all fade in together, then the strip flashes a brief success pulse to mark commit. - Special cases handled inline.
x¹→1·x⁰ = 1(exponent zero shown dimmed);x⁰→0·x⁻¹ = 0(coefficient zero shown dimmed, x fades). - Reduced motion. Under
prefers-reduced-motion: reduce, every spring is replaced by an immediate attribute set — the end-state of each phase still renders, but no motion plays.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
examples | readonly PowerRuleBuilderExample[] | six-step default bank | Override the worked example sequence. |
exampleIndex | number | — | Controlled index of the current example. |
defaultExampleIndex | number | 0 | Initial example index for the uncontrolled API. |
onExampleIndexChange | (next) => void | — | Fired when the component advances to the next example. |
phase | "ready" | "animating" | "result" | — | Controlled phase. Pair with onPhaseChange. |
defaultPhase | "ready" | "animating" | "result" | "ready" | Initial phase for the uncontrolled API. |
onPhaseChange | (next) => void | — | Fires after the component commits to the next phase. |
transition | Transition | SPRINGS.bouncy | Override the spring used for the exponent drop. |
actionLabels | { ready?, animating?, next?, startOver? } | — | Override action-button labels. |
hideNarration | boolean | false | Hide the narration paragraph. |
hideAction | boolean | false | Hide the built-in action button. |
hideCounter | boolean | false | Hide the "1 / 6" counter in the SVG header. |
renderAction | ({ phase, label, disabled, onClick }) => ReactNode | — | Render slot for a custom action button. |
className | string | — | Merged onto the root via cn(). |
Accessibility
- The root carries
aria-labelledbypointing to a hidden<span>summary ("Power rule builder. Phase: result. Showing x to the 5. Result: 5x⁴."), so screen readers hear the current narrative state without parsing the SVG. - The SVG itself is
role="img"with the samearia-label, so consumers who slot the SVG into another tree still surface a readable name. - An
aria-live="assertive"region under the SVG announces each completed derivative ("Derivative of x to the 5 is 5x⁴...") so non-sighted users hear when the result lands. - The action button is a real
<button type="button">with:focus-visibleoutline, adisabledstate during animation, and standard keyboard activation. - Status is never colour-only — every phase emits both an aria-live announcement and a visible label / derivative; the accent / warning / success tones are reinforced by position and copy.
- Motion respects
prefers-reduced-motion: reduce— every spring collapses to an immediate attribute set, including the drop, glow pulse, ghost fade-in, x-letter shift, and success flash.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/math/PowerRuleBuilder.tsx). The library extract drops the project-specificSvgLabelandChallengeBtnchrome in favour of plain<text>and acn()-styled<button>, swaps the per-tone--color-accent-*/--color-warn-*/--color-success-*palette for the canonical--cb-accent/--cb-warning/--cb-successtoken vars, replaces the inlineSPRINGS.gentlereference withSPRINGS.bouncy/SPRINGS.snap/SPRINGS.smooth, generalises the bundledEXAMPLESconstant into anexamplesprop, and adds a controlledphase/exampleIndexAPI plusrenderActionslot so consumers can drive the walkthrough from a parent stepper, a keyboard, or a custom button.