7

Proportion Bar

PreviousNext

Share-of-total bar with rounded segments, textures and a legend carrying each share.

  • Needs45 %
  • Transportation20 %
  • Entertainment10 %
"use client"

import { ProportionBar } from "@/components/ui/charts"

// Shares of income, so the track is a full 100 and the gap is what is left.
const breakdown = [
  { label: "Needs", value: 45, color: "var(--chart-series-1)" },
  { label: "Transportation", value: 20, color: "var(--chart-series-5)" },
  { label: "Entertainment", value: 10, color: "var(--chart-series-2)" },
]

export function ProportionBarDemo() {
  return (
    <ProportionBar
      className="max-w-sm"
      data={breakdown}
      total={100}
      height={32}
    />
  )
}

About

A Proportion Bar shows how one total divides into parts, along a single track. Reach for it over a pie or donut whenever the parts are few and the reader needs to compare shares rather than admire angles — and pass a total larger than the sum when the headroom left over is the point (budget remaining, quota unused).

It renders as CSS rather than SVG: the whole mark is rectangles, so there is nothing an <svg> would buy.

Installation

pnpm dlx shadcn@latest add https://ui.simplifyingai.com/r/proportion-bar.json

Usage

import { ProportionBar } from "@/components/ui/charts"
<ProportionBar
  data={[
    { label: "Needs", value: 45 },
    { label: "Transportation", value: 20 },
    { label: "Entertainment", value: 10 },
  ]}
  total={100}
/>

API Reference

PropTypeDefaultDescription
dataProportionSegment[]—{ label, value, color?, pattern? } per segment.
totalnumbersum of valueDenominator. Larger than the sum leaves a visible remainder.
heightnumber28Track height in px.
gapnumber6Space between segments in px.
radiusnumberheight / 2Corner radius. Defaults to a full pill.
showTrackbooleantruePaint the unfilled remainder.
trackColorstringvar(--muted)Colour of that remainder.
patternChartPatternKindthemeTexture over every segment.
showLegendbooleantrueRender the label/share rows.
legendValue"percent" | "value" | "none""percent"What the legend prints on the right.
valueFormatter(value: number) => stringtoLocaleStringFormats raw values.