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
Operating profit£150,000Margin25%
"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

PropTypeDefaultDescription
dataStackedBarSegment[]Required. Segments in display order. Pass a stable reference.
trailingReact.ReactNodeOptional info at the right of the footer row (e.g. totals).
heightnumber32Bar height in px.
showLegendbooleantrueRender the legend beneath the bar.
tooltipDelayDurationnumber300Tooltip open delay in ms.
labelstringAccessible label summarising the bar (sets role="img").
classNamestringSizing / spacing hook.

StackedBarSegment

FieldTypeDefaultDescription
labelstringRequired. Legend + tooltip label.
valuenumberRequired. Drives the segment width (value / total). Int or float.
valueLabelstringString(value)Formatted value for the legend + tooltip.
barLabelstringText rendered inside the segment; auto-hidden when too narrow.
colorstringvar(--chart-{n})Segment fill — any CSS colour or token var.
pattern"solid" | "hatched""solid""hatched" overlays a diagonal stripe texture on the fill.
keystringlabelStable React key.

On this page