AreaChart
A typed area chart — single or stacked, with solid or gradient fill.
Usage
import { AreaChart } from '@acronis-platform/ui-react';
import type { ChartConfig } from '@acronis-platform/ui-react';AreaChart is a typed composition over the shared Chart
primitives. Give it data, a per-series config, the series to plot
(dataKeys), and the category key (xKey) — it renders a themed recharts area
chart (tooltip, legend, axes, grid included), so you don't hand-compose recharts
children.
Series colors come from the palette prop, not from config — see
Palettes. Each config entry maps a data key to a
label and an optional tone that re-points that one series within the palette.
AreaChart resolves them into the --color-<key> custom properties its areas
stroke and fill from. Single vs multi area simply follows from how many
dataKeys you plot.
Examples
A multi-series area chart with the default solid fill, a themed tooltip and legend:
const data = [
{ month: 'Jan', desktop: 186, mobile: 80 },
{ month: 'Feb', desktop: 305, mobile: 200 },
{ month: 'Mar', desktop: 237, mobile: 120 },
];
const config = {
desktop: { label: 'Desktop' },
mobile: {
label: 'Mobile'
},
} satisfies ChartConfig;
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
className="h-[320px] w-[560px]"
/>;Stack the series into one band with layout="stacked":
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
layout="stacked"
/>Switch from the default solid fill to a gradient with fill="gradient" — the
series color fades from full opacity at the line down to transparent:
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
fill="gradient"
/>Change the interpolation with curve. Seven types are available, from most to
least literal about the data:
curve | Reads as |
|---|---|
linear | Straight segments between points. |
monotone (default) | Smoothed, never overshooting a point's value. |
natural | A natural cubic spline — smoother, but it may overshoot, so read it as a trend. |
basis | A B-spline that need not pass through the points at all; the smoothest, least literal option. |
step | Right angles, changing value at the midpoint between two points. |
stepBefore | The same, changing at the leading point. |
stepAfter | The same, changing at the trailing point. |
Toggle the chrome / dots with showGrid / showTooltip / showLegend /
showDots:
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
curve="stepAfter"
showLegend={false}
/>dotSize sets the dot radius (3px by default; the hover dot is always 2px
larger). showActiveDot decides the hover dot on its own — unset it follows
showDots:
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
showDots
dotSize={5}
/>Add axis titles and a y-axis unit suffix with xAxisLabel / yAxisLabel /
yUnit (the x-axis is categorical). The titles inherit the theme token:
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
xAxisLabel="Month"
yAxisLabel="Response time"
yUnit="ms"
/>Projections
Mark a boundary at which the data transitions from actuals to forecast with
projectionStart. Pass the xKey value where the projection zone begins — from
that point onward, x-axis tick labels render in the disabled text color, series
strokes switch to a dashed pattern, and the area fill is suppressed so only the
dashed line continues:
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
projectionStart="Apr"
/>The boundary point is included in both the solid and dashed segments so they
connect visually. When projectionStart doesn't match any value in the data the
chart renders normally.
Per-series overrides
areaSettings restyles one series without touching the others — keyed by data
key, and any field left out falls back to the chart-wide prop. A faint dashed
projection beside solid actuals, for instance:
<AreaChart
config={config}
data={data}
dataKeys={['actual', 'projected']}
xKey="month"
areaSettings={{
projected: { dashed: true, fillOpacity: 0.1 },
}}
/>Each entry takes color, strokeWidth, dashed, curveType, fillOpacity,
showDots, dotSize, and the label controls (showLabel, labelPosition) — so
one series can carry value labels while the rest stay clean. A color override
also recolors that series' gradient stops, and under fill="gradient" a
fillOpacity scales the gradient's own alpha rather than replacing it.
Reference line
referenceLine draws a dashed rule across the value axis — a target, a
threshold, or a series average. Pass one config or an array:
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
referenceLine={[
{ value: 320, label: 'Target' },
{ average: true, label: 'Average' },
]}
/>A fixed value wins; otherwise average takes the mean of one series
(average: 'desktop') or of every plotted series (average: true) — null
values are skipped, and nothing is drawn when there are no numeric values to
average. The rule extends the axis domain, so a target above the data maximum
stays visible instead of being clipped.
Each caption sits at its rule's top right. Where that lands on the series,
labelPosition moves it (top, insideTopLeft, insideTopRight,
insideBottomLeft, insideBottomRight):
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
referenceLine={{
average: true,
label: 'Average',
labelPosition: 'insideBottomLeft',
}}
/>Under layout="stacked" the value is read against the stack's axis, which
measures stack totals — but average is still the mean of the individual
series' values, so pass an explicit value when the rule should compare against
the stacked total. BarChart and LineChart take the same config.
Custom tooltip
Replace the tooltip with a configured ChartTooltipContent — imported from the
same library, so you never compose recharts yourself. Its formatter renders
each row and labelFormatter the header, giving you custom formatting, per-series
content, and extra fields:
import { AreaChart, ChartTooltipContent } from '@acronis-platform/ui-react';
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
tooltipContent={
<ChartTooltipContent
labelFormatter={(label) => `${label} · fiscal Q3`}
formatter={(value, name) => `${name}: ${value.toLocaleString()}k`}
/>
}
/>;Format the tick values with xTickFormatter / yTickFormatter, or hide an axis
with showXAxis / showYAxis — the shared axis knobs described under
Formatting and hiding axes. Unlike
unit, a formatter transforms the value (abbreviate, currency, map to a label):
import { AreaChart, formatCompactNumber } from '@acronis-platform/ui-react';
<AreaChart
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
yTickFormatter={formatCompactNumber}
/>;Animation
Charts render statically by default. Opt in to an entrance animation with
animate, and tune it with animationDuration / animationBegin /
animationEasing:
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
animate
animationDuration={800}
animationEasing="ease-out"
/>animate honors prefers-reduced-motion: for a visitor who has asked their
system to reduce motion, the series render at their final geometry with no
animation (the same applies when rendering on the server).
Data labels
Annotate each point with its value using showLabels. labelFormatter takes the
same formatters as the axes, so a label and its axis read alike:
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
showLabels
labelFormatter={formatCompactNumber}
/>labelPosition moves them; the default is top. Under layout="stacked" that
end is covered by the next segment, so each value centres inside its own segment
instead. An area's fill is translucent, so labels keep the on-surface text color
at every position — the surface, not the series color, is what shows behind them:
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
showLabels
labelPosition="insideEnd"
/>Labels are off by default — with more than one series they collide easily, so turn them on for a single series or a chart with room to spare.
Range brush
Long series don't have to be read all at once: showBrush renders a range
selector under the plot. Drag a handle — or the selected window itself — and the
series, its category axis, and the tooltip all follow the selection. brushHeight
sizes the strip (28px by default):
<AreaChart
config={config}
data={data}
dataKeys={['desktop']}
xKey="month"
showBrush
/>The brush indexes rows, so it slices the category axis. It is independent of
showXAxis, so a chart with its axis hidden still gets a working brush. The two
range captions appear on the strip while you hover, drag, or focus a handle.
Both handles are focusable role="slider" elements: Tab reaches them, and the
arrow keys move the selection one row at a time. Pass brushAriaLabel to
localize their accessible name (it defaults to 'Chart range selector').
Accessibility
Neither AreaChart nor the shared ChartContainer adds a role or an aria-*
attribute of its own. What semantics the chart has come from recharts, whose
accessibility layer is on by default and is not switched off here: the plot's
<svg> renders role="application" with tabindex="0", so Tab reaches it and
focusing it opens the tooltip on the first category. The left/right arrow keys
step it along the categories. Enter toggles the tooltip rather than pinning
it, and since focus has already opened one, the first Enter closes it — press
Enter again, or an arrow key, to bring it back.
That surface has no accessible name, though, and the layer to fix that is this
one rather than recharts. recharts takes title, desc and role as
first-class chart props and writes them straight into the plot's <svg>;
AreaChart passes none of them down, because it spreads the props it doesn't
consume onto its own root <div> and hands the recharts chart only the data and
margins it computes itself. The <title> and <desc> recharts always emits
therefore stay empty and a screen reader announces an unnamed application
region. The tooltip is not a live region either: ChartTooltipContent renders
plain markup with no role="status" or aria-live, so the values it reveals as
you arrow along are shown but never announced.
So name the chart from the outside: role and aria-label (or
aria-labelledby) land on that same root <div>. Choose the role before you
copy the snippet, though. role="img" names the chart and also makes its
subtree presentational, hiding the plot from assistive technology while it stays
in the tab order; that is the right trade when the picture is the whole message.
Where the keyboard tooltip should stay reachable, wrap the chart in a <figure>
with a <figcaption>, or pass role="group" with the same aria-label, and
leave the plot's own semantics alone.
<AreaChart
role="img"
aria-label="Desktop and mobile sessions, January to March"
config={config}
data={data}
dataKeys={['desktop', 'mobile']}
xKey="month"
/>A name is not a text alternative. The chart is a visual encoding of numbers, and
"Sessions by month" says what the picture is about, not what it shows — so put
the numbers in text as well: a caption carrying the takeaway, a summary sentence,
or the same rows in an adjacent Table. Series are told
apart by hue alone unless you say otherwise, so on a multi-series chart reach for
areaSettings[key].dashed, per-series dots, or showLabels to give each one a
second cue.
The range brush is the one part of the plot with real control
semantics. Each traveller is a role="slider" element with tabindex="0", named
by brushAriaLabel, and the left/right arrow keys move that end of the selection
one row at a time — the traveller consumes those keys, so they resize the range
instead of stepping the tooltip. ChartContainer restores the focus outline that
its blanket outline-hidden would otherwise take away. Its aria-valuenow is
recharts' own: the handle's pixel position, not a row index, so what a screen
reader reads back from it carries no meaning.
Direction (RTL)
Under dir="rtl" the chrome around the plot mirrors on its own — the legend, the
tooltip, and any readouts you compose alongside the chart are ordinary flow
layout built from logical CSS utilities. The plot area itself deliberately stays
left-to-right: recharts lays every mark out in physical SVG coordinates, so a
mirrored category axis would flip the reading order of the data without flipping
the geometry that encodes it. This is what mainstream charting libraries do by
default.
ChartContainer pins .recharts-surface to direction: ltr so that holds
whatever the page inherits, and the pin is load-bearing rather than a
formality: recharts anchors axis tick text with the direction-relative SVG
keywords text-anchor: start / end while placing each mark at a coordinate it
computed in physical space, so an inherited dir="rtl" mirrors the text away
from the geometry — end-anchored Y-axis ticks land inside the plot area,
rotated X-axis ticks drift, and a ReferenceLine label at the right edge
overflows the surface. Text anchored middle is direction-immune either way:
unrotated X-axis ticks, axis titles, and the values showLabels draws. Because
the pin stops at the surface, the tooltip and the legend — HTML outside it —
still mirror. Chart carries the measured detail.
API Reference
Prop
Type