Skip to content
microcharts
ReferenceCoreDumbbell

Dumbbell

React dumbbell chart — before/after or A/B pairs as dots linked on one scale. Tiny accessible SVG microchart; RSC-safe static or /interactive.

Dumbbell answers "where did each row start and end?". The hollow dot is before, the filled dot is after — direction is shape-coded, so it never relies on color alone. With positive the connector takes the valence token by direction.

Dumbbell
interactive · 5.61 kB · static · 3.04 kB

Install

Import & usereact/dumbbell
import { Dumbbell } from "@microcharts/react/dumbbell";<Dumbbell data={[{ from: 62000, to: 84000 }]} title="Band move" />
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — salary bands, before/after per table row, ranges.
  • Avoid for — many categories where crossings matter (Slope) or the path between (Sparkline).

Sizing

Variants

valence
values

Edge cases

from === to — a single dot, honestly

When a row's from equals its to, the connector is dropped and only one filled dot is drawn — never a hollow-and-filled pair sitting on top of each other pretending to be two points. The summary says "No change at 55." for a single row.

Four homes

Why this default

Hollow → filled reads as before → after without a legend, and renders identically whichever way the data runs — direction comes from the values, not the array order. For ranges (min→max, confidence spans) the docs require dropping positive: a range has no valence, and coloring it green or red would invent one.

Accessibility

Single row: "From 40 to 60, up 50%."; a degenerate pair says "No change at 55."; multi-row leads with the largest change ("2 rows. Largest change Paris, up 17%."). The interactive entry roves rows with ↑/↓ (←/→ do the same), announcing each row's own pair — "From 52 to 61, up 17%."

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?; from; to }[]Start/end pairs.
positive"up" | "down"Direction valence for CHANGES; drop it for ranges (no valence).
label"value" | "none"From/to values outside the dots (drop when the span is tight).
highlightnumber | stringAccent one row.
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