Skip to content
Sign in
PlaygroundEval resultsMenu

Eval results

The results of an eval run: pass rate, average score, cost and duration against a baseline, and every case with its score, latency and pass or fail. Filter, sort, and expand a case for the full input, output and the grader's reasoning. Rows fill in while the run is going.

A docs assistant graded for correctness: pass rate, score, cost and duration against main, with the first failure open.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/eval-results.json

Usage

tsx
import { EvalResults } from "@/components/ui/chatcn/eval-results"

<EvalResults
  title="docs-qa"
  meta="claude-sonnet-5-5, 12 cases"
  cases={cases}
  baseline={{ label: "main, run 212", passRate: 0.6, avgScore: 0.71, cost: 0.045 }}
  threshold={0.7}
/>

Each case has an input, the expected reference, the output, a score from 0 to 1, a status and its latencyMs. Pass rate, average score and cost are computed from the cases; pass metrics to override them, and to give the run duration, which is never guessed. With a baseline, every figure gets a delta: green and an up arrow when it got better, red and a down arrow when it got worse, whichever direction is good for that figure.

While running, pass cases as queued or running and update them as results arrive. Their rows keep their place and fill in, the summary updates in place, and a 2 px bar under the header tracks progress against total.

Examples

Running

Cases finish three at a time and the summary updates in place.

Failures, worst first

Filter, sort and expanded rows are all controllable. Sorting by score starts with the lowest, and by latency with the slowest: the cases worth reading come first. Cases without the figure always sort last.

Controlled filter and sort: only failed cases, lowest score first.

States

Loading a past run, a run stopped by an error, no cases, and a narrow width.

Props

PropTypeNotes
casesEvalCase[]{ id, input, expected?, output?, score?, status, latencyMs?, cost?, grader?, reasoning?, errorText? }
title, metaReactNodeRun name and quiet context such as dataset and model
metricsEvalMetrics{ passRate?, avgScore?, cost?, durationMs? }. Overrides the computed figures
baselineEvalBaseline{ label, ...metrics }. Turns on deltas
running, totalboolean, numberProgress and fill-in while cases finish
loadingbooleanSkeleton summary and rows in the final layout
error, onRetryReactNode, () => voidA banner above the cases with Resume run
thresholdnumberThe pass mark, shown in the toolbar and in each case's reasoning
filter, defaultFilter, onFilterChange"all" | "passed" | "failed"Failed includes errored cases
sort, defaultSort, onSortChange{ key, direction }Keys index, score, latency
expanded, defaultExpanded, onExpandedChangestring[]Ids of the open cases
emptyStateReactNodeReplaces the no cases message
currency, localestringCost formatting. Defaults to USD
maxHeightnumber | stringHeight of the table scroll area. The header row stays put

Keyboard

KeyAction
TabFilter buttons, sort headers, then one stop per case
ArrowDown, ArrowUpNext or previous case
Home, EndFirst or last case
Enter, SpaceExpand or collapse the focused case

Accessibility

  • A real table with column headers. Sortable headers are buttons and the header cell carries aria-sort.
  • Each case row has one button with aria-expanded; the whole row is its hit area, so a click anywhere opens it.
  • Pass, fail and error badges pair the hue with an icon and a word. Deltas add an arrow and a hidden Better or Worse.
  • Progress is a progressbar while running, and the final counts are announced once through a polite live region.
  • On narrow containers, expected and output columns fold away and stay readable in the expanded case.

Motion

  • Expanding a case is instant: reviewing a run is a high-frequency action.
  • When a case finishes, its badge swaps in with the kit's 150 ms blur crossfade. Figures update in place and never count up.
  • The progress bar scales rather than resizes. Under reduced motion the swap is skipped.