RoadieRoadie
  • Home
  • Foundations
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeFoundationsComponents
Appearance

Charts

  • Guidelines

    • Data visualisation
    • Dashboard design
  • Layout

    • Dashboard
    • DataCard
  • Data pieces

    • StatTile
    • Meter
    • Sparkline
    • DataTable
  • Chart types

    • LineChart
    • BarChart
    • RankedBars
    • StackedBars
    • Histogram
    • Funnel
    • Heatmap
    • Scatter
    • SmallMultiples
  • Chart parts

    • Chart
    • ChartLegend
    • ChartPatterns
    • ChartTooltip
  • Examples

    • Show dashboard
    • Portfolio dashboard
    • Audience dashboard

BarChart

Bars over time, with an optional second measure labelled at its end.

Import

import { BarChart } from '@oztix/roadie-charts/bar-chart'

Examples

Default

<div className='w-140 max-w-full'>
  <Chart label='Daily orders' source='Oztix sales.' size='md'>
    <BarChart
      data={[42, 88, 120, 94, 38, 51, 60].map((orders, i) => ({ day: `2026-10-0${i + 1}`, orders }))}
      x='day'
      y='orders'
      takeaway='Weekends carry the week'
    />
  </Chart>
</div>

Annotated on-sale

<div className='w-140 max-w-full'>
  <Chart label='On-sale by hour' source='Oztix sales.' size='md'>
    <BarChart
      data={[1840, 920, 410, 260, 210, 190].map((orders, i) => ({ time: `2026-08-03T${String(9 + i).padStart(2, '0')}:00`, orders }))}
      x='time'
      y='orders'
      interval='hour'
      annotations={[{ at: '2026-08-03T09:00', label: 'General on-sale' }]}
      takeaway='Nearly half the orders came in the first hour'
    />
  </Chart>
</div>

With a second measure

line draws another measure on its own axis. It is labelled at its end, so it needs no second axis.

<div className='w-180 max-w-full'>
  <Chart label='Entry' source='Oztix scans.' size='full'>
    <BarChart
      data={[80, 190, 300, 260, 150, 90].map((scans, i, all) => ({
        time: `2026-11-14T${String(17 + Math.floor(i / 2)).padStart(2, '0')}:${i % 2 ? '30' : '00'}`,
        scans,
        inside: all.slice(0, i + 1).reduce((a, b) => a + b, 0) / 1200
      }))}
      x='time'
      y='scans'
      interval='hour'
      line={{ y: 'inside', label: 'Inside', format: 'percent' }}
      takeaway='Entry peaked at 6pm'
    />
  </Chart>
</div>

States

<div className='grid w-140 max-w-full gap-4'>
  <p className='text-sm text-subtle'>No values yet</p>
  <Chart label='Daily orders' source='Oztix sales.' size='sm'>
    <BarChart data={[{ day: '2026-10-01', orders: null }]} x='day' y='orders' />
  </Chart>
</div>

Guidelines

  • Bars always start at zero.
  • Send one row per bar. Rows that share an x add up into one bar, and validateDashboard warns about them. A line can't add up a rate, so it keeps the first value it has and skips empty rows.
  • Use interval='hour' for on-sale and entry charts so ticks and spoken values carry the time.
  • Keep annotation labels to 20 characters. Mark what moved sales: announcements, line-up drops, email sends, ad bursts and price releases.
  • Only line gets its own scale. Don't put two unrelated measures on one chart. A percent line always runs from 0 to 100%.

Accessibility

  • The plot is one tab stop. Left and right arrows move between bars, and each bar is read out with its time, such as "Monday 3 August, 9am, 1,840 orders".
  • With line, each bar is read out with the second measure too, such as "Saturday 14 November, 6pm, 300 scans, inside 48%".
  • The Table tab lists every bar and the line measure in full.

API reference

BarChart

dataPlotRow[]
Required

Rows of plain values. Dates are ISO strings in venue wall time.

xstring
Required

Field along the bottom, usually an ISO date or time.

ystring
Required

Field for the bar height. Bars always start at zero.

format"number" | "compact" | "percent" | "currency" | "compactCurrency" | "points" | "index"

Defaults to 'number'.

takeawaystring

The headline sentence. It becomes the plot's accessible name.

annotations{ at: string | number; label: string; }[]

Dated markers with labels of 20 characters at most.

interval"hour" | "day" | "week"

How long each bar covers. Sets the tick and spoken formats.

Defaults to 'day'.

line{ y: string; label: string; format?: ValueFormat; }

A second measure on its own axis, labelled at its end.

classNamestring
Previous page← LineChartNext pageRankedBars →