Bullet bar

Pro

Actual against a target in one row (coverage against the 75% production needs, adoption against a goal). Background bands mark the thresholds, darkest at the worst end: the start when higher is better, the end when lower is. The bar is the actual; a tick is the target. A missing actual says so instead of drawing an empty bar.

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/bullet-bar

Brings in: data, locale, scale, utils

Usage

TSX · The example above
"use client"

import { BulletBar } from "@/components/bullet-bar"

export default function Example() {
  return (
    <div className="flex max-w-md flex-col gap-4 rounded-xl border bg-card p-4">
      <BulletBar label="Test coverage, api" actual={0.81} target={0.75} max={1} bands={[0.6, 0.75]} format="percent" />
      <BulletBar label="Changed files covered" actual={0.68} target={0.85} max={1} bands={[0.6, 0.85]} format="percent" />
      <BulletBar label="Failed deploys this month" actual={2} target={3} max={10} bands={[6, 3]} higherIsBetter={false} />
      <BulletBar label="Flags cleaned up" actual={null} target={20} max={40} />
    </div>
  )
}

<BulletBar>

PropTypeDefaultDescription
labelrequiredstring—What's measured, e.g. "Test coverage".
actualrequirednumber | null—The measured value. null means not measured, and says so.
targetrequirednumber—The goal, drawn as a tick.
maxrequirednumber—The value at the bar's right end.
bandsnumber[] | undefined—Thresholds from worst to best, e.g. [0.6, 0.75] on a 0–1 scale, or [0.1, 0.05] for an error rate. The worst end is shaded darkest.
formatValueFormat | undefined"number"How values are written: number, percent (0–1), currency (USD) or duration (seconds). Defaults to number.
higherIsBetterboolean | undefinedtrueWhether meeting the target means at or above it. Set false when lower is better, e.g. error rate. Defaults to true.
classNamestring | undefined—Extra classes for the outer element.

Strings

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

KeyEnglish
notMeasuredNot measured
notMeasuredInlinenot measured
target/ {target} target
summary{label}: {actual}, target {target}