Uncertainty Meter

A horizontal axis with a single dot at the point estimate and fading bands at ±1σ, ±2σ, and ±3σ. The standard rendering for a value with calibrated uncertainty — Bayesian posteriors, ensemble predictions, calibrated regression output.

Accuracy0.720 ± 0.080
Customize
Value
0.72
0.080
Display
±2σ
accent

Installation

npx shadcn@latest add https://craftbits.dev/r/uncertainty-meter.json

Usage

import { UncertaintyMeter } from "@craft-bits/core";
 
<UncertaintyMeter value={0.72} stddev={0.08} label="Accuracy" />

Set sigmaLevels={3} to draw the faintest ±3σ band as well, or pin the axis with range:

<UncertaintyMeter value={50} stddev={5} range={[0, 100]} unit="ms" />

Understanding the component

  1. Two motion-values, four transforms. A useMotionValue holds the current value, another the current stddev. Per-band x / width are derived from these via useTransform, so React never re-renders during the spring — every band, the dot, and both whisker ticks track the same two drivers in sync.
  2. Bands fade out with distance. The ±1σ band paints at 42% alpha, ±2σ at 22%, ±3σ at 10%. The same tone color fills all three layers, so the visual reads as a single Gaussian-tinted error bar rather than three discrete rectangles. Outer-to-inner z-order means the ±1σ band stays crisp on top.
  3. Auto-fit range. When range is omitted, the axis spans roughly ±(sigmaLevels + 0.5)σ around the value so the widest band always sits inside the plot with a small breathing margin. The numeric readout's decimal precision is picked from the resolved span.
  4. Springs. Value uses SPRINGS.smooth (caller can override via the transition prop) — it reads as the model's belief drifting. Stddev uses SPRINGS.snap — it reads as a discrete state change (the model just learned how uncertain it is).
  5. Reduced motion. When prefers-reduced-motion: reduce is set, both motion-values snap to their targets with no spring, regardless of transition.

Props

PropTypeDefaultDescription
valuenumberPoint estimate.
stddevnumberOne standard deviation. Clamped to >= 0.
range[number, number]auto-fitAxis bounds. Auto-fits to roughly ±(sigmaLevels + 0.5)σ when omitted.
sigmaLevels1 | 2 | 32How many sigma bands to draw.
labelstringOptional label rendered to the left of the readout.
unitstringOptional unit suffix appended to the readout.
tone'default' | 'accent' | 'success' | 'warning''accent'Semantic color for bands, dot, and readout.
transitionTransitionSPRINGS.smoothSpring transition for value updates.
classNamestringMerged onto the rendered <div>.

Accessibility

  • Renders with role="figure" and an aria-label summarizing the value, one-sigma uncertainty, and unit — e.g. "Accuracy: 0.72 plus or minus 0.08 (one sigma)."
  • When label is provided, the rendered label element gets an id and becomes the figure's aria-labelledby target, so screen readers announce the label too.
  • The SVG is marked aria-hidden="true" — the figure's label fully describes the data, and the SVG carries no information not in the readout.
  • Reduced motion: both value and stddev springs collapse to instant snaps when prefers-reduced-motion: reduce is set.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/nn/UncertaintyMeter.tsx).
  • The source primitive renders an interactive entropy gauge for a 3-class distribution; this library version is the simpler, generic "point estimate with error bar" pattern.