AreaChart
A time-series area chart with gradient fills, stacking, dual Y-axis, comparison overlays, and reference lines.
import { AreaChart } from "metricui";Use AreaChart to visualize time-series data with filled areas that emphasize volume and trends. It supports gradient fills, stacking, dual Y-axis, comparison overlays, reference lines, and threshold bands. For clean lines without area fills, use LineChart instead.
Basic Example
<AreaChart
data={[{
id: "Revenue",
data: [
{ x: "Jan", y: 42000 },
{ x: "Feb", y: 45000 },
{ x: "Mar", y: 48000 },
// ...
],
}]}
title="Revenue Over Time"
format={{ style: "currency" }}
/>Stacked Areas
Pass multiple series and enable stacked to stack areas. Use stackMode="percent" to normalize to 100%.
<AreaChart
data={trafficData}
stacked
title="Traffic Sources"
format={{ style: "number", compact: true }}
/>Comparison Overlay
Pass comparisonData to render a dashed overlay of a previous period. The comparison lines use 50% opacity so the current period stays prominent.
<AreaChart
data={currentPeriod}
comparisonData={previousPeriod}
title="Revenue vs Last Year"
format={{ style: "currency" }}
/>Reference Lines & Thresholds
Add horizontal or vertical referenceLines for targets and benchmarks. Use thresholds to highlight Y-axis ranges (e.g., danger zones, target bands).
<AreaChart
data={revenueData}
title="Revenue with Target"
format={{ style: "currency" }}
referenceLines={[
{ axis: "y", value: 60000, label: "Target", color: "#EF4444", style: "dashed" },
]}
thresholds={[
{ from: 40000, to: 55000, color: "#F59E0B", label: "Warning zone" },
]}
/>Data States
Every component handles loading, empty, error, and stale states. Pass individual props or use the grouped state prop.
Loading
Error
Failed to load data
// Loading state
<AreaChart data={[]} title="Revenue" loading />
// Error state
<AreaChart data={[]} title="Revenue" error={{ message: "Failed to load" }} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
data* | { id: string; data: { x: string | number; y: number | null }[] }[] | — | Array of data series. Each series has an id and array of {x, y} data points. y: null creates gaps. |
index | string | — | Column key for the x-axis labels. Used with the unified flat-row data format. If omitted with categories, auto-inferred as the first string column. |
categories | Category[] | — | Columns to plot as series. Accepts plain strings or CategoryConfig objects ({ key, label?, format?, color?, axis? }). If omitted with index, auto-inferred as all number columns. |
simpleData | { label: string; value: number | null }[] | — | Simple data format for single-series. Converted to full series internally. `data` takes precedence. |
simpleDataId | string | "Value" | Series name when using simpleData. |
comparisonData | { id: string; data: { x: string | number; y: number | null }[] }[] | — | Previous period data rendered as dashed overlay lines at 50% opacity. Same shape as `data`. Use for period-over-period comparison — e.g., this month vs last month. Series IDs must match `data` series IDs. |
title | string | — | Chart card title. |
subtitle | string | — | Chart card subtitle. |
description | string | React.ReactNode | — | Description popover content. |
footnote | string | — | Footnote below the chart. |
action | React.ReactNode | — | Action slot in the top-right corner of the header. |
format | FormatOption | — | Format for Y-axis values and tooltips. |
height | number | 300 | Chart height in px. Dense mode defaults to 220. |
curve | CurveType | "monotoneX" | Curve interpolation: "basis", "cardinal", "catmullRom", "linear", "monotoneX", "monotoneY", "natural", "step", "stepAfter", "stepBefore". |
enablePoints | boolean | false | Show data points on the line. |
enableArea | boolean | true | Show filled area under the line. |
gradient | boolean | true | Use gradient fill instead of flat opacity. |
areaOpacity | number | 0.08 | Area fill opacity when gradient is false. |
stacked | boolean | false | Stack multiple series. |
stackMode | "normal" | "percent" | "normal" | Stack mode. "normal" stacks raw values, "percent" normalizes to 100%. |
enableGridX | boolean | false | Show vertical grid lines. |
enableGridY | boolean | true | Show horizontal grid lines. |
referenceLines | ReferenceLine[] | — | Horizontal or vertical reference lines for targets, averages, or benchmarks. Each: `{ axis: 'x'|'y', value: number|string, label?: string, color?: string, style?: 'solid'|'dashed'|'dotted' }`. Rendered on top of the chart area. |
thresholds | ThresholdBand[] | — | Colored horizontal range bands for danger/warning/safe zones. Each: `{ from: number, to: number, color: string, opacity?: number, label?: string }`. Rendered behind the chart area. Great for SLA targets, budget limits, or performance zones. |
legend | boolean | LegendConfig | — | Legend with series toggle. `true` shows default legend. LegendConfig: `{ position?, orientation?, toggleable?, className? }`. Cmd/Ctrl+click to solo a series. ARIA keyboard accessible. |
xAxisLabel | string | — | Label displayed along the X-axis. Use to clarify units or context (e.g., 'Month', 'Date'). Auto-hidden at narrow widths (<400px). |
yAxisLabel | string | — | Label displayed along the Y-axis. Use to clarify units or context (e.g., 'Revenue ($)', 'Users'). Auto-hidden at narrow widths (<400px). |
rightAxisSeries | string[] | — | Series IDs to plot on a separate right Y-axis. Use for dual-axis charts where series have different scales (e.g., revenue on left, percentage on right). |
rightAxisFormat | FormatOption | — | Format for the right Y-axis values and tooltips. Typically different from the left axis (e.g., left='currency', right='percent'). |
rightAxisLabel | string | — | Label for the right Y-axis. |
lineWidth | number | 2 | Line width in px. |
lineStyle | "solid" | "dashed" | "dotted" | "solid" | Line stroke style. |
pointSize | number | 6 | Point radius in px. |
pointColor | string | { from: string; modifiers?: any[] } | "var(--card-bg)" | Point fill color. Default creates hollow ring effect. Use { from: "serieColor" } for solid. |
pointBorderWidth | number | 2 | Point border width in px. |
pointBorderColor | string | — | Point border color. Default: series color. |
seriesStyles | Record<string, SeriesStyle> | — | Per-series visual overrides keyed by series ID. Override color, lineWidth, lineStyle ('solid'|'dashed'|'dotted'), pointSize, pointColor, pointBorderWidth for individual series. E.g., make one series dashed while others are solid. |
colors | string[] | — | Series colors. Default: theme series palette (SERIES_COLORS). |
onPointClick | (point: { id: string; value: number; label: string; seriesId: string; x: string | number; y: number }) => void | — | Click handler for data points. |
dense | boolean | false | Compact layout — reduces margins and default height. |
chartNullMode | ChartNullMode | "gap" | How null/missing data points are handled: "gap", "zero", or "connect". |
animate | boolean | true | Enable/disable chart animation. Falls back to config.animate. |
variant | CardVariant | — | Card variant (supports custom strings). CSS-variable-driven via [data-variant]. Falls back to config.variant. |
className | string | — | Additional CSS class names. |
classNames | { root?: string; header?: string; chart?: string; legend?: string } | — | Sub-element class name overrides. |
id | string | — | HTML id attribute. |
data-testid | string | — | Test id for testing frameworks. |
loading | boolean | — | Loading state. |
empty | EmptyState | — | Empty state configuration. |
error | ErrorState | — | Error state configuration. |
stale | StaleState | — | Stale data indicator. |
crossFilter | boolean | { field: string } | — | Enable cross-filter signal on click. true uses the index field, { field } overrides. Emits selection via CrossFilterProvider — does NOT change chart appearance. Dev reads selection with useCrossFilter() and filters their own data. |
tooltipHint | boolean | string | — | Show action hint at bottom of tooltip. true: auto ('Click to drill down' / 'Click to filter'). string: custom hint text. false: disable. Default: respects MetricConfig.tooltipHint (true). |
drillDown | boolean | ((event: { indexValue: string; data: Record<string, unknown> }) => React.ReactNode) | — | Enable drill-down on click. `true` auto-generates a summary KPI row + filtered DataTable from the chart's source data. Pass a render function for full control over the panel content. Requires DrillDown.Root wrapper. When both drillDown and crossFilter are set, drillDown wins. |
drillDownMode | DrillDownMode | "slide-over" | Presentation mode for the drill-down panel. "slide-over" (default) slides from the right, full height. "modal" renders centered and compact. |
exportable | ExportableConfig | — | Enable PNG/CSV/clipboard export. true: auto-exports source data as CSV. { data: rows[] }: exports custom rows. Charts auto-detect source data. Set globally via MetricProvider or per-component. |
Data Shape
// Full series format
type Datum = { x: string | number; y: number | null };
type SeriesData = { id: string; data: Datum[] };
// Simple format (single series)
type SimpleData = { label: string; value: number | null }[];Notes
- Uses forwardRef.
- Uses forwardRef — attach a ref to the root div.
- X-axis ticks are automatically thinned based on container width.
- Left Y-axis is hidden at container widths below 300px.
- When using rightAxisSeries, right-axis data is internally normalized to the left scale and de-normalized for tooltips.
- Comparison data renders as dashed lines at 50% opacity.
- simpleData is converted to full series format internally; `data` takes precedence when non-empty.
- crossFilter prop emits a selection signal on click — it does NOT change the chart's appearance. The dev reads the selection via useCrossFilter() and filters their own data.
- drillDown={true} auto-generates a summary KPI row + filtered DataTable from the chart's source data. Pass a render function for custom panel content. Requires DrillDown.Root wrapper.
- When both drillDown and crossFilter are set on the same component, drillDown wins.
- All charts use CardShell internally. CardShell features (export, auto empty state, variant, dense, data states) work everywhere automatically.
- exportable: true auto-exports the chart's source data as CSV. Charts auto-detect their data — no manual { data } override needed.
- Auto empty state: when the chart has no data (exportData.length === 0), CardShell shows 'Nothing to show — try adjusting your filters' automatically. Override globally via MetricProvider.emptyState or per-component via the empty prop.
Playground
Experiment with every prop interactively. Adjust the controls on the right to see the component update in real time.
Live Preview
Monthly recurring revenue
Code
<AreaChart
data={[{ id: "Revenue", data: [...] }]}
title="Revenue Over Time"
subtitle="Monthly recurring revenue"
format={{ style: "currency" }}
/>Props
Adjust props to see the chart update in real time
Switch between sample datasets
Applied to Y-axis labels and tooltips
Line interpolation method
Stroke width in px
Stroke dash pattern
When set, stacking is implicit. 'percent' normalizes to 100%.