# Bullet bar

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.

- Registry name: `bullet-bar` (`@candor/bullet-bar`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/bullet-bar

## Install

```bash
npx candor-ui add bullet-bar
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/bullet-bar`.
It brings in: data, locale, scale, utils.

## Example

```tsx
"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>

Props:

- `label: string`: What's measured, e.g. "Test coverage".
- `actual: number | null`: The measured value. null means not measured, and says so.
- `target: number`: The goal, drawn as a tick.
- `max: number`: The value at the bar's right end.
- `bands?: number[] | 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.
- `format?: ValueFormat | undefined` (default `"number"`): How values are written: number, percent (0–1), currency (USD) or duration (seconds). Defaults to number.
- `higherIsBetter?: boolean | undefined` (default `true`): Whether meeting the target means at or above it. Set false when lower is better, e.g. error rate. Defaults to true.
- `className?: string | undefined`

## Strings (`bulletBar`)

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

- `notMeasured`: Not measured
- `notMeasuredInline`: not measured
- `target`: / {target} target
- `summary`: {label}: {actual}, target {target}

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
