DotPlot
StableShows a best guess and how sure it is, with a caption that explains the marks.
Also known as scatter, strip plot, dot chart
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Happy customers, with a range
Dots show the share of happy customers. Lines show the range we are 95% sure it falls in. 200 customers per shop.
<div className="w-full">
<DotPlot
caption="Dots show the share of happy customers. Lines show the range we are 95% sure it falls in. 200 customers per shop."
measure="Happy customers"
intervalLabel="95% range"
data={[
{ label: "North shop", estimate: 0.925, low: 0.881, high: 0.954, n: 200 },
{ label: "East shop", estimate: 0.87, low: 0.82, high: 0.91, n: 200 },
{ label: "West shop", estimate: 0.81, low: 0.75, high: 0.86, n: 200 },
]}
formatValue={(n) => Math.round(n * 1000) / 10 + "%"}
unit="percent"
ariaLabel="Happy customers by shop"
/>
</div>The caption says what is measured, how sure we are and how many customers. The text column gives the numbers.
When to use it
Shows a best guess and the range it likely falls in, one row per result. A caption says what the dot and line mean, because a bare range line means little to most readers.
Made of: Caption · Number scale · Row names · Range line with end caps · Best-guess dot · Numbers in text · Reference line (optional)
Do and avoid
Dot is the best guess. Line is the likely range.
Scores
Do
- Write the caption so a reader can say what the line means, how sure it is and how many people are behind it.
- Show group sizes when groups are small or differ between rows.
- Print the numbers as text, so no one has to read them off the scale.
- When the question is how two things differ, show that difference directly.
Avoid
- Don't leave the range line unexplained. A bare line means nothing.
- Don't treat overlapping lines as proof that two results are the same. They are not.
- Don't show scores with no range and no group size. At least show how many were asked.
- Don't cut a bar chart to fit a range. This chart marks positions, not bar lengths, so its scale can start above zero.
On a phone
- The chart measures its container and redraws at that width. Long row labels are shortened with an ellipsis to fit.
- Touch a row to show the tooltip. Vertical swipes still scroll the page, and the tooltip stays until you tap elsewhere.
- The caption above the chart wraps, so write it in plain words.
Seen in products
- Hofman, Goldstein and Hullman find that interval displays can mislead about effect size, and the research brief notes that overlapping intervals do not reliably mean no difference.
- A clinician study found that quantile dot plots reduced interpretation errors.
- Wilke's visualization text notes that distributions show full variability.
- The guidance is to label what error bars mean, naming the quantity and the level, for example 95% confidence intervals.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| datarequired | DotDatum[] | none | One row per estimate: label, estimate, low, high and an optional n. |
| captionrequired | string | none | Says what the dot and line mean, with the interval level and sample size. Rendered above the chart. |
| showN | boolean | none | Prints n beside each row. Use it for small samples. |
| measure | string | "Estimate" | Name of the estimate in announcements and the tooltip. |
| intervalLabel | string | "interval" | Names the interval, for example 95% confidence interval. |
| formatValue | (n: number) => string | formatNumber | Formats the axis, text column and tooltip. |
| unit | string | "" | Unit word read after each value by screen readers. |
| domain | [number, number] | none | Fixed value axis. Defaults to the interval extent. The axis does not need to start at zero. |
| reference | { value: number; label: string } | none | A named reference line, such as the current model. |
| ariaLabel | string | "Dot plot" | Name for the chart region. |
| className | string | none | Extra classes on the wrapper. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one DotPlot switches all of this from its properties panel, across 2 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Show n | showN | On or off |
| Caption | caption | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- hover
- Moving the pointer over a row shades it and shows a tooltip with the estimate, interval and sample size.
- focus
- The chart can be focused with the keyboard; arrow keys step through rows and Escape clears the tooltip.
- reference line
- Pass reference to draw a labelled vertical line at that value.
- narrow
- Below about 440px wide, the value text beside each row is hidden, though the tooltip still shows it.
- sample size
- Pass showN to print each row's sample size when the data has n.
Tokens
Change one of these and every part that uses it follows.
--chart-1--chart-grid--chart-axis--surface--surface-hover--fg--fg-muted--radius-overlay
Built in
- The caption is shown above the chart and is also part of the chart's name for screen readers.
- You can tab to the chart. Arrow keys move between rows, and Home and End jump to the first and last.
- Each row is read out as measure, row, value and unit, then the range and group size.
- The range line has end caps, and the dot has a ring that keeps it clear.
What you need to do
- Write a caption that says what the dot and line mean and how many people are behind them. Screen readers hear it as part of the chart's name.
- Set measure, intervalLabel and unit, so each row is read in full.
- Put it in a ChartFrame with a table. The numbers beside each row are dropped when the chart is narrow.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide