# Diagram

A diagram an agent wrote as Mermaid: a product's data model (objects and their relationships), a flow, a sequence. Mermaid loads on first use, renders in strict mode (no scripts or HTML from the source), and takes its colours from the theme, redrawing when the theme changes. Source that won't parse shows the parser's message and the source, never a blank box.

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

## Install

```bash
npx candor-ui add diagram
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/diagram`.
It brings in: degraded-panel, locale, payload, skeleton, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { Diagram } from "@/components/diagram"

const source = `erDiagram
  customers ||--o{ invoices : "is billed"
  customers }o--|| regions : "is routed to"
  invoices ||--|{ invoice_lines : contains`

export default function Example() {
  return <Diagram className="max-w-xl" title="Billing data model" caption="Tables Keel read from the Staging schema and how they relate." source={source} />
}
```

## <Diagram>

Props:

- `source: string`: The Mermaid source.
- `title: string`: Heading above the diagram, also its accessible name.
- `caption?: string | undefined`: A line under the title saying what the diagram shows.
- `className?: string | undefined`

## Strings (`diagram`)

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

- `source`: Source
- `invalid`: The source isn’t valid Mermaid.
- `failed`: Couldn’t draw this diagram: {message}
- `missing`: The picture; the source is below

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