# Chart Artifact

Chart Artifact [#chart-artifact]

The **Chart Artifact** is a client-side data-viz chart rendered from **local** data. It supports six types — `line`, `bar`, `area`, `scatter`, `radar`, `gauge` — and targets genuinely on-device metrics:

* **radar** — evaluation curves: precision / recall / F1 / accuracy from [`useEvaluateModel()`](https://localmode.dev/docs/react).
* **scatter** — 2D embedding projections (PCA / UMAP).
* **line / area** — drift-over-time ([`useReindex()`](https://localmode.dev/docs/react)), latency / tok-s trends.
* **bar** — embedding-similarity distributions, per-class counts.
* **gauge** — a single normalized score (e.g. overall F1).

It is **not** a generic BI widget — its value is visualizing what runs in the browser. The renderer is a **minimal, dependency-free inline SVG** (no charting library), so the copied component stays small and tree-shakeable. Colors come from `currentColor` + shadcn/ui tokens, so charts inherit your theme.

**Local content only.** No server, no sandbox — you pass in local numbers and it draws them.

Preview [#preview]

```tsx
'use client';

/**
 * @file chart-artifact-demo.tsx
 * @description Demo for ChartArtifact, used by the docs live preview. Shows a
 * radar of precision/recall/F1 (the canonical `useEvaluateModel` output) and a
 * scatter of a 2D embedding projection — both rendered from local data, no
 * model download required for the preview.
 */

import { ChartArtifact } from '@/components/chart-artifact';

/** Stand-in for a real `evaluateModel()` result (precision/recall/F1). */
const EVAL = [
  { label: 'Precision', value: 0.91 },
  { label: 'Recall', value: 0.84 },
  { label: 'F1', value: 0.87 },
  { label: 'Accuracy', value: 0.89 },
];

/** Stand-in for a 2D embedding projection (PCA/UMAP scatter). */
const PROJECTION = [
  { x: -1.2, y: 0.8 },
  { x: -0.9, y: 1.1 },
  { x: 0.4, y: -0.6 },
  { x: 0.7, y: -0.9 },
  { x: 1.4, y: 0.2 },
  { x: -0.3, y: -1.3 },
];

export default function ChartArtifactDemo() {
  return (
    <div className="grid gap-4 sm:grid-cols-2">
      <ChartArtifact type="radar" title="Eval (P / R / F1)" data={EVAL} />
      <ChartArtifact
        type="scatter"
        title="Embedding projection (2D)"
        data={PROJECTION}
      />
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/artifacts/chart-artifact
```

Dependencies [#dependencies]

* **Data source:** draws the `ChartPoint[]` you pass — works with any backend (any in-memory numbers). Recommended LocalMode producers: `useEvaluateModel()` / `useReindex()` from `@localmode/react` for eval curves and drift series (optional).
* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

> No charting library is installed — the chart is rendered with inline SVG.

Files installed [#files-installed]

* `chart-artifact.tsx` — the component
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**ChartArtifact**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `type` | `ChartType` | — | **Required.** Chart kind. |
| `data` | `array` | — | **Required.** Data points. Shape requirements vary by `type` (see each field's docs). |
| `width` | `number` | `360` | Drawing width in px. |
| `height` | `number` | `220` | Drawing height in px. |
| `max` | `number` | — | For `gauge`: the maximum value (the dial's full-scale). Defaults to the single data point's `value` if ≤ 1 then 1, else the value itself. |
| `title` | `string` | — | Accessible label / title for the chart region. |

ChartPoint [#chartpoint]

**ChartPoint**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `x` | `number` | — | Numeric x value (line/area/scatter). |
| `y` | `number` | — | Numeric y/value. |
| `label` | `string` | — | Category label (bar/radar axes). |
| `value` | `number` | — | Numeric value (bar/radar/gauge). |

Examples [#examples]

Radar of precision / recall / F1 (from `useEvaluateModel`) [#radar-of-precision--recall--f1-from-useevaluatemodel]

```tsx
import { useEvaluateModel } from '@localmode/react';
import { ChartArtifact } from '@/components/artifacts/chart-artifact';

export function EvalRadar({ result }) {
  // result is a real evaluateModel() output
  const data = [
    { label: 'Precision', value: result.metrics.precision },
    { label: 'Recall', value: result.metrics.recall },
    { label: 'F1', value: result.metrics.f1 },
  ];
  return <ChartArtifact type="radar" title="Eval (P / R / F1)" data={data} />;
}
```

Scatter of a 2D embedding projection [#scatter-of-a-2d-embedding-projection]

```tsx
// projection = real local embeddings reduced to 2D (PCA / UMAP)
<ChartArtifact
  type="scatter"
  title="Embedding projection"
  data={projection.map(([x, y]) => ({ x, y }))}
/>
```

Line / area for drift or latency [#line--area-for-drift-or-latency]

```tsx
<ChartArtifact type="area" data={driftOverTime.map((d, i) => ({ x: i, y: d }))} />
```

Gauge for a single score [#gauge-for-a-single-score]

```tsx
<ChartArtifact type="gauge" data={[{ value: 0.87 }]} />
```

Data shapes by type [#data-shapes-by-type]

| Type                        | Expected `ChartPoint` fields                         |
| --------------------------- | ---------------------------------------------------- |
| `line` / `area` / `scatter` | `{ x, y }`                                           |
| `bar`                       | `{ label, value }`                                   |
| `radar`                     | `{ label, value }` (values typically 0–1)            |
| `gauge`                     | a single `{ value }` (0–`max`, default full-scale 1) |

Local-first boundary [#local-first-boundary]

This is a **local** chart. It draws numbers your app computed on-device (evaluation metrics, embedding projections, drift, latency). It makes no network requests and pulls in no charting dependency.

Customization [#customization]

The chart uses `currentColor` for the series (defaults to `text-primary`) and shadcn/ui token classes for grid/axis text, so it inherits your theme. Because you own the file, restyle the series color, adjust `width` / `height`, add tooltips, or render the chart inside an [`Artifact`](/docs/artifacts/artifact) canvas.