Skip to content
microcharts
ReferenceExpressiveThermometer

Thermometer

Thermometer fills a ticked tube from the bottom of a stated domain, with an optional target line.

encodes
column extent on a ticked calibrated scale
precision
high
nodes
≤ 6
collection
Expressive
Source

Thermometer fills a ticked tube from the bottom of its range, and the ticks calibrate the read, which is what buys the precision. The fill always anchors at the bottom of the domain: never re-zeroed, never log. An optional target line crosses the tube to mark the goal. domain defaults to [0, 100] because a calibrated instrument needs a stated range, and auto-fitting would move the scale under the reader. The bulb is instrument chrome and always full; it is not data, so its area means nothing.

Thermometer
interactive · 4.15 kB · static · 2.58 kB

Install

Import & usereact/thermometer
import { Thermometer } from "@microcharts/react/thermometer";<Thermometer value={72} target={80} title="Fundraiser" />
Needs package + stylesheetSet up with AI

Try it

Live playground
onSelect
idle
  1. hover · click · Enter…

Tap to raise the level — the fill glides to its new reading (reduced-motion → it jumps), hover reveals the exact value, and each change is announced against the calibrated scale and target.

value · 72
target · 80
orientation
bulb
readout chip
animate
import { Thermometer } from "@microcharts/react/thermometer/interactive";<Thermometer  value={72}  target={80}/>

When to use it

Use it for a fundraising or goal-progress read, a capacity or utilization gauge in a cell, or any value against a stated range. Trends belong in Sparkline and proportions of a whole in SegmentedBar; it reads a single value, so many series need a different chart.

Sizing

horizontal, in a table cell
explicit calibration ticks

Variants

Vertical with the bulb is the default, since a filling tube reads as progress toward the goal. orientation="horizontal" fits a table cell where a vertical tube cannot, and bulb={false} drops the reservoir where the instrument metaphor is too much for the context.

horizontal cell + explicit ticks

Edge cases

out-of-domain clamps the fill; the accessible name keeps the true value
value at the domain floor
locale

A value beyond the domain clamps the fill, and the accessible name still reports the true number, so the reading is never silently clipped. The accessible summary's value, domain, and target all go through the same locale-aware formatter, so "7,234" becomes "7.234" in German grouping.

Four homes

In a sentence

Fundraiser progress — $72K raised, $8K from goal.

In a table cell
Annual$72K
Q4$42K
Emergency$18K
In a KPI card
Fundraiser
$72Kof $80K goal
In a tab header
AnnualQ4Emergency

Preview uses the public chart API only. When an interactive twin exists, it swaps in with the same props and no entrance motion - code samples stay on the static import. Placement recipes: Composition, Sizing.

Accessibility

The accessible name states the value on its scale, "62 on a 0–100 scale.", and appends the goal when a target is set. The interactive entry reveals the exact value on hover or focus, glides the fill to its new level with a reduced-motion-gated transition, and announces each change through a polite live region.

This chart is a single unit, so there is nothing to rove between: a click, tap, Enter or Space selects it and fires onSelect, and no selection stays pinned. That is the scalar half of the shared interaction contract. Hover or focus also reveals the reading itself in a floating chip, for the sizes and label modes where the mark does not print it; readout={false} drops the chip and keeps everything else.

Props

PropTypeNotes
value*numberThe reading.
targetnumberA goal tick across the tube.
domain[number, number]The calibrated range (default [0, 100]).
ticksnumber | number[]Tick count or explicit values.
orientation"vertical" | "horizontal"Horizontal fits table cells.
bulbbooleanDraw the reservoir bulb (default true).
fontSizenumberType size of the tick and value numerals, in viewBox units (default 8).
animatebooleaninteractiveOpt-in entrance motion when the chart mounts client-side — add import "@microcharts/react/motion" once. Inert on the server, on hydrated server HTML, and under prefers-reduced-motion.

Plus the shared grammar — data, domain, color, title, summary, format — and the layout props (width, height, className, style) that every chart accepts. Interactive entries also share animate and live, and — wherever a chart has more than one navigable unit — onActive, onSelect, selectedIndex and defaultSelectedIndex; and — wherever the chart shows a hover value — readout. See the shared grammar.

Related charts