Confidence Meter

Purpose-built readout for a classifier's class-probability output. The bars variant lays out the top K classes as horizontal bars with an other bucket folding the remaining mass; the gauge variant compresses the top class into a single arc gauge for compact embeds. Common UI for image / text classifiers, LLM token-probability tooltips, and uncertainty-quantification panels.

Top class: cat, confidence 72%.
Top class: cat, confidence 72%.
cat72%
dog18%
fox6.0%
raccoon3.0%
hamster1.0%
Customize
Layout
bars
5
Display

Installation

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

Usage

import { ConfidenceMeter } from "@craft-bits/core";
 
<ConfidenceMeter
  classes={[
    { label: "cat", probability: 0.72 },
    { label: "dog", probability: 0.18 },
    { label: "fox", probability: 0.06 },
    { label: "raccoon", probability: 0.03 },
    { label: "hamster", probability: 0.01 },
  ]}
/>

Trim to the top 3 — the remaining mass folds into an italicised other row:

<ConfidenceMeter classes={predictions} topK={3} />

Compact gauge variant for sidebars / inline tooltips:

<ConfidenceMeter classes={predictions} variant="gauge" />

Understanding the component

  1. Sort, trim, renormalise. The input list is sorted descending, clipped to topK, and the visible mass is renormalised so the bars sum to 100% even when the caller passes a truncated distribution. Negative or non-finite entries are clamped to zero.
  2. Top-K with an other bucket. When the input has more than topK classes, the remaining tail collapses into a single italicised other row whose probability is the sum of the dropped entries. Pass topK as Infinity to disable the cutoff.
  3. Argmax highlight. The top row paints with the accent color; tail rows render with the muted-foreground colour and opacity that fades by rank, capped so the last row never disappears.
  4. Bar width driven by a motion value. Each row owns a motion value holding the bar width as a percentage. On every prop change a spring drives the width toward the new value — React never re-renders on each frame; the spring drives the DOM directly.
  5. Gauge variant. When variant is gauge, only the top class renders — as a circle with a spring-animated stroke-dashoffset. The percentage and label sit in the middle.
  6. Reduced motion. When prefers-reduced-motion: reduce is set, bar widths and the gauge stroke snap to their targets with no spring.

Props

PropTypeDefaultDescription
classes{ label: string; probability: number }[]The model's class distribution. Negative entries are clamped to 0; renormalised against the visible mass.
topKnumber5Show the top K classes; remaining mass collapses into an other row. Pass Infinity to disable.
variant'bars' | 'gauge''bars'Layout style.
showPercentagesbooleantrueRender the percentage readouts.
transitionTransitionSPRINGS.smoothSpring for bar / gauge transitions.
classNamestringMerged onto the root <div> via cn().

Accessibility

  • The component is wrapped in role="figure" with an aria-labelledby heading that reads the top class and its confidence ("Top class: cat, confidence 72%.").
  • A visually hidden aria-live="polite" region announces updates as the distribution changes — useful for live-inference displays.
  • The bars and gauge are decorative (aria-hidden); screen-reader users read the headline summary instead of percentages per bar.
  • prefers-reduced-motion: reduce snaps bar widths and the gauge stroke to their targets with no spring.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/nn/ConfidenceMeter.tsx). The source was a cross-entropy / surprise-meter teaching widget (drag a confidence slider, watch -log(p) rocket up). The library extract redirects the same name to the canonical use of the term — a classifier-output readout — and adds the top-K-with-other bucket and a gauge variant.