# Heatmap

Intensity over a grid (field fill rate by object, runs by hour and day). One hue, light to dark. A missing cell is hatched and says "No data" — it's never painted as the lowest value. A legend shows the scale's ends.

- Registry name: `heatmap` (`@candor/heatmap`)
- 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/heatmap

## Install

```bash
npx candor-ui add heatmap
```

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

## Example

```tsx
"use client"

import { Heatmap } from "@/components/heatmap"

const tables = ["users", "projects", "deployments", "invoices", "audit_log"]
const columns = ["owner_id", "region", "plan", "created_by", "archived_at"]

// Share of rows with a value; null where Keel couldn't read the column.
const fillRate: (number | null)[][] = [
  [1, 0.97, 0.88, 0.92, 0.04],
  [1, 0.91, null, 0.99, 0.12],
  [0.99, 1, null, 1, null],
  [1, 0.86, 0.95, 0.71, 0.02],
  [null, 0.64, null, 1, null],
]

export default function Example() {
  return <Heatmap className="max-w-xl" title="Fill rate by table and column" subtitle="Production · last 90 days" rows={tables} columns={columns} values={fillRate} format="percent" />
}
```

## <Heatmap>

Props:

- `title: string`: What the chart shows, above it.
- `subtitle?: string | undefined`: A line under the title, e.g. the period or unit.
- `rows: string[]`: The row labels, top to bottom.
- `columns: string[]`: The column labels, left to right.
- `values: (number | null)[][]`: values[row][column]; null = no data.
- `format?: ValueFormat | undefined` (default `"number"`): How values are written: number, percent (0–1), currency (USD) or duration (seconds). Defaults to number.
- `state?: ChartState | undefined`: Loading, empty, partial or error. Defaults to partial when any cell is null, else ready.
- `className?: string | undefined`

## Strings (`heatmap`)

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

- `heatmap`: Heatmap
- `missing`: { one: "{count} cell has no data (hatched).", other: "{count} cells have no data (hatched)." }
- `noData`: No data
- `noDataInline`: no data
- `cell`: {row}, {column}: {value}

## 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`.
