Stacked Bar
A single horizontal stacked bar that splits a whole into proportional, labelled segments.
- To the household£72,430
- Tax£28,225
- Retained in business£49,345
"use client";import { StackedBar, Text } from "@reva/ui";const data = [{ label: "To the household", value: 72430, valueLabel: "£72,430", barLabel: "£72k" },{ label: "Tax", value: 28225, valueLabel: "£28,225", barLabel: "£28k" },{ label: "Retained in business", value: 49345, valueLabel: "£49,345", barLabel: "£49k" },];export function StackedBarHeroDemo() {return ( <StackedBar data={data} label="Operating profit allocation" trailing={ <> <span className="flex items-center gap-1"> <Text as="span" size="xs" weight="medium" color="muted-foreground">Operating profit</Text> <Text as="span" size="xs" weight="medium">£150,000</Text> </span> <span className="flex items-center gap-1"> <Text as="span" size="xs" weight="medium" color="muted-foreground">Margin</Text> <Text as="span" size="xs" weight="medium">25%</Text> </span> </> } />);}Usage
import { StackedBar } from "@reva/ui";
<StackedBar
data={[
{ label: "To the household", value: 72430, valueLabel: "£72,430", barLabel: "£72k" },
{ label: "Tax", value: 28225, valueLabel: "£28,225", barLabel: "£28k" },
{ label: "Retained in business", value: 49345, valueLabel: "£49,345", barLabel: "£49k" },
]}
/>A single horizontal stacked (100%) bar — proportional segments that sum to a whole — with a static legend beneath and optional trailing totals on the right. Each segment width is value-driven (value / total, so values can be integers or floats), and colours fall back to the categorical --chart-1..7 ramp by index. It is pure flexbox — no plotting library — so it fills its container's width.
Hover for the full figure
Each segment is a delayed tooltip trigger that repeats its label and value — handy when an in-bar label is abbreviated (or dropped) but you still want the precise number on hover.
Examples
Auto-fitting bar labels
barLabel renders inside a segment, but is hidden automatically when the segment is too narrow to hold it — so a thin sliver never shows clipped text. The full label and value stay available in the legend and on hover. Resize the preview to watch labels drop in and out.
- Documents62 GB
- Media30 GB
- Apps6 GB
- System2 GB
const data = [{ label: "Documents", value: 62, valueLabel: "62 GB", barLabel: "62 GB" },{ label: "Media", value: 30, valueLabel: "30 GB", barLabel: "30 GB" },{ label: "Apps", value: 6, valueLabel: "6 GB", barLabel: "6 GB" },{ label: "System", value: 2, valueLabel: "2 GB", barLabel: "2 GB" },];<StackedBar data={data} label="Disk usage by category" />Custom colours
Set color per segment to any CSS colour or token var — here the chart role tokens (--chart-positive-fill, --chart-neutral-fill, --chart-accent-fill) carry meaning. Omit color to fall back to the categorical ramp.
- Equities55%
- Bonds30%
- Cash15%
const data = [{ label: "Equities", value: 55, valueLabel: "55%", barLabel: "55%", color: "var(--chart-positive-fill)" },{ label: "Bonds", value: 30, valueLabel: "30%", barLabel: "30%", color: "var(--chart-neutral-fill)" },{ label: "Cash", value: 15, valueLabel: "15%", barLabel: "15%", color: "var(--chart-accent-fill)" },];<StackedBar data={data} label="Portfolio allocation" />Hatched segments
Set pattern: "hatched" on a segment to overlay a diagonal stripe texture on its fill — a segment being given up or subtracted (a mortgage against an asset total), distinct from the plain solid segments beside it.
- Net worth£1.1m
- Mortgage£430k
- Tax reserved£70k
const data = [{ label: "Net worth", value: 1_100_000, valueLabel: "£1.1m", barLabel: "Net worth · £1.1m", color: "var(--chart-primary-fill)" },{ label: "Mortgage", value: 430_000, valueLabel: "£430k", color: "var(--chart-negative-fill)", pattern: "hatched" },{ label: "Tax reserved", value: 70_000, valueLabel: "£70k", color: "var(--chart-negative-projected)" },];<StackedBar data={data} label="Net worth after liabilities" />Props
StackedBar
| Prop | Type | Default | Description |
|---|---|---|---|
data | StackedBarSegment[] | — | Required. Segments in display order. Pass a stable reference. |
trailing | React.ReactNode | — | Optional info at the right of the footer row (e.g. totals). |
height | number | 32 | Bar height in px. |
showLegend | boolean | true | Render the legend beneath the bar. |
tooltipDelayDuration | number | 300 | Tooltip open delay in ms. |
label | string | — | Accessible label summarising the bar (sets role="img"). |
className | string | — | Sizing / spacing hook. |
StackedBarSegment
| Field | Type | Default | Description |
|---|---|---|---|
label | string | — | Required. Legend + tooltip label. |
value | number | — | Required. Drives the segment width (value / total). Int or float. |
valueLabel | string | String(value) | Formatted value for the legend + tooltip. |
barLabel | string | — | Text rendered inside the segment; auto-hidden when too narrow. |
color | string | var(--chart-{n}) | Segment fill — any CSS colour or token var. |
pattern | "solid" | "hatched" | "solid" | "hatched" overlays a diagonal stripe texture on the fill. |
key | string | label | Stable React key. |