Dual Axis Guard

Shows how much each series in a dual-axis chart really changed and offers to index both to 100, so the chart doesn't imply a correlation that isn't there.

StopsDual-axis chart faked a correlation

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/dual-axis-guard.json

The files land in your project. They're yours to edit.

Usage

dual-axis-guard-usage.tsx
import { DualAxisGuard } from "@/components/ui/dual-axis-guard"

<DualAxisGuard
  label="Ad spend vs sign-ups"
  labels={months}
  left={{ label: "Ad spend", values: [4.0, 4.1, 4.2, 4.35, 4.45, 4.6], format: lakh }}
  right={{ label: "Sign-ups", values: [1000, 1180, 1460, 1720, 2050, 2400] }}
  height={130}
/>

What it catches

  • Zero baselines at different heights on the two axes
  • Independent ranges that make different growth rates look identical
  • Each series' real change, stated in the summary

Props

DualAxisGuard props
PropTypeDefault
label* (required)

Accessible name of the chart, shown as its caption.

string—
labels* (required)

X-axis labels, one per value.

string[]—
left* (required)

The series on the left axis.

DualAxisSeries—
right* (required)

The series on the right axis.

DualAxisSeries—
value

Controlled view.

DualAxisMode—
defaultValue

Initial view when uncontrolled.

DualAxisMode"dual"
onValueChange

Called when the view switches between dual-axis and indexed.

(mode: DualAxisMode) => void—
indexAt

Which point becomes 100 when indexed, and where change is measured from.

number0
locale

Locale for the default number and percent formats.

string"en"
height

Plot height in px.

number160
children

Draw with your own chart library instead of the built-in SVG; the warnings still apply.

(view: DualAxisView) => React.ReactNode—
messages

Override any visible string.

Partial<DualAxisGuardMessages>—

* required. Also accepts the native props of <figure> (className, aria-*, data-*…), passed through to it.

Accessibility

  • A text summary of each series' change, linked to the chart
  • The scrubber is a role="slider" with arrow and Page Up/Down keys
  • Legend swatches are aria-hidden; series are named in text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Indexing to 100 needs a positive value at the index point
  • It flags misleading scales, not whether the series are actually related

What it stops

Dual-axis chart faked a correlation

Also known as

dual axis · chart · recharts · y axis · dashboard · analytics · line chart · data viz

Field type

Dependencies

Pairs well with