Passer au contenu principal

TimeSeriesAreaChart

Implemented

Time-series area chart with gradient fill (recharts integration). Used for revenue-over-time with currency-formatted axes.

Categoryorganisms
Sourcecomponents/organisms/TimeSeriesAreaChart/TimeSeriesAreaChart.tsx
AI HintUse for time-series area charts with currency formatting. Replaces direct recharts imports in consumer packages.

Single-series time-series area chart (recharts-based) with a vertical gradient fill, currency-ready axis/tooltip formatters and a designed empty state — pass hasData={false} plus emptyMessage instead of branching at the call site.

TimeSeriesAreaChart

Organism — Chart family

One Area over dataKey, stroked with color (default --ep-text-teal) and filled with a gradient keyed by gradientId. yAxisFormatter and tooltipFormatter adapt the public (number) => string contract; labelFormatter adapts (label: string) => string.

EmptyState

Organism — Chart family

hasData={false} + emptyMessage: the designed empty state renders inside the fixed-height container — no call-site branching, the frame stays stable.

Aucun revenu pour cette période

Loading

Organism — Chart family

loading: renders nothing inside the fixed-height container — height is preserved so the layout does not shift when data lands.

Usage

Feed day-keyed rows with one numeric dataKey, name the chart with ariaLabel, and pass the same money formatter to yAxisFormatter and tooltipFormatter (the AdminStatistics pattern). Pass a unique gradientId per instance when several area charts share a page — SVG ids are global.

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

const daily = [
  { day: '2026-08-31', revenue: 1240 },
  { day: '2026-09-01', revenue: 1810 },
  { day: '2026-09-02', revenue: 990 },
  { day: '2026-09-03', revenue: 2260 },
  { day: '2026-09-04', revenue: 3140 },
  { day: '2026-09-05', revenue: 2870 },
  { day: '2026-09-06', revenue: 1980 },
]

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

const fmtMoney = (v: number) =>
  v.toLocaleString('fr-CA', { style: 'currency', currency: 'CAD', maximumFractionDigits: 0 })

<TimeSeriesAreaChart
  data={daily}
  xAxisKey="day"
  dataKey="revenue"
  xAxisFormatter={fmtDay}
  yAxisFormatter={fmtMoney}
  tooltipFormatter={fmtMoney}
  labelFormatter={fmtDay}
  ariaLabel="Revenus quotidiens, du 31 août au 6 septembre"
  gradientId="adminDailyGrad"
  hasData={daily.length > 0}
  emptyMessage={<p>Aucun revenu pour cette période</p>}
/>

Conventions

The default color (var(--ep-text-teal)) meets the ≥4.5:1 non-text contrast minimum on both themes (5.45:1 light / 4.75:1 dark on --ep-surface-card, WCAG 1.4.11); override with another audited token, never a raw hex. Gate the render with hasData and carry the designed empty state in emptyMessage — the height is fixed so loading, empty and populated states never shift the layout. Animation is disabled (isAnimationActive={false}) — the chart renders instantly without transitions. The organism imports charts.css (shared with StackedBarChart) for recharts DOM styling — token-based, dark/light auto-flip. This organism is single-series by design; for multi-series stacked bars use StackedBarChart.

Accessibility

When !loading && hasData && ariaLabel, the wrapper is a role="img" region named by ariaLabel (WCAG 1.1.1 / 4.1.2) — always pass a summary of metric + period (e.g. "Revenus quotidiens, du 31 août au 6 septembre"); the recharts SVG exposes no per-point text alternative. The emptyMessage node renders in a plain div (no img role) so its text content stays exposed to screen readers, and loading renders nothing — the accessible name exists only on the chart branch; the empty and loading branches have no img role. Unlike Chart, there is no built-in sr-only data table — for exact values, pair with an adjacent table (e.g. AdminDataTable) or nearby prose.

Props

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

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

xAxisKey*
string
—

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

dataKey*
string
—

Row field plotted on the y-axis (e.g. 'revenue').

color
string
var(--ep-text-teal)

Stroke and gradient color — pass a token, not a raw hex.

height
number
280

Chart height in pixels.

xAxisFormatter
(value: string) => string
—

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

yAxisFormatter
(value: number) => string
—

Formats y-axis ticks (e.g. money).

tooltipFormatter
(value: number) => string
—

Formats the tooltip value (e.g. money).

labelFormatter
(label: string) => string
—

Formats the tooltip header label (e.g. ISO date → short date).

ariaLabel
string
—

Accessible label for the chart region — produces a role="img" wrapper only when !loading && hasData && ariaLabel; otherwise dropped. Summarize the metric and period.

loading
boolean
—

Renders nothing inside the fixed-height container while data is fetched.

gradientId
string
tsAreaGrad

SVG gradient id — pass a unique id when rendering several instances on one page.

emptyMessage
React.ReactNode
—

Rendered instead of the chart when hasData is false (e.g. a muted Body empty-state).

hasData
boolean
—

Gate for the empty state — render the chart only when truthy.

Used By

  • storefront/src/components/dashboard/admin/AdminStatistics.tsx — daily-revenue area chart with money-formatted axes

Props

Preview

TimeSeriesAreaChart

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

Array of data points

xAxisKey
string
Required
—

Key for the x-axis values

dataKey
string
Required
—

Key for the y-axis data values

color
string
Optional
var(--ep-text-teal)

Stroke and gradient color (WCAG-safe on card surface)

height
number
Optional
280

Chart height in pixels

ariaLabel
string
Optional
—

Accessible label for the chart region

loading
boolean
Optional
—

Renders nothing while fetching

gradientId
string
Optional
tsAreaGrad

SVG gradient id — unique per instance

emptyMessage
ReactNode
Optional
—

Rendered when hasData is false

hasData
boolean
Optional
—

Gate for the empty state

Quick use:<TimeSeriesAreaChart />

Accessibility

ARIA roleimg

ARIA

1 rule

WCAG 1.1.1

Container must have role='img' with aria-label when !loading && hasData && ariaLabel (conditional post-S2)

Usage

Import

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

Example 1

tsxSnippet
<TimeSeriesAreaChart data={daily} xAxisKey="day" dataKey="revenue" hasData />
Design System v4.1.0 | ePassLive