# Evaluation Metrics Dashboard

Evaluation Metrics Dashboard [#evaluation-metrics-dashboard]

The **Evaluation Metrics Dashboard** composes the displays that co-occur in a model-evaluation flow: a labeled KPI/stat-tile row (value + delta indicator), a responsive grid of metric cards (accuracy / precision / recall / F1), a color-coded N×N confusion matrix (diagonal success-tinted, off-diagonal error-tinted, intensity scaled to the max cell, with legend), a radar/spider sub-view, and a threshold-calibration panel. Every chart is a minimal in-component SVG implementation — no external chart library.

**When to use it:** rendering the output of `useEvaluateModel` together with `useCalibrateThreshold`. Each section is optional; pass only the data you have.

Preview [#preview]

```tsx
'use client';

import { EvaluationMetricsDashboard } from '@/components/evaluation-metrics-dashboard';

/**
 * Demo for the EvaluationMetricsDashboard component, used by the docs live
 * preview. Renders a full evaluation run (stats + metrics + confusion matrix +
 * radar + calibration) from sample data. Fully local.
 */
export default function EvaluationMetricsDashboardDemo() {
  return (
    <EvaluationMetricsDashboard
      stats={[
        { label: 'Dataset size', value: 200 },
        { label: 'Duration', value: '1.24s' },
        { label: 'Accuracy', value: '91.0%', delta: 2.4, deltaUnit: 'pts' },
        { label: 'Errors', value: 18, delta: -5, deltaUnit: '' },
      ]}
      metrics={[
        { label: 'Accuracy', value: 0.91 },
        { label: 'Precision', value: 0.89 },
        { label: 'Recall', value: 0.86 },
        { label: 'F1', value: 0.875 },
      ]}
      confusionMatrix={{
        labels: ['positive', 'neutral', 'negative'],
        matrix: [
          [58, 4, 2],
          [6, 49, 5],
          [1, 7, 62],
        ],
      }}
      calibration={{
        threshold: 0.624,
        percentile: 90,
        presetThreshold: 0.5,
        distribution: {
          mean: 0.41,
          median: 0.39,
          stdDev: 0.18,
          min: 0.02,
          max: 0.97,
          count: 200,
        },
      }}
    />
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/results/evaluation-metrics-dashboard
```

Dependencies [#dependencies]

* **Data source:** renders the `stats` / `metrics` / `confusionMatrix` / `calibration` props you pass (each section optional) — works with any backend. Recommended producers: `useEvaluateModel` and `useCalibrateThreshold` from `@localmode/react` (optional). See [Bring your own data](/docs/bring-your-own-data#results--insights).

* `clsx` + `tailwind-merge` — via the shared `cn()` util

Files installed [#files-installed]

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

Props [#props]

**EvaluationMetricsDashboard**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `stats` | `array` | — | KPI stat-tile row (value + delta). |
| `metrics` | `array` | — | Metric cards (accuracy / precision / recall / F1, etc.). |
| `confusionMatrix` | `object` | — | Confusion matrix (color-scaled, with legend). |
| `radarMetrics` | `array` | — | Metrics to plot on the radar/spider sub-view. Defaults to the `metrics` array when omitted; pass an empty array to hide the radar. |
| `calibration` | `object` | — | Threshold-calibration panel data. |

Examples [#examples]

From an evaluation run [#from-an-evaluation-run]

`useEvaluateModel` returns `{ score, predictions, datasetSize, durationMs }` — one metric. Compose the rest from the `@localmode/core` evaluation helpers (`f1Score`, `confusionMatrix`, which returns `{ labels, matrix }`) over the same `predictions` and the expected labels.

```tsx
import { EvaluationMetricsDashboard } from '@/components/evaluation-metrics-dashboard';
import { f1Score, confusionMatrix } from '@localmode/core';

export function Example({ evaluation, expected, calibration }) {
  const cm = confusionMatrix(evaluation.predictions, expected);
  return (
    <EvaluationMetricsDashboard
      stats={[
        { label: 'Dataset', value: evaluation.datasetSize },
        { label: 'Duration', value: `${(evaluation.durationMs / 1000).toFixed(2)}s` },
      ]}
      metrics={[
        { label: 'Accuracy', value: evaluation.score },
        { label: 'F1', value: f1Score(evaluation.predictions, expected) },
      ]}
      confusionMatrix={{ labels: cm.labels, matrix: cm.matrix }}
      calibration={{ threshold: calibration.threshold, percentile: calibration.percentile, distribution: calibration.distribution }}
    />
  );
}
```

Customization [#customization]

Cell coloring uses `color-mix` over CSS-variable tokens (`--color-emerald-500` for the diagonal, `--color-rose-500` for off-diagonal), with opacity scaled to each cell relative to the matrix max. The radar polygon fills with `color-mix(... var(--color-primary) ...)`. Everything inherits your theme; adjust the section components in the copied file to add or reorder displays.