Freeze and Slice

A two-panel partial-derivative explainer on f(x, y) = x² + y². The left panel shows a contour plot with a fixed evaluation point. The right panel is empty until the learner clicks Freeze x or Freeze y — at which point a vertical or horizontal slice line appears on the contour, and the corresponding 1D parabolic slice shows up on the right with a tangent at the evaluation point. The tangent's slope IS the partial derivative.

At the default point (2, 1): freezing x gives the slice f(2, y) = 4 + y² with tangent slope 2y = 2 at y = 1 — that's ∂f/∂y. Freezing y gives f(x, 1) = x² + 1 with tangent slope 2x = 4 at x = 2 — that's ∂f/∂x. The ∂f/∂x slice is steeper because x = 2 is farther from the center than y = 1.

Freeze and slice — partial derivative explainer on f of x, y equals x squared plus y squared.
No variable frozen. Use Freeze x or Freeze y to see a partial derivative.

f(x, y) = x² + y² — a bowl centered at the origin. The point sits at (2, 1) where f = 5. Freeze x or y to slice the surface and reveal a partial derivative.

Customize
Evaluation point
2.0
1.0
Starting phase

Installation

npx shadcn@latest add https://craftbits.dev/r/freeze-and-slice.json

Usage

import { FreezeAndSlice } from "@craft-bits/viz/freeze-and-slice";
 
<FreezeAndSlice />

Evaluate at a different point:

<FreezeAndSlice point={{ x: 1.5, y: -0.5 }} />

Start with one variable already frozen:

<FreezeAndSlice defaultPhase="freeze-x" />

React to phase changes:

<FreezeAndSlice
  onPhaseChange={(phase) => {
    /* now showing: phase */
  }}
/>

Understanding the component

  1. The contour plot. The left panel is a symmetric window around the origin with five concentric contour circles (since f(x, y) = x² + y² = c is a circle of radius √c). A single accent-coloured dot marks the evaluation point and gently pulses in the idle state to draw the eye.
  2. The slice plot. The right panel is empty in the idle phase. Once a variable is frozen, it renders a parabolic slice f(P_x, y) or f(x, P_y) over the same variable domain, with a tangent line drawn at the evaluation point.
  3. Freezing a variable. Clicking Freeze x paints a vertical dashed line at x = P_x on the contour, the contour circles fade to dim, the slice curve and tangent fade in on the right, and the narration switches to explain ∂f/∂y. Clicking again toggles back to idle. Freeze y works symmetrically.
  4. The tangent IS the partial. The tangent's slope on the slice plot is computed from the closed-form derivative (2y or 2x) and never re-fits. That's the point of the visualization — a partial derivative is just an ordinary derivative on a slice.
  5. Visual link between panels. Where the vertical/horizontal slice line crosses each contour circle on the left, a small accent-coloured dot appears. They're the same level sets read in 1D. A faint dashed line connects the panels along the mid-height to make the relationship explicit.
  6. Phase palette. freeze-x uses the accent token, freeze-y uses the warning token so the two slices stay visually distinct. The narration background tints with the active colour so the eye lands on it after a click.
  7. Reduced motion. Under prefers-reduced-motion: reduce, slice / tangent / dot entrances skip the fade-in and the idle breathing pulse on the evaluation point disables.

Props

PropTypeDefaultDescription
point{ x: number; y: number }{ x: 2, y: 1 }Point at which the partials are evaluated and the tangent is drawn.
defaultPhaseFreezeAndSlicePhase"idle""idle", "freeze-x", or "freeze-y".
transitionTransitionSPRINGS.smoothOverride the slice / tangent entrance transition.
onPhaseChange(phase) => voidFires whenever the phase changes via the buttons.
classNamestringMerged onto the root via cn().

Accessibility

  • The plot SVG is role="img" with an aria-label summarising the current point, the frozen variable (if any), and the partial-derivative value.
  • The freeze buttons are real <button> elements with aria-pressed reflecting whether that variable is currently frozen.
  • A live region (aria-live="polite") below the buttons announces the current frozen state and the partial-derivative value whenever the phase changes.
  • The narration paragraph also has aria-live="polite" and reads as plain prose; it is the canonical explanation for each phase.
  • Colour is never the only signal — the phase is also encoded in the narration prose, the button label flip ("Freeze x" / "Unfreeze x"), and the live-region status text.
  • Motion respects prefers-reduced-motion: reduce — the slice and tangent entrances skip the fade-in, and the idle breathing pulse on the evaluation point disables.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/math/FreezeAndSlice.tsx). The source was a tightly bundled lesson component — it consumed SvgLabel and ChallengeBtn from the lesson chrome, depended on per-track lesson palette tokens, and inlined its own ad-hoc spring names. The viz extract drops the lesson chrome, remaps every colour to var(--cb-*) semantic tokens so consumer themes repaint freely, exposes the evaluation point and starting phase as props, and re-keys all entrance animations to the canonical SPRINGS.* so motion comes from the same place as every other craft-bits component.