DitherCharts

Combo chart

Updated

ComboChart draws dithered bars on the left axis and one-cell pixel lines on a right axis whose grid lines up with the bars', the line cut clear of the bars' tone. Like every DitherCharts chart, it fills its container's width, animates in, moves a cursor with the arrow keys, and keeps a data table for screen readers.

Example

Combo

Revenue bars with the conversion rate on a second axis

Combo

Install it:

npx dithercharts add combo-chart

Then use it:

import { ComboChart } from "@/components/dithercharts/combo-chart"
import type { ChartConfig } from "@/components/dithercharts/chart-config"

const chartData = [
  { month: "Jan", revenue: 186, conversion: 2.1 },
  { month: "Feb", revenue: 305, conversion: 3.4 },
  { month: "Mar", revenue: 237, conversion: 2.8 },
  { month: "Apr", revenue: 173, conversion: 2.2 },
  { month: "May", revenue: 209, conversion: 2.9 },
  { month: "Jun", revenue: 264, conversion: 3.6 },
  { month: "Jul", revenue: 298, conversion: 4.1 },
  { month: "Aug", revenue: 251, conversion: 3.5 },
  { month: "Sep", revenue: 222, conversion: 3 },
  { month: "Oct", revenue: 276, conversion: 3.8 },
  { month: "Nov", revenue: 318, conversion: 4.4 },
  { month: "Dec", revenue: 342, conversion: 4.6 },
]

const chartConfig = {
  revenue: { label: "Revenue" },
  conversion: { label: "Conversion %" },
} satisfies ChartConfig

export function ChartCombo() {
  return (
    <ComboChart
      data={chartData}
      config={chartConfig}
      xKey="month"
      lineKeys={["conversion"]}
      label="Monthly revenue and conversion"
    />
  )
}

Installing needs DitherCharts Pro. See pricing.

Monthly revenue and conversion
monthRevenueConversion %
Jan1862.1
Feb3053.4
Mar2372.8
Apr1732.2
May2092.9
Jun2643.6
Jul2984.1
Aug2513.5
Sep2223
Oct2763.8
Nov3184.4
Dec3424.6
import { ComboChart } from "@/components/dithercharts/combo-chart"
import type { ChartConfig } from "@/components/dithercharts/chart-config"

const chartData = [
  { month: "Jan", revenue: 186, conversion: 2.1 },
  { month: "Feb", revenue: 305, conversion: 3.4 },
  { month: "Mar", revenue: 237, conversion: 2.8 },
  { month: "Apr", revenue: 173, conversion: 2.2 },
  { month: "May", revenue: 209, conversion: 2.9 },
  { month: "Jun", revenue: 264, conversion: 3.6 },
  { month: "Jul", revenue: 298, conversion: 4.1 },
  { month: "Aug", revenue: 251, conversion: 3.5 },
  { month: "Sep", revenue: 222, conversion: 3 },
  { month: "Oct", revenue: 276, conversion: 3.8 },
  { month: "Nov", revenue: 318, conversion: 4.4 },
  { month: "Dec", revenue: 342, conversion: 4.6 },
]

const chartConfig = {
  revenue: { label: "Revenue" },
  conversion: { label: "Conversion %" },
} satisfies ChartConfig

export function ChartCombo() {
  return (
    <ComboChart
      data={chartData}
      config={chartConfig}
      xKey="month"
      lineKeys={["conversion"]}
      label="Monthly revenue and conversion"
    />
  )
}

Install

Charts install with DitherCharts Pro. See Installation to log in and import the stylesheet.

npx dithercharts add combo-chart

Props

ComboChart props
PropTypeDefaultDescription
datarequiredType readonly ChartRow[]Default –One row per x position, left to right, e.g. { month: "Jan", revenue: 186, conversion: 2.4 }.
configrequiredType ChartConfigDefault –One entry per data key to plot, in draw and legend order: its label and, optionally, its pattern.
xKeyrequiredType stringDefault –The row key that holds the x label, e.g. "month".
lineKeysrequiredType readonly string[]Default –The config keys drawn as lines; every other config key is a bar. Keys not in config are ignored.
labelrequiredType stringDefault –Accessible name, e.g. "Revenue and conversion". Also captions the table twin.
dualAxisType booleanDefault trueThe lines on their own right axis, its grid aligned to the bars' left axis. False puts them on the left axis.
legendType booleanDefault falseA legend under the chart whose buttons show and hide series.
yAxisType booleanDefault trueValue labels beside the grid lines, on both axes.
stackType "none" | "stacked"Default "none"The bars side by side, or stacked; the lines never stack.
radiusType numberDefault 0 (square, pixel-hard ends)Corner radius of a bar's ends in CSS pixels, stepped by the dither grid.
curveType "monotone" | "linear" | "step"Default "monotone"How the lines run between points.
dotsType "square" | "ring"Default noneA dot on every line point: a solid square, or a hollow ring that knocks the line out.
tooltipType TooltipOptionsDefault –The tooltip's indicator and label, and the x position it opens on at rest.
styleType StyleIdDefault "bayer4"Dither style.
animationType "develop" | "none"Default "develop"Entrance animation; reduced motion always shows the final frame.
heightType numberDefault 300Height in CSS pixels; the width fills the container.
cellType numberDefault 3Dither cell size in CSS pixels; a line is one cell wide.
classNameType stringDefault –Classes on the chart's outer figure.

Styles

The dither styles style takes:

  • "bayer2"
  • "bayer4"
  • "bayer8"
  • "blue-noise"
  • "halftone"
  • "crosshatch"
  • "pixel"
  • "stipple"
  • "engraved"
  • "mezzotint"
  • "woodcut"
  • "floyd-steinberg"
  • "atkinson"
  • "riemersma"

Keyboard and accessibility

The chart is one Tab stop. Focusing it from the keyboard puts the cursor on the first column, or where the keys last left it; moving focus away clears it. The keys stop at the ends.

Chart keys
KeyAction
Left arrow Right arrowPrevious / next column
Home EndFirst / last column
Up arrow Down arrowPrevious / next series (2+ series)
EscapeDismiss the cursor

Screen readers

  • The chart's label names it, says how many columns it has and lists these keys.
  • Each key press is announced in a polite live region. Moving the pointer is silent.
  • The table button under the chart shows its data as a table. Screen readers can reach the table even while it's hidden; clicking a row moves the cursor there and announces it.
  • With legend, each entry is a toggle button. The last one showing can't be hidden, but its button stays focusable.

On a touch screen, a tap pins the cursor and a tap outside the chart dismisses it.

See every combo chart example