For AI agents: the complete documentation index is available at https://wallarm.github.io/design-system/llms.txt, the full documentation bundle is available at https://wallarm.github.io/design-system/llms-full.txt, and this page is available as Markdown at https://wallarm.github.io/design-system/components/simple-charts.md.

SimpleCharts

Source · Storybook

Usage

import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartXAxis, LineChartYAxis, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';

Examples

AreaChart

Standard

Standard (overlaid) variant — each series draws from the baseline independently with transparency, useful when stacking would be misleading.

With metric

The metric variant: Metric bricks sit to the left of the legend in a row between the header and the plot.

Filterable

Clicking a legend row isolates that series and clicking another adds it back.

Zoom

Drag across the plot to choose a range, then confirm in the popover.

Loading

Loading skeleton state composed from the same primitives as a populated chart.

Empty

Empty state — LineChartEmpty keeps the dashed plot frame and puts the message inside it.

BarList

Default

The interactive shape: click a row to filter down to it, and the header's clear button appears while that filter holds. Filtering recomputes max from what is left, which is why a lone row reads 100%.

Colored

color tints the bar with a palette hue at 16% — enough to distinguish the rows while still letting the row's own hover state show through it.

Custom colors

For a hue the palette does not carry, pass a bg-* utility on the bar instead — the explicit class wins the merge against the variant's own fill.

Percentage

Values that are already percentages: max={100}, and the value slot prints the number itself rather than a share derived from it.

Selectable

selected marks the active row — the hover tint and aria-current — and never touches the bar, whose width stays value / max whatever is selected.

Truncated labels

Long labels truncate at the row width. A tooltip on the label needs pointer-events-auto, since the row's slots are transparent to the pointer by default.

Truncated labels with tooltip

The same labels under OverflowTooltip, which shows the full text only when it is actually cut off — the right choice when most labels fit.

Data variants

One card, three datasets behind a settings menu: raw counts, percentages and fractions each need their own max, so switching the source switches that too.

Loading

BarListSkeleton stands in for the list while data loads, taking a row count so the card holds the height it will end up at.

Overflow

A value above max caps the bar at full width and the label at 100%, rather than overrunning the row.

Invalid max

max={0} is not a division the component will guess at: every row renders empty at 0%, with a single warning in development.

Percent digits

digits adds decimal places, for a set of shares too close together to tell apart as whole numbers.

Percent variants

The three percent treatments — split colours the number and the % differently and is the Figma default, muted sets both back, inherit leaves them to the row.

Chart

Default

The frame with everything it owns — title, hover-revealed actions, and a body slot standing in for the chart.

With always visible actions

alwaysVisible pins the actions open, which is what a card does while a filter is applied: the control that clears it must not need hovering to be found.

Custom size

The card is a full-width block with a minimum height; give it a width and height directly when a dashboard slot demands a particular size.

Long title

ChartTitle stays on one line and truncates, so the actions keep their place however long the title runs.

Empty

ChartEmpty centres a default 'No data' in the body — the frame and the title stay, so the card does not vanish from the grid when its data does.

Empty with custom message

Pass children to say why it is empty. A card emptied by a filter should say so, since the fix is different from having no data at all.

Vertical Stacked Columns Chart

Default

Findings by verdict over a week: the legend carries each verdict and its total for the period, a column per day stacks the verdicts in legend order with the first on top. Hover a column for the day's breakdown, or a legend item to fade the other verdicts out.

Adaptive width

Column width follows the chart width and the number of steps: up to 32px, a fixed 22px between columns below that, and 16px at least. The same week in a narrow card keeps 32px columns; two weeks in it narrow them.

Card height

The plot follows the card height: set a height on <Chart> and the columns stretch or shrink with it. The card goes down to 128px — header, legend and a 72px plot.

Clickable legend

Legend items become buttons when they get an onClick — here a verdict opens its list, as on the Agentic Overview. The item's data-key carries the series key, so one handler serves every item. Hover and keyboard focus fade the other verdicts out alike.

Loading

Loading: skeleton legend items over LineChartEmpty's dashed plot frame.

Empty

Empty: LineChartEmpty keeps the dashed plot frame and puts the message inside it.

HorizontalBarStack

Default

The full shape: a headline value with its delta, a three-part band, and the legend that names the parts.

No delta

The same without the delta — a value with no comparison to make yet.

No value

No header at all: the band and its legend alone, for a card whose total is already stated somewhere else.

With remainder

A total above the sum of the parts fills the difference with a grey tail — 91 of 120, where the 29 nobody has accounted for is part of what the card says.

Legend off

legend={false} leaves the band on its own, for a card too small to carry names or one whose legend is already nearby.

Palette

All six chart colours in one band, which is the check that they stay tellable apart at the widths a real breakdown gives them.

Loading

HorizontalBarStackSkeleton stands in while the card loads, holding the header and band heights so nothing shifts when data arrives.

Selectable

onSelect turns the legend into a filter — the chosen series stays bright, the rest fade, and clicking it again clears. Hover always wins, so pointing at any series brings it forward regardless of what is selected.

LineChart

Default

One series with the full chrome — grid, both axes, and a tooltip that follows the pointer along the line.

Default multi

Three series with a legend composed from LineChartLegendItem rows. The dot in each row is the same one the tooltip uses, so the colours cannot drift apart.

With metric

The metric variant: the shared Metric bricks sit to the left of the legend in a row of their own between the header and the plot. Pure composition — the chart is untouched and the card simply grows by that row.

Curves

Straight joins tell the truth about where the samples are; monotone smooths between them and reads better for a rate. Mix the two only when the series mean genuinely different things.

Line styling

A dashed series against a solid one — the way to separate a threshold or a projection from measured data — and a CSS colour string for a series whose colour is decided elsewhere.

Edge cases

The three shapes that break naive charts: a sparkline with no chrome at all, a single data point, and a series with null gaps, which has to break the line rather than bridge it.

Custom tooltip

Composing the hover popover yourself, a LineChartHoverPopoverRow per series, for when a value needs its unit rather than the default name-and-number.

Legend placements

Legend placement is structural rather than a prop: JSX order picks top or bottom, and wrapping the body and the legend in an HStack picks left or right, where a vertical orientation stacks its rows.

Filterable

Clicking a legend row isolates that series and clicking another adds it back, with the header's clear control appearing while anything is hidden.

Cross chart hover sync

Two cards sharing a pointer, and it takes two mechanisms: syncId lines up the cursor and tooltip through recharts, while activeKey shares the series highlight through our own context.

Zoom

Drag across the plot to choose a range, then confirm in the popover — Enter or the button emits onZoomChange, while Escape, an outside click or a new drag dismisses it. Slicing the data to that range is yours, and so is the way back out.

Loading

There is no loading prop: the state is composed from the same primitives as a populated chart — Skeleton chips inside the legend and a bare LineChartEmpty for the dashed plot — with aria-busy on the Chart left to the caller.

Refreshing

Each panel loads for two seconds before swapping to data, and the refresh button replays it. The skeleton and the real chart share an outer layout, so nothing but the content moves on the swap.

Empty

LineChartEmpty keeps the dashed plot frame and puts the message inside it, so a card with no data still reads as a chart rather than as something broken.

Long time range

A thousand hourly samples in one card: drag to zoom and the header's control restores the full range. The story slices the data itself, exactly as a consumer has to.

Metric

Every brick combination on its own card, mirroring the Figma options board: value alone, value with a delta in each sentiment, and the three MetricTotal connectors: a slash, the word "of", and the word "total" after the number.

Loading

MetricSkeleton in place of the stat while the card loads, so the number arriving does not resize the card.

Sparkline

MetricSparkline after Metric draws the trend over the period, edge to edge along the card's bottom. Hover it for a ruler on the nearest point and a popover with its date and value.

Sparkline colors

The sparkline's color is set per chart, on purpose apart from the delta's sentiment: brand (default), positive, negative, and neutral.

Overview

Default

One card per chart, at its default: a BarList top-five, a PieChart share-of-total, a LineChart over time, a HorizontalBarStack composition and a bare Metric.

PieChart

Default

The interactive shape: click a legend row to filter to that slice, with the header's clear control appearing while the filter holds.

Selectable

Selection kept in state rather than by filtering the data — the chosen row stays lit and the other slices fade, so the whole remains visible while one part is emphasised.

Truncated labels

Legend labels truncate at the row width, since the legend takes whatever horizontal space the donut leaves.

Truncated labels with tooltip

The same rows under OverflowTooltip, which reveals the full label only when it is actually cut off.

Loading

PieChartSkeleton takes a row count so the placeholder legend is as long as the real one, and the card does not resize when data lands.

Single slice

One slice is a full ring at 100% — legible, but ask whether a Metric says it better, since there is no share left to compare against.

Two slices

Two slices is where a donut earns its place: the split is readable at a glance without reading either number.

Custom colors

Colours passed per datum rather than taken from the palette, for a breakdown whose categories already have colours elsewhere in the product.

Zero total

Every value zero: the ring renders empty and the percents read 0% rather than the chart dividing by nothing or disappearing.

Width variants

The same chart at 280, 400 and 560px. The donut holds its size and the legend takes the rest, which is what sets the practical minimum width.

Percent variants

The three percent treatments, matching BarList — split colours number and symbol differently, muted sets both back, inherit leaves them to the row.

Palette

The six chart colours around one ring, for checking adjacent slices stay tellable apart at small sizes.

Props

AreaChartArea

PropTypeDefaultDescription
seriesKey *stringJoins to LineChartSeries.key from the root series prop.
curve"linear" | "monotone" | undefinedmonotoneRecharts curve type. Defaults to 'monotone'.
disableAnimationboolean | undefinedfalseForce-disable the recharts mount animation.
connectNullsboolean | undefinedfalseRecharts pass-through — when true, the area bridges null/undefined gaps.
strokeWidthnumber | undefinedAREA_STROKE_WIDTHStroke width override. Defaults to AREA_STROKE_WIDTH.

AreaChartBody

PropTypeDefaultDescription
heightnumber | undefinedDEFAULT_BODY_HEIGHTBody height passed to recharts' <ResponsiveContainer>.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

AreaChart

PropTypeDefaultDescription
data *T[]Long-form data array, one entry per X position.
series *LineChartSeries<Extract<keyof T, string>>[]Schema describing each area drawn from data.
xKey *Extract<keyof T, string>Key on each datum used as the X-axis value.
variantAreaChartVariant | undefinedArea chart variant. - 'stacked' (default): series stack cumulatively — each band starts where the previous ends. - 'standard': series overlap from the baseline with transparency.
activeKeystring | null | undefinedControlled hover key — pass alongside onActiveKeyChange for cross-chart sync.
onActiveKeyChange((key: string | null) => void) | undefined
filteredKeysstring[] | undefinedControlled set of series.key values to hide from the plot.
onZoomChange((range: LineChartZoomRange | null) => void) | undefinedFired after the user confirms a brush selection.
syncIdstring | number | undefinedCharts that share a syncId synchronise their tooltip cursor.
syncMethodcomplexHow sibling syncId charts match X positions.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

BarListBar

PropTypeDefaultDescription
colorChartColor | undefinedBuilt-in palette fill. Each colour maps to the --color-badge-{color}-light design-system token (dark-mode aware). Pass a Tailwind bg-* utility via className to use any other colour — it wins over the palette class through tailwind-merge.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

BarListItem

PropTypeDefaultDescription
value *number
selectedboolean | undefinedfalseMarks the row as visually active (selected / filtered). Applies the hover background + aria-current. The bar width and percent label are driven purely by value / max — selected never changes the fill.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

BarListLabel

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

BarListPercent

PropTypeDefaultDescription
digitsnumber | undefined0Number of fractional digits. Defaults to 0.
variantBarListPercentVariant | undefinedsplitColor treatment for the value and the % symbol. - split (default, matches Figma) — value uses text-text-primary, symbol uses text-text-secondary. - muted — both tokens use text-text-secondary. - inherit — both tokens inherit the parent's color (e.g. match BarListValue).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

BarList

PropTypeDefaultDescription
max *numberValue at which a bar reaches 100%. Required. - Percent inputs → max={100}. - Fractions → max={1}. - Raw counts → Math.max(...values) or the total. Invalid values (non-finite, zero, negative) render every row empty with a 0% label and log a single dev-only warning.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

BarListSkeleton

PropTypeDefaultDescription
rowsnumber | undefined5Number of skeleton rows to render. Defaults to 5.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

BarListValue

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

ChartActions

PropTypeDefaultDescription
alwaysVisibleboolean | undefinedfalseKeep actions visible regardless of card hover/focus. Defaults to false — the block fades in on card hover/focus-within.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

ChartEmpty

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

ChartHeader

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

Chart

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChartTitle

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

ColumnChartBody

PropTypeDefaultDescription
heightnumber | undefinedFixed plot height in pixels. Leave it unset to follow the card: the plot starts at the Figma 164px (card 220) and grows or shrinks with the <Chart> height, down to a 128px card.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

ColumnChart

PropTypeDefaultDescription
data *T[]One entry per column (step), sorted ascending by xKey.
series *LineChartSeries<Extract<keyof T, string>>[]The categories each column is split into, in legend order — the first one stacks on top. The same schema drives the legend, the parts and the hover popover rows.
xKey *Extract<keyof T, string>Key on each datum used as the X-axis value (the step: a day, an hour, …).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ColumnChartXAxis

PropTypeDefaultDescription
tickFormatter((value: unknown, index: number) => string) | undefinedFormat the rendered tick label. Receives the raw xKey value of the column.
intervalnumber | "preserveStart" | "preserveEnd" | "preserveStartEnd" | undefinedpreserveStartEndRecharts tick interval. Defaults to 'preserveStartEnd': the first and last columns keep their labels and middle ones drop out when the labels would collide. 0 labels every column.
minTickGapnumber | undefinedMinimum gap (in pixels) between rendered tick labels.

HorizontalBarStack

PropTypeDefaultDescription
data *HorizontalBarStackDatum[]Segments + legend. One array drives both, so colors stay in sync.
totalnumber | undefinedBar denominator. > sum(data.value) → grey remainder tail. Default: sum(data.value).
legendboolean | undefinedtrueShow/hide the legend. Default: true.
activeNamestring | null | undefinedControlled hover target, joined by name. Omitted → managed internally. Set together with onActiveNameChange to sync hover across charts (e.g. a sibling highlights the same series). Mirrors PieChart.
onActiveNameChange((name: string | null) => void) | undefined
selectedNamesstring[] | undefinedNames to emphasise. When non-empty, non-selected segments + legend items fade. Hover (activeName) wins — while a series is hovered, only it stays bright. Names not in data are ignored.
onSelect((name: string) => void) | undefinedClick-to-filter. When provided, legend items become interactive (role='button', tabIndex=0, Enter/Space) and fire with the clicked datum's name. The caller owns the filter (typically: drive selectedNames, or filter data).
titlestring | undefined
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

HorizontalBarStackSkeleton

PropTypeDefaultDescription
legendItemsnumber | undefined3Number of legend placeholder pills. Defaults to 3.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

LineChartBody

PropTypeDefaultDescription
heightnumber | undefinedDEFAULT_BODY_HEIGHTBody height passed to recharts' <ResponsiveContainer>. Defaults to the Figma single-line plot height (LINE_CARD_HEIGHT - LINE_HEADER_HEIGHT).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartEmpty

PropTypeDefaultDescription
heightnumber | undefinedDEFAULT_BODY_HEIGHTBody height override. Defaults to the standard plot height.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

LineChartGrid

PropTypeDefaultDescription
verticalboolean | undefinedfalseRender vertical grid lines in addition to the default horizontal ones.
keepTopLineboolean | undefinedfalseKeep the topmost horizontal grid line unconditionally. By default the line is dropped only when it would visually crowd the chart's top edge — see {@link dropEdgeGridLines} for the threshold (Figma "no top x-line" rule).
keepBottomLineboolean | undefinedfalseKeep the bottommost horizontal grid line. By default the line is dropped because the solid <LineChartXAxis> axis line owns the bottom rail — set to true when the X-axis line is hidden and the grid should draw the bottom rail itself.

LineChartHoverPopoverDot

PropTypeDefaultDescription
color(string & {}) | ChartColor | undefinedPalette token or CSS colour. Omitted → no inline fill (lets a className bg win).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartHoverPopover

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartHoverPopoverRow

PropTypeDefaultDescription
series *LineChartSeries<string>Series whose colour and label feed the row.
valuestring | number | null | undefinedRaw datum value at the active index. null/undefined renders an em-dash.
formatValue((value: string | number | null | undefined) => ReactNode) | undefinedOptional value formatter. Defaults to the shared locale formatting.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartHoverPopoverTimestamp

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartLegendItem

PropTypeDefaultDescription
seriesKey *stringJoins to LineChartSeries.key. Drives hover sync, dim, and aria-current.
selectedboolean | undefinedExplicit selection state. When omitted, falls back to "not in filteredKeys". true = row is on (line drawn); false = row is off (line hidden, dimmed). Passing this prop fully overrides the context — useful when the legend renders rows that are not part of the chart's filter set.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartLegend

PropTypeDefaultDescription
orientationLineChartLegendOrientation | undefinedhorizontalHow legend rows lay out inside the legend itself. Defaults to 'horizontal'. Use 'vertical' when the legend sits to the side of the chart (the consumer controls placement by JSX child order or by wrapping body+legend in an <HStack>). Layout-vs-orientation is the only knob the legend exposes.
align"center" | "end" | "start" | undefinedstartCross-axis alignment of the legend rows. Default 'start'.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartLine

PropTypeDefaultDescription
seriesKey *stringJoins to LineChartSeries.key from the root series prop.
curve"linear" | "monotone" | undefinedmonotoneRecharts curve type. Defaults to 'monotone'.
disableAnimationboolean | undefinedfalseForce-disable the recharts mount animation.
connectNullsboolean | undefinedfalseRecharts pass-through — when true, the line bridges null/undefined gaps.
strokeWidthnumber | undefinedLINE_STROKE_WIDTHStroke width override. Defaults to LINE_STROKE_WIDTH.
onClick((event: MouseEvent<SVGPathElement, MouseEvent>) => void) | undefined
onMouseEnter((event: MouseEvent<SVGPathElement, MouseEvent>) => void) | undefined
onMouseLeave((event: MouseEvent<SVGPathElement, MouseEvent>) => void) | undefined

LineChart

PropTypeDefaultDescription
data *T[]Long-form data array, one entry per X position.
series *LineChartSeries<Extract<keyof T, string>>[]Schema describing each line drawn from data.
xKey *Extract<keyof T, string>Key on each datum used as the X-axis value. Required — a silent fallback would hide key-name typos until the chart renders empty.
activeKeystring | null | undefinedControlled hover key — pass alongside onActiveKeyChange for cross-chart sync. Heads-up: if the controlled value points at a series key that no longer exists in series (filter, schema change, refresh), the chart pushes null back through onActiveKeyChange so sibling charts stop highlighting a stale key. If you wire activeKey to external state, the snap-to-null write will arrive as a normal state change — do not be surprised when your value resets after a series disappears.
onActiveKeyChange((key: string | null) => void) | undefined
filteredKeysstring[] | undefinedControlled set of series.key values to hide from the plot.
onZoomChange((range: LineChartZoomRange | null) => void) | undefinedFired after the user confirms a brush selection.
syncIdstring | number | undefinedCharts that share a syncId synchronise their tooltip cursor and brush via recharts' built-in middleware — hovering one chart highlights the matching X on every sibling chart with the same id. Pair with activeKey + onActiveKeyChange if you also want the series highlight to sync.
syncMethodcomplexHow sibling syncId charts match X positions. Defaults to 'index' (Recharts' default). Use 'value' when the synced charts have different dataset lengths but share categorical X values.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

LineChartTooltip

PropTypeDefaultDescription
xTickFormatter((value: unknown) => ReactNode) | undefinedCustom formatter for the default popover timestamp slot.

LineChartXAxis

PropTypeDefaultDescription
tickFormatter((value: unknown, index: number) => string) | undefinedFormat the rendered tick label. Receives the raw datum value at the tick.
densityLineChartXAxisDensity | undefinedCurated tick-spacing preset ('sparse' | 'normal' | 'dense'). Sets minTickGap to 64/32/16px respectively. Explicit minTickGap overrides the preset — reach for that escape hatch when no preset fits.
intervalnumber | "preserveStart" | "preserveEnd" | "preserveStartEnd" | "equidistantPreserveStart" | undefinedpreserveStartEndRecharts tick interval — 0 to render every tick, the literal strings to auto-pick.
tickCountnumber | undefinedRecharts target tick count.
ticksreadonly (string | number)[] | undefinedExplicit tick values. Overrides recharts' generator.
minTickGapnumber | undefinedMinimum gap (in pixels) between rendered tick labels. Overrides density.
domain[string | number, string | number] | undefinedRecharts domain override — ['auto', 'auto'] by default.
padding"gap" | { left?: number | undefined; right?: number | undefined; } | "no-gap" | undefinedPadding between the plot edge and the first/last tick.
type"number" | "category" | undefinedRecharts axis scale type — 'category' (default for line charts) or 'number' for continuous X.
hideTicksboolean | undefinedfalseRender the axis area as a spacer (preserves layout, hides the labels).
axisLineboolean | undefinedtrueRender the solid bottom axis line. Defaults to true — the line owns the bottom rail of the plot (the <LineChartGrid> drops its bottom horizontal grid line to avoid stacking on top of it). Pass false for sparkline-style plots; in that case set <LineChartGrid keepBottomLine /> if a bottom rail is still wanted.

LineChartYAxis

PropTypeDefaultDescription
tickFormatter((value: unknown, index: number) => string) | undefinedFormat the rendered tick label.
tickCountnumber | undefinedRecharts target tick count.
ticksreadonly (string | number)[] | undefinedExplicit tick values. Overrides recharts' generator.
domain[string | number, string | number] | undefinedRecharts domain override.
padding{ top?: number | undefined; bottom?: number | undefined; } | undefinedPadding between the plot edge and the first/last tick.
widthnumber | undefinedLINE_Y_LABEL_WIDTHY-label gutter width. Defaults to the Figma-mandated LINE_Y_LABEL_WIDTH (38px).
hideTicksboolean | undefinedfalseRender the axis area as a spacer (preserves layout, hides the labels).

LineChartZoomBrush

PropTypeDefaultDescription
disabledboolean | undefinedfalseWhen true the zoom interaction is removed entirely.
formatRange((range: LineChartZoomRange) => ReactNode) | undefineddefaultFormatRangeOverride the default range text rendered inside the popover.
confirmLabelReactNodeZoom inOverride the default "Zoom in" label on the confirm button.
containerHTMLElement | null | undefinedPortal target for the floating range/confirm popover. Defaults to document.body. Pass a dialog/modal node to keep the popover inside the focus-trapped subtree — without this the portal escapes the focus context and tabbing from the confirm button lands outside the dialog.

LineChartZoomPopoverConfirm

PropTypeDefaultDescription
disabledboolean | undefined
namestring | undefined
type"button" | "submit" | "reset" | undefinedbutton
valuestring | number | readonly string[] | undefined
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartZoomPopover

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LineChartZoomPopoverRange

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

MetricCaption

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

MetricDelta

PropTypeDefaultDescription
value *numberMagnitude shown in the chip; rendered as Math.abs(value).toLocaleString('en-US').
trendChartDeltaTrend | undefinedArrow direction. Defaults to the sign of value (>= 0 → up).
sentimentChartDeltaSentiment | undefinedColour = meaning, and it is independent of the arrow: positive → green, negative → red, neutral → slate. Defaults to neutral. An increase can therefore read as negative (red ↑) and a decrease as positive (green ↓).

MetricHeader

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

Metric

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

MetricSkeleton

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

MetricSparkline

PropTypeDefaultDescription
data *MetricSparklinePoint[]The trend over the period, oldest first.
colorMetricSparklineColor | undefinedbrandLine colour. Independent of the MetricDelta sentiment — set both. brand (default) · positive (success) · negative (danger) · neutral (slate).
labelReactNodeSeries name on the hover popover row (Figma "Attribute").
formatX((x: string | number | Date) => ReactNode) | undefinedFormats the hovered point's x for the popover. Defaults to 1 Jan, 2026 for dates.
formatValue((value: number) => ReactNode) | undefinedFormats the hovered value. Defaults to toLocaleString('en-US').
titlestring | undefined
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

MetricTotal

PropTypeDefaultDescription
connectorMetricTotalConnector | undefinedslashHow the denominator reads: /120 (slash) · of 120 (of) · 120 total (total).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

MetricValue

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

LegendDot

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartCenterLabel

PropTypeDefaultDescription
hoverSyncboolean | undefinedtrueWhen true (default), the label tracks the hovered slice/legend row — so a pluralize rules object picks the form for the hovered datum's value rather than the chart total. Has no effect when pluralize is omitted.
pluralizePieChartCenterLabelPluralRules | undefinedOptional pluralization rules. When provided, the label content is selected from the rules using Intl.PluralRules for the currently visible count (the hovered datum's value when hoverSync is on, otherwise the chart total). When omitted, children renders unchanged.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartCenter

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartCenterValue

PropTypeDefaultDescription
hoverSyncboolean | undefinedtrueWhen true (default), hovering a slice or legend row replaces children with the hovered datum's value (formatted via formatHoveredValue). Set to false to keep children visible regardless of hover state — useful when the centre value should always reflect the unfiltered total.
formatHoveredValue((datum: PieChartDatum) => ReactNode) | undefineddefaultFormatHoveredValueFormatter applied to the hovered datum when hoverSync is enabled. Defaults to datum.value.toLocaleString(). Pass a custom formatter to keep the hover format aligned with whatever formatter produced children (e.g. compact notation, units).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartDonut

PropTypeDefaultDescription
inactiveOpacitynumber | undefined0.3Opacity applied to slices that are not currently hovered. Defaults to 0.3. Set to 1 to disable the hover-dim effect.
disableAnimationboolean | undefinedfalseDisable the recharts mount/transition animation. Defaults to false. Set true in test/screenshot environments where deterministic frames matter.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartLegendItem

PropTypeDefaultDescription
name *stringIdentifier matching a PieChartDatum.name from the root data prop. Drives both the percent calculation and the bidirectional hover sync with the donut slice.
valuenumber | undefinedOptional override for the value used in the percent calculation. Defaults to looking the value up from the root data array by name. Pass an explicit value when the legend renders entries that are not part of the donut (e.g. a synthetic "Other" row).
selectedboolean | undefinedVisually marks the row as the selected/filtered datum — applies bg-states-primary-active and aria-current. When omitted, the row falls back to membership in the root's selectedNames set (if provided). When passed explicitly (true or false) it fully overrides the context — useful when the legend renders rows that aren't part of the chart's multi-selection (e.g. a single filtered view). The resolved value also feeds the dim calculation: a row resolved to selected=false while some peer is selected will fade like any other non-selected row.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartLegendPercent

PropTypeDefaultDescription
digitsnumber | undefined0Number of fractional digits in the percent label. Defaults to 0.
variantPieChartLegendPercentVariant | undefinedsplitColor treatment for the value and the % symbol. Mirrors BarListPercent. - split (default, matches Figma) — value uses text-text-primary, symbol uses text-text-secondary. - muted — both tokens use text-text-secondary. - inherit — both inherit the parent's color (e.g. follow PieChartLegendValue).
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartLegend

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChartLegendValue

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined

PieChart

PropTypeDefaultDescription
data *PieChartDatum[]Each datum's name is the join key used by PieChartLegendItem to sync hover/active state. Non-finite or negative values are coerced to 0 so recharts can draw them.
totalnumber | undefinedOverride for the value used to compute percentages and the centre total. Defaults to sum(data.value). Pass an explicit value when the centre label should reflect a different denominator — e.g. the unfiltered total while the chart shows a filtered view.
activeNamestring | null | undefinedControlled active slice. When provided, the component does not manage hover state internally — the parent must update it via onActiveNameChange.
onActiveNameChange((name: string | null) => void) | undefined
selectedNamesstring[] | undefinedMulti-selection set. When non-empty, donut slices and legend rows whose name is not in the set fade so emphasis lands on the chosen group. Hover (activeName) wins — while the user points at a specific slice, only that one stays bright. Names not present in data are ignored. Pass a stable reference (useMemo/state) — an inline array literal recreates on every parent render and invalidates the internal Set memo.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

PieChartSkeleton

PropTypeDefaultDescription
rowsnumber | undefined5Number of skeleton rows in the legend column. Defaults to 5.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

Explorer