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.
Install
import { Dumbbell } from "@microcharts/react/dumbbell";<Dumbbell data={[{ from: 62000, to: 84000 }]} title="Band move" />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
Edge cases
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
| Prop | Type | Notes |
|---|---|---|
| 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). |
| highlight | number | string | Accent one row. |
| animate | boolean | interactiveOpt-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.