Skip to content
microcharts
ReferenceCoreDotPlot

DotPlot

DotPlot compares a few named values as dots on one shared scale, with or without stems to zero.

encodes
dot position on a common scale
precision
high
nodes
≤ 2 per row + text (rows ≤ 7)

DotPlot places each named value as a dot on one shared scale, which is the minimum ink per comparison. Reach for it over bars when the scale doesn't start at zero: position stays readable where a truncated bar length would overstate the difference. Without stem the domain fits the data and position is the read; with stem the domain is forced through zero and the read becomes magnitude.

DotPlot
interactive · 5.24 kB · static · 2.67 kB

Install

Import & usereact/dot-plot
import { DotPlot } from "@microcharts/react/dot-plot";// team — real values under “Sample data” below<DotPlot data={team} title="Review scores" />
Sample data
const team = [  { label: "Ada", value: 96 },  { label: "Kim", value: 41 },  { label: "Sam", value: 88 },  { label: "Noor", value: 73 },  { label: "Lee", value: 60 },];
Needs package + stylesheetSet up with AI

Try it

When to use it

Use it for KPI leaderboards, named comparisons in cards, and rows where a truncated bar would overstate the difference. Avoid it above 7 rows; for a time series use Sparkline.

Sizing

Variants

stems
values + highlight

Edge cases

no data
single category
null keeps its row

An empty series has nothing to compare, so no dots draw and the accessible name reads "No data." A single category still renders normally, one dot and one label, with the summary's "category"/"categories" wording matching the count ("1 category. Highest Only 42, lowest Only 42."). A null value draws no dot and no label for its row, but the row still occupies its slot in the vertical rhythm, so the real values around it keep the spacing they'd have in a fully populated set. It is also excluded from the category count in the summary.

Two dots that would land on the same spot on adjacent rows de-overlap by half a unit. Labels truncate by character count and drop entirely once rows get dense. Both are arithmetic on the layout; nothing is measured from the rendered text.

Four homes

Accessibility

The accessible name carries the count and the extremes: "3 categories. Highest Ada 96, lowest Kim 41." The interactive entry roves rows and announces each one with its rank ("Ada: 96 — 1st of 3.").

The interactive entry follows the shared interaction contract: arrow keys rove between units on both axes, Home and End jump to the ends, and a click, tap, Enter or Space selects a unit — pinning its readout so it survives blur, until you select it again or press Escape. On touch, a tap pins and a drag scrubs.

Props

PropTypeNotes
data*{ label; value }[]Named values.
stembooleanHairline from zero — flips to a magnitude read (zero-anchored domain forced).
highlightnumber | stringAccent one category.
label"value" | "none"Value text beside each dot (drops out under 8-unit rows).
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