Skip to main content

StackedBarChart

Implemented

Multi-series stacked bar chart (recharts integration). Used for channel breakdowns (merch/ticket/package/pass/free per day).

Categoryorganisms
Sourcecomponents/organisms/StackedBarChart/StackedBarChart.tsx
AI HintUse for multi-series stacked bar charts. Replaces direct recharts imports in consumer packages.

Multi-series stacked bar chart (recharts-based) — one Bar per series sharing a single stack, over day/channel-keyed rows. Renders empty axes on empty data so the card frame stays visually consistent, and a “...” placeholder while loading.

StackedBarChart

Organism — Chart family

Stacks every series in `series` onto one bar per row (xAxisKey labels the row). Legend labels come from series.label; the topmost (last) series gets a rounded top by default.

Stacked bar chart data
LabelValue
BilletsForfaits
Lun 412030
Mar 59841
Mer 614326
Jeu 78735

Loading

Organism — Chart family

loading: renders a centered '...' placeholder inside the fixed-height role="img" container — the card frame stays stable while data is fetched.

...

Stacked bar chart data
LabelValue
BilletsForfaits

EmptyAxes

Organism — Chart family

data={[]}: empty axes, no 'no data' message — the consumer pattern (RevenueOverview, TicketsChannelChart design-phase dummies) that keeps the ChartCard frame visually consistent pre-wiring.

Stacked bar chart data
LabelValue
BilletsForfaits

Usage

Feed day-keyed rows plus one numeric field per series, and name the chart with ariaLabel — the SVG itself exposes no per-point text. Use xAxisFormatter for ISO dates and tooltipFormatter for currency.

import { StackedBarChart } from '@epasslive/design-system'

const daily = [
  { day: '2026-09-04', ticket: 120, pass: 30 },
  { day: '2026-09-05', ticket: 98, pass: 41 },
  { day: '2026-09-06', ticket: 143, pass: 26 },
  { day: '2026-09-07', ticket: 87, pass: 35 },
]

const series = [
  { dataKey: 'ticket', label: 'Billets', color: 'var(--chart-ticket)' },
  { dataKey: 'pass', label: 'Forfaits', color: 'var(--ep-amber)' },
]

const fmtDay = (d: string) =>
  new Date(d).toLocaleDateString('fr-CA', { month: 'short', day: 'numeric' })

<StackedBarChart
  data={daily}
  xAxisKey="day"
  series={series}
  xAxisFormatter={fmtDay}
  ariaLabel="Ventes par canal, du 4 au 7 septembre"
  srTableCaption="Données du graphique"
  srLabelHeader="Libellé"
  srValueHeader="Valeur"
/>

Conventions

Series colors must be tokens with ≥3:1 non-text contrast on both themes (WCAG 1.4.11) — var(--chart-ticket) and var(--ep-amber) are the audited pair; do NOT use var(--chart-merch) (amber-500 fails at 2.15:1 — DM-14). Empty data renders empty axes rather than a "no data" message; pair the chart with ChartCard's chart slot for the titled card frame (see TicketsChannelChart for the 5-series shape).

Accessibility

The wrapper is role="img" named by ariaLabel (WCAG 1.1.1 / 4.1.2) — pass a summary of series + period (e.g. "Ventes par canal, du 4 au 7 septembre") for the best name; when omitted, a default is derived from the series labels. The recharts SVG exposes no per-point text alternative, so exact values live in a built-in sr-only data table (same pattern as Chart): a caption (srTableCaption), a label column (srLabelHeader), and one column per series grouped under srValueHeader, each headed by its own series[].label. While loading, the wrapper carries aria-busy="true" and renders a plain "..." paragraph, so the accessible name stays stable across states. Legend labels and sr-table strings come from series[].label and the sr* props — localize them at the call site (e.g. srTableCaption="Données du graphique", srLabelHeader="Libellé", srValueHeader="Valeur").

Props

Prop
Type
Default
Description
data*
Record<string, unknown>[]
—

Data rows — one per x-axis tick, keyed by xAxisKey plus one numeric field per series dataKey.

xAxisKey*
string
—

Row field rendered on the x-axis (the category label, e.g. 'day').

series*
StackedBarSeries[]
—

Stacked series definitions — see the series definition table below.

height
number
280

Chart height in pixels.

xAxisFormatter
(value: string) => string
identity

Formats x-axis ticks and tooltip labels (e.g. ISO date → '12 août').

tooltipFormatter
(value: number, name: string) => [string, string]
toLocaleString

Formats tooltip cells; returns [formattedValue, displayName].

ariaLabel
string
Stacked bar chart: <series labels>

Accessible name for the role="img" wrapper — summarize the series and period; derived from the series labels when omitted ("Stacked bar chart" when series is empty).

srTableCaption
string
Stacked bar chart data

Caption of the built-in sr-only data table.

srLabelHeader
string
Label

Header of the label (x-axis) column in the sr-only data table.

srValueHeader
string
Value

Group header spanning the per-series value columns; each column is headed by its own series.label.

loading
boolean
—

Renders a centered '...' placeholder instead of the chart; the wrapper carries aria-busy="true" while loading.

Series definition

StackedBarSeries — the shape of each series entry.

Prop
Type
Default
Description
dataKey*
string
—

Row field stacked into this bar series.

label*
string
—

Legend and tooltip display name — localize at the call site.

color*
string
—

Bar fill — pass a token (e.g. var(--chart-ticket)), not a raw hex.

radius
[number, number, number, number]
—

Corner radius; defaults to [4, 4, 0, 0] and applies to the topmost (last) series only.

Used By

  • storefront/src/components/dashboard/RevenueOverview.tsx — two-series net/fee chart in a ChartCard slot
  • storefront/src/components/dashboard/TicketsChannelChart.tsx — five-series channel breakdown (merch/ticket/package/pass/free)

Props

Preview

StackedBarChart

Prop
Type
Required
Default
Description
data
Record<string, unknown>[]
Required
—

Array of data points (one per x-axis tick)

xAxisKey
string
Required
—

Key for the x-axis values (e.g. 'day')

series
StackedBarSeries[]
Required
—

Array of { dataKey, label, color, radius? } defining each bar series

height
number
Optional
280

Chart height in pixels

ariaLabel
string
Optional
'Stacked bar chart: <series labels>'

Accessible label for the chart region. Falls back to a label derived from the series labels when omitted (WCAG 4.1.2 named region).

srTableCaption
string
Optional
"Stacked bar chart data"

Caption for the visually-hidden data table (screen readers). French consumers should pass localized string.

srLabelHeader
string
Optional
"Label"

Header for the label (x-axis) column in the sr-only data table. French consumers should pass localized string.

srValueHeader
string
Optional
"Value"

Group header over the per-series value columns in the sr-only data table (each series column is headed by its own label). French consumers should pass localized string.

Quick use:<StackedBarChart />

Accessibility

ARIA roleimg

ARIA

4 rules

WCAG 1.1.1

Container must have role='img' with aria-label

WCAG 4.1.2

aria-label defaults to 'Stacked bar chart: <series labels>' when ariaLabel is omitted (region is always named)

WCAG 4.1.2

Loading state sets aria-busy='true' on the role='img' wrapper

WCAG 1.1.1

Provide data table alternative (visually-hidden but accessible) — caption + label column + grouped per-series value columns

Usage

Import

tsxSnippet
import { StackedBarChart } from "@epasslive/design-system"

Example 1

tsxSnippet
<StackedBarChart data={daily} xAxisKey="day" series={series} />
Design System v4.1.0 | ePassLive