caliper uidocs

Combo chart

Free

An amount as bars and a rate as a line, on two axes. The bars rise first and the line draws over them; one column highlight reads both.

Installs components/ui/combo-chart.tsxDepends on d3-shapeMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/combo-chart.json
Orders and checkout conversion

Orders and checkout conversion
PeriodOrdersConversion
Jan8202.1
Feb7602
Mar9102.3
Apr10402.6
May9802.4
Jun12102.9
Jul13403.1
Aug12902.8
Sep14603.3

When to use #

Use it for

  • Orders and conversion rate, signups and activation, spend and return.
  • A rate that only means something next to its volume.

Skip it when

  • Two amounts in the same unit; group them as bars.
  • Readers who will compare the two axes' heights; say plainly that the scales differ.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/combo-chart.json

Adds its 6 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { ComboChart } from "@/components/ui/combo-chart"

const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

const orders = months.slice(0, 9).map((label, i) => ({ id: label, label, values: { orders: [820, 760, 910, 1040, 980, 1210, 1340, 1290, 1460][i], rate: [2.1, 2.0, 2.3, 2.6, 2.4, 2.9, 3.1, 2.8, 3.3][i] } }));

export function ComboChartDemo() {
  return (
    <ComboChart
      label="Orders and checkout conversion"
      data={orders}
      bars={[{ id: "orders", label: "Orders" }]}
      line={{ id: "rate", label: "Conversion" }}
      formatBar={(v) => v.toLocaleString("en-US")}
      formatLine={(v) => `${v.toFixed(1)}%`}
      className="w-full"
    />
  );
}

API reference #

ComboChart

component
PropTypeDefaultDescription
label *string—
data *readonly ChartDatum[]—
bars *readonly ChartSeries[]—One or more bar series, grouped side by side.
line *ChartSeries—The series on the right axis.
formatBar((value: number) => string)numberText
formatLine((value: number) => string)numberText
heightnumber260
loadingboolean—
errorstring—
classNamestring—

Accessibility #

It exposes group and status semantics, with aria-label, aria-busy and aria-hidden kept in step with state. Changes that matter are announced through a live region.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.