Skip to content

Charts

IBarChart ​

Bars, in plain SVG with no charting dependency. It inherits the theme like everything else, so it follows light and dark for free.

Revenue by month
Category Value
Jan€18,200
Feb€22,400
Mar€19,800
Apr€27,600
May€31,200
Jun€29,900

The width fills the container and height (240px by default) is the only dimension you set. The value axis always includes zero and lands on round numbers, so ticks is a target count rather than an exact one.

Hovering a category raises a tooltip with the value formatted exactly as the ticks are: locale and format feed one Intl.NumberFormat used everywhere in the chart.

Horizontal ​

Turn the chart when the category names are long or numerous — a horizontal chart gives every name a full row.

Revenue by channel
Category Value
Direct€41,200
Partner referrals€28,800
Marketplace€19,400
Outbound€12,100

Several series ​

Pass series to read more than one measure out of each datum. Each series names the key it reads and, optionally, how it should be labelled.

  • North
  • South
  • East
Revenue by quarter and region
Category NorthSouthEast
Q1€18,200€12,400€9,100
Q2€22,600€15,100€11,800
Q3€20,100€17,400€14,200
Q4€26,800€19,200€16,900

A legend appears automatically from two series up; legend is honoured only for a single series. When you filter series in and out, give each one a slot so its colour stays with the entity rather than with its position in the list.

Stacked ​

  • North
  • South
  • East
Total revenue by quarter, split by region
Category NorthSouthEast
Q1€18,200€12,400€9,100
Q2€22,600€15,100€11,800
Q3€20,100€17,400€14,200
Q4€26,800€19,200€16,900

Stacking answers "what makes up the total"; grouping answers "how do these compare". The stacked tooltip adds a sum row, labelled by totalLabel.

Negative values ​

Net change by month
Category Value
Jan€4,200
Feb-€1,800
Mar€3,100
Apr-€900
May€5,600

Bars below zero hang from the zero line rather than from the axis floor.

Bare bars ​

Drop the axis and gridlines for a chart that sits inside a tile, where the shape is the whole message.

Revenue by month
Category Value
Jan18,200
Feb22,400
Mar19,800
Apr27,600
May31,200
Jun29,900

Gaps ​

null is a missing reading, not a zero — no bar is drawn at all, which is not the same as a bar of no height.

Animation ​

The bars grow out of the baseline on the first paint, staggered a little across the categories so the row reads left to right. They grow from the baseline, not from their own box, so a negative bar drops rather than rising into the plot on its way down.

Revenue by month
Category Value
Jan18,200
Feb22,400
Mar19,800
Apr27,600
May31,200
Jun29,900

animate takes false to switch the reveal off, or an object to tune it: duration in milliseconds and easing, one of ease-out (the default), ease-in, ease-in-out or linear.

It plays once, on the first paint with something to draw — not again when the data changes underneath it, which on a polling dashboard would read as a fault rather than as polish. A reader who has asked for reduced motion gets the finished chart with no animation at all.

Props ​

PropTypeDefaultDescription
dataBarChartDatum[][]One entry per category
seriesChartSeries[]—Two or more measures per category
orientation'vertical' | 'horizontal''vertical'Bars up, or categories down the side
stackedboolean—One bar per category instead of a group
heightnumber240Rendered height in px; width fills the container
ticksnumber5Target tick count; the axis lands on round numbers
axisbooleantrueDraw the value axis and its gridlines
animateboolean or { duration, easing }trueReveal on the first paint; false turns it off
legendbooleantrueOnly honoured for a single series
totalLabelstring'Total'Word for the stacked tooltip's sum
localestring—Locale for every number in the chart
formatIntl.NumberFormatOptions—Options for every number in the chart
labelstring—Accessible name for the figure
unstyledboolean—Drop built-in classes
classstring—Merged with the built-in classes
ui{ root?, svg?, grid?, tick?, category?, bar?, tooltip?, tooltipLabel?, tooltipValue?, table? }—Per-element class overrides

Slots ​

SlotPropsWhen to use it
underlaylayout geometryDraw behind the bars — a target band, a shaded period
overlaylayout geometryDraw in front — an annotation, a threshold line

Data shapes ​

ts
interface BarChartDatum {
  label: string
  value?: number | null
  [key: string]: unknown
}

interface ChartSeries {
  key: string
  name?: string
  slot?: number
}

The bars are hidden from assistive technology and the same data is exposed as a table, named by label.