Spend breakdown

Pro

AI spend over time, split by model, agent or feature. Six series at most; the rest fold into "Other". The split can change without repainting the survivors' colours, because colour follows the entity, not its rank. The total is to the cent. A period whose spend isn't known stays unknown: it's left out of the total, and the total says so. totalText shows your server's own total as written instead.

Markdown

Preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/spend-breakdown

Brings in: bar-chart, locale, ops, utils

Usage

TSX · The example above
"use client"

import { SpendBreakdown } from "@/components/spend-breakdown"
import type { SpendRow } from "@/lib/ops"

const weeks = ["Oct 6", "Oct 13", "Oct 20", "Oct 27", "Nov 3"]

const byModel: SpendRow[] = [
  { key: "opus", label: "Claude Opus 5.5", values: [62, 71, 58, 84, 90] },
  { key: "sonnet", label: "Claude Sonnet 5.5", values: [41, 44, 52, 49, 57] },
  { key: "haiku", label: "Claude Haiku 5.5", values: [4, 5, 5, 6, 6] },
]

const byAgent: SpendRow[] = [
  { key: "keel", label: "Keel", values: [24, 26, 22, 31, 33] },
  { key: "dev", label: "Dev agent", values: [55, 63, 61, 72, 80] },
  { key: "qa", label: "QA agent", values: [28, 31, null, 36, 40] },
]

export default function Example() {
  return <SpendBreakdown className="max-w-2xl" periods={weeks} by={{ model: byModel, agent: byAgent }} />
}

<SpendBreakdown>

PropTypeDefaultDescription
periodsrequiredstring[]—The time periods along the x-axis, e.g. months, oldest first.
byrequiredPartial<Record<SpendSplit, SpendRow[]>>—Rows per split; each row's values align with `periods` (null when that period isn't known).
splitsSpendSplit[] | undefined—Which splits to offer, in order, e.g. without one that has a single row. Defaults to every split in `by`. With one, there's no switch.
totalTextstring | undefined—The total as your server wrote it ("about $1,240"), shown instead of summing the known values.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under spendBreakdown in <LocaleProvider strings={{ … }}>; the table is exported as spendBreakdownStrings.

KeyEnglish
splitBySplit by
byModelBy model
byAgentBy agent
byFeatureBy feature
totalTotal
unknownUnknown
someUnknownknown; some periods aren’t
otherOther
spendAI spend
spendByModelAI spend by model
spendByAgentAI spend by agent
spendByFeatureAI spend by feature
perWeekPer week, USD

Types

SpendSplit
"model" | "agent" | "feature"