Components
Compare totals while keeping the composition of each category visible. Positive and negative contributions share a clear zero baseline.
npx mario-charts@latest add stacked-bar-chartExplore orientations, signed contributions, and segment inspection.
The same chart through every state.
Illustrative quarterly observations · thousands
Waiting for chart space
Hover or tap a segment to inspect. Left/Right changes quarter; Up/Down changes device. Enter selects.
import { StackedBarChart } from "@/components/charts/stacked-bar-chart";
const data = [
{ quarter: "Q1", desktop: 120, mobile: 80, tablet: 30 },
{ quarter: "Q2", desktop: 150, mobile: 95, tablet: 40 },
{ quarter: "Q3", desktop: 130, mobile: 110, tablet: 35 },
{ quarter: "Q4", desktop: 170, mobile: 125, tablet: 45 },
];
export function Traffic() {
return <StackedBarChart data={data} x="quarter"
y={["desktop", "mobile", "tablet"]} showLegend showGrid height={400}
ariaLabel="Traffic by device" valueFormatter={value => value + "k"} />;
}All categories use one numeric scale. Positive values stack away from zero in one direction, negative values in the other. A net total of zero can still contain substantial positive and negative contributions; inspection shows both subtotals.
Segments need comparable units. Stacked bars make totals and the first segment easiest to compare; use separate bars when comparing every series is the main question.
Zero is a measured value with no painted length. It remains reachable by keyboard and in the accessible source table. Missing values produce an error so incomplete observations cannot look like measured zeros.
Keep data while loading to preserve geometry. Long category labels are shortened visually and dense labels are thinned; full labels and every segment remain available through inspection and the source table.
Typed props for stacked values, appearance, and interaction.
| Prop | Type | Default | Description |
|---|---|---|---|
dataRequired | readonly T[] | — | Rows in input order. Segment values must be finite numbers or unambiguous numeric strings. Missing values produce an error. |
xRequired | keyof T | — | Category key. Duplicate labels remain distinct observations. |
yRequired | readonly (keyof T)[] | — | One or more unique numeric keys in stack, legend, and keyboard order. Positive and negative values accumulate independently from zero. |
orientation | 'vertical' | 'horizontal' | 'vertical' | Orient the same signed stacks and zero baseline. |
variant | 'filled' | 'outline' | 'filled' | Filled segments or colored outlines. Both variants support segment inspection and actions. |
cornerRadius | number | 2 | Outer-end radius in pixels, capped by segment dimensions. Internal joins stay flat. Use 0 for square ends. |
showLegend | boolean | false | Show series colors within the total frame height. |
showGrid | boolean | false | Show grid lines on the shared numeric scale. |
gridStyle | 'solid' | 'dashed' | 'dotted' | 'dashed' | Grid line style. |
height | number | 300 | Positive total frame height, including the legend, in every state. |
loading | boolean | false | Retain rows to preserve the exact segment geometry during refresh. Without data, show a neutral placeholder. |
error | string | null | null | Actionable error inside the persistent chart frame. |
animation | boolean | true | Grow stacks from zero while preserving segment joins. Grid and labels stay still. Keyboard focus completes entrance; reduced motion is respected. |
valueFormatter | (value: number) => string | formatValue | Format segment inspection, accessible values, and signed totals. Include shared units when helpful. |
axisValueFormatter | (value: number) => string | valueFormatter | Optional compact numeric tick format. |
onSegmentClick | (data: T, stackKey: string, index: number) => void | — | Receive the original row, selected key, and row index through pointer or Enter/Space activation. |
tooltipRenderer | TooltipRenderer<StackedBarChartTooltipData<T>> | — | Original data, label, index, all segments, activeKey/activeIndex, positiveTotal, negativeTotal, and total (signed net). |
ariaLabel / description | string | 'Stacked bar chart' / undefined | Accessible chart name and context. Keyboard instructions and a source-value table are included. |
colors | readonly string[] | DEFAULT_COLORS | Colors follow y-key order, including zero-valued segments. |
className | string | — | Classes for the persistent outer frame. |