Skip to main content
A dumbbell compares values within each category: a dot per value on the value axis, joined by a connector from the smallest to the largest. It reads the gap between groups, such as pay by sex across roles or life expectancy across two years.
The dumbbell ships as its own package, @graphysdk/geom-dumbbell, on a 0.x version line. While it is on 0.x, a minor release may change its aesthetics, style parts or look; pin a caret range (^0.1.0) to take only patches. Tell us what works and what doesn’t on Discord.

Install

It peer-depends on @graphysdk/react and nothing else. Register the plugin once with createGraphyKit, which adds kit.geom.dumbbell() and binds kit.GraphProvider to the same plugin:

Long data: one row per dot

Map the category to x, the value to y and the group to color. The geom groups the dots of each category itself, so the legend, palette, tooltip order and highlights all come from the color scale:
A dumbbell encodes position, not length, so the value axis fits the data rather than holding zero the way a bar axis does, and the gaps read at full width. A category with one dot draws the dot and no connector. With three or more dots, the connector spans the smallest to the largest and the others sit on it. Leave color unmapped and every dot takes the default geom colour, with no legend.

Wide data

When each group is its own column, reshape it to long in the spec:

Horizontal

Add kit.coord.flip(), as for a horizontal bar. The categories move to the vertical axis and the connectors lie across.

Styling

The dots are the layer’s observations and style through the kind’s own builder. The connector is a part beside them, with a builder of its own:
An entry that names no part, such as style.geom({ fill: 'navy' }), styles the dots like any other geom’s observations and never the connector. The connector takes no colour from the scale: it joins dots of different groups, so a scale colour would be arbitrary. A connector entry’s where is tested against the category’s first dot, so write it against what every dot of the category shares, such as its x.

Hover and highlight

Hovering a category emphasises its whole dumbbell. The tooltip lists every dot in legend order, with the dot nearest the cursor marked in place. A highlight matches dots. A connector is raised only when every dot it joins is: highlighting one group raises that group’s dots and no connector, and highlighting one category raises its whole dumbbell.

Data labels

dataLabels.showDataLabels prints every dot’s value beside it. Under the default position: 'auto' each label sits outward from the connector — the low dot’s away from the high one and the high one’s away from it — so the gap the chart is read from stays clear. An explicit position puts every label on the side justify names, for a chart that wants them in a row.
The label prints the dot’s y, formatted as the value axis formats it; map label to print another column instead. showStackTotals and showCategoryLabels are bar settings and a dumbbell places neither.

Not yet supported

  • The editor’s chart-type picker and the chart agent. In editable mode the dumbbell renders, hovers, selects and takes annotations on its dots, but it is authored in code.
  • Aggregation. Duplicate rows for one category and group all draw; aggregate them first with transform.aggregate().