Skip to content
microcharts
ReferenceCorePairedBars

PairedBars

PairedBars sets a value against its reference, category by category, on one zero-anchored domain.

encodes
adjacent bar lengths, zero-anchored
precision
high
nodes
2 per pair (pairs ≤ 5)

East came in at 940 against a plan of 1,200, West a little over its own: PairedBars draws each value beside its reference, category by category. Both bars in a pair share one zero-anchored domain, so their lengths are always comparable. The reference is muted by two structural cues, opacity and width, never color alone.

PairedBars
interactive · 5.51 kB · static · 2.96 kB

Install

Import & usereact/paired-bars
import { PairedBars } from "@microcharts/react/paired-bars";// regions — real values under “Sample data” below<PairedBars data={regions} title="Actual vs plan" />
Sample data
const regions = [  { label: "East", value: 940, ref: 1200 },  { label: "West", value: 410, ref: 400 },  { label: "South", value: 620, ref: 600 },  { label: "North", value: 120, ref: 300 },];
Needs package + stylesheetSet up with AI

Try it

When to use it

Use it for budget vs actual per region and target vs result rows. For data without a reference series use MiniBar, and keep it to 5 pairs or fewer.

Sizing

Variants

overlay

Grouped is the default because overlapping bars hide small overshoots. Reach for mode="overlay" when the cell is too tight for two bars per pair.

valence
locale

The gap named in the summary follows format/locale — 12000 reads "12.000" under de-DE rather than the English "12,000".

Edge cases

missing reference
single pair

A pair whose ref is null draws its value bar alone, with no ghost and no zero-width placeholder, and the interactive entry announces it as "East: 940, no reference." A chart where every reference is missing dev-warns and points you to MiniBar. Past 5 pairs the grouped read blurs, so the component still renders every pair and logs a dev warning.

Four homes

Accessibility

The accessible name leads with the largest gap — "2 pairs. Largest gap East: 940 vs 1,200." The interactive entry roves pairs and announces each as value vs reference ("East: 940 vs 1,200.").

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; ref }[]Value + reference per category.
mode"grouped" | "overlay"Overlay puts the ref as a full-width ghost behind — halves the footprint.
positive"up" | "down"Over/under-reference valence tint.
orientation"horizontal" | "vertical"Rows for wide cells.
localestring | string[]BCP 47 locale(s) for the gap named in the summary, e.g. "de-DE".
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