affectUI › Components › Data display

Compact Breakdown

A total split into its parts in one small card – numbers roll, the bar glides and the ranked rows trade places when the period changes.

Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/compact-breakdown.json · Import from @/components/ui/compact-breakdown

When to use

  • One number and what it is made of – revenue by channel, usage by feature, tokens by model, tickets by category
  • Dashboards where the card sits next to others and a full chart would be too much
  • Whenever people switch between periods and should see what moved

When not to use

  • Trends over time – a line chart shows those; this card compares the parts of one total
  • More than about seven parts – group the small ones into "Other" first
  • Several measures and slicing options – use Breakdown Chart

Usage

import { CompactBreakdown } from "@/components/ui/compact-breakdown";

export function RevenueByChannel() {
  const [period, setPeriod] = useState("30d");
  const { items, delta } = useRevenue(period); // [{ label: "Direct", value: 16900 }, …]
  return (
    <CompactBreakdown
      title="Revenue by channel"
      periods={[
        { id: "7d", label: "7d" },
        { id: "30d", label: "30d" },
        { id: "90d", label: "90d" },
      ]}
      period={period}
      onPeriodChange={setPeriod}
      items={items}
      delta={delta}
      format={(n) => `$${Math.round(n).toLocaleString("en-US")}`}
      totalLabel="Total revenue"
    />
  );
}

Props

NameTypeDefaultDescription
itemsBreakdownItem[]{ id?, label, value, color? } – the parts of the shown period; the list ranks them by value. Give an id when labels can change
titlestring"Breakdown"Heading of the card
periods{ id: string; label: string }[]Options of the period switch – no switch when left out
periodstringControlled period id
defaultPeriodstringfirst periodStarting period when uncontrolled
onPeriodChange(id: string) => voidCalled with the new period – pass the matching items and delta back in
deltanumberChange against the previous period in percent (12.4 or -3) – a small green or red pill next to the total
format(value: number) => stringwhole numbers with separatorsFormats every value – the total, the rows and the hovered part
totalLabelstring"Total"Line under the big number while nothing is hovered
footerReactNode | null"Largest: <part>"Replaces the line on the gray tray; null hides it
classNamestringExtra class on the root

Keyboard

  • Tab: Moves to the period switch, then through the rows – a focused row is highlighted like a hovered one
  • ← / →: In the period switch: previous or next period (wraps around)
  • Home / End: In the period switch: first or last period

Accessibility

  • A group named by its title; the period switch is a radiogroup with one tab stop
  • The rolling numbers are aria-hidden – screen readers get the final total and the change in one sentence, and every row with its value and share
  • Rows can be focused, so the highlight and the part's value are reachable without a mouse
  • The bar is decorative: everything it shows is in the list

Responsive

  • Fills its container up to 360px; below 250px the share column goes and the values stay
  • Touch screens: taller rows and period options
  • Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"

Requirements

  • React 19

Related

  • Usage Meter – Plan usage and AI credits – a stacked credits meter by category, daily sparkline, limits and a button that speaks up near the limit
  • Breakdown Chart – Stacked bar chart with measure, slice and segment pickers, a hover breakdown and a linked table
  • KPI Chart – Metric card with a multi-line chart and a tooltip that follows the pointer

Guides