StackedBarChart
ImplementedMulti-series stacked bar chart (recharts integration). Used for channel breakdowns (merch/ticket/package/pass/free per day).
components/organisms/StackedBarChart/StackedBarChart.tsxMulti-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.
| Label | Value | |
|---|---|---|
| Billets | Forfaits | |
| Lun 4 | 120 | 30 |
| Mar 5 | 98 | 41 |
| Mer 6 | 143 | 26 |
| Jeu 7 | 87 | 35 |
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.
...
| Label | Value | |
|---|---|---|
| Billets | Forfaits | |
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.
| Label | Value | |
|---|---|---|
| Billets | Forfaits | |
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
data*Record<string, unknown>[]Data rows — one per x-axis tick, keyed by xAxisKey plus one numeric field per series dataKey.
xAxisKey*stringRow field rendered on the x-axis (the category label, e.g. 'day').
series*StackedBarSeries[]Stacked series definitions — see the series definition table below.
heightnumber280Chart height in pixels.
xAxisFormatter(value: string) => stringidentityFormats x-axis ticks and tooltip labels (e.g. ISO date → '12 août').
tooltipFormatter(value: number, name: string) => [string, string]toLocaleStringFormats tooltip cells; returns [formattedValue, displayName].
ariaLabelstringStacked 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).
srTableCaptionstringStacked bar chart dataCaption of the built-in sr-only data table.
srLabelHeaderstringLabelHeader of the label (x-axis) column in the sr-only data table.
srValueHeaderstringValueGroup header spanning the per-series value columns; each column is headed by its own series.label.
loadingbooleanRenders a centered '...' placeholder instead of the chart; the wrapper carries aria-busy="true" while loading.
Series definition
StackedBarSeries — the shape of each series entry.
dataKey*stringRow field stacked into this bar series.
label*stringLegend and tooltip display name — localize at the call site.
color*stringBar 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 slotstorefront/src/components/dashboard/TicketsChannelChart.tsx— five-series channel breakdown (merch/ticket/package/pass/free)
Props
StackedBarChart
dataRecord<string, unknown>[]—Array of data points (one per x-axis tick)
xAxisKeystring—Key for the x-axis values (e.g. 'day')
seriesStackedBarSeries[]—Array of { dataKey, label, color, radius? } defining each bar series
heightnumber280Chart height in pixels
ariaLabelstring'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).
srTableCaptionstring"Stacked bar chart data"Caption for the visually-hidden data table (screen readers). French consumers should pass localized string.
srLabelHeaderstring"Label"Header for the label (x-axis) column in the sr-only data table. French consumers should pass localized string.
srValueHeaderstring"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.
<StackedBarChart />Accessibility
ARIA
4 rulesUsage
Import
import { StackedBarChart } from "@epasslive/design-system"Example 1
<StackedBarChart data={daily} xAxisKey="day" series={series} />