Xzero UI
Pro library

Eval suitePro

Run an evaluation suite on a new version of an LLM feature against its baseline: results stream in case by case, and regressions and fixes are called out with the cases behind them.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/eval-suite
Live · keyboard ready

Pass cases, candidate, baseline and run, which streams graded results, to show your own evals; with no props it runs a sample suite.

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui-pro/eval-suite

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { EvalSuite } from "@/components/xzero/blocks/eval-suite/eval-suite";

export function SupportAgentEvals({ suite, history }) {
  return (
    <EvalSuite
      suite={suite}
      runs={history}
      onRun={async function* (suite, { signal, started }) {
        const response = await fetch(`/api/evals/${suite.name}/runs`, { method: "POST", signal });
        for await (const event of readEvents(response)) {
          if (event.type === "started") started(event.caseId);
          if (event.type === "scored") yield event.result; // { caseId, outcome, output, scores, rationale, costUsd }
        }
      }}
      onTriage={async (caseId, action) => {
        if (action === "issue") return (await createIssue(caseId)).key; // "SUP-2481"
        await markExpected(caseId);
      }}
    />
  );
}

// A case with a drilldown. Cases without input still score and list, without the side by side view.
const refundCase = {
  id: "refunds-02",
  category: "Refunds",
  title: "Refund after partial shipment",
  baseline: "pass",
  input: "Only 2 of my 3 items arrived (order #48213). Can I get my money back for that part?",
  expected: "Refund only the missing item, not the whole order.",
  baselineOutput: "I've refunded $34.00 for the candle set to your original payment method.",
  baselineScores: [5, 5, 4, 5], // one per rubric criterion
};

API reference

EvalSuite

One card for running an evaluation suite on a new version of an LLM feature against its baseline. The header names the feature, the candidate and baseline versions with their models, the case count and the judge model, with Run beside it. While the run streams, one row per category fills with a small cell per case (pass, fail or error, each with its own glyph), the score counts up next to the baseline with the delta in points, and each category bar fills with a ghost tick at the baseline value. Cost, time and a sparkline of the last runs sit in the summary. The case list filters to All, Failed, Regressions or Improved; opening a case shows the input, the expected behavior, the baseline and new outputs side by side with a word diff, and the judge's rubric scores and rationale, then lets you mark it as expected or open an issue.

PropTypeDefaultDescription
suiteEvalSuiteDatasampleSuiteThe suite: name, candidate { version, model }, baseline { version, model }, judge model, optional categories (row order), rubric (criteria the judge scores 1 to 5), cases and an estimate { costUsd, seconds } shown before the first run. A model is { name, brand?: "claude" | "openai", mark?: ReactNode }. Each case has id, category, title and its baseline outcome; add input, expected, baselineOutput and baselineScores to give it a drilldown.
runsEvalRunRecord[]sampleRunsEarlier runs, oldest first, each { id, label, score, date? } with the score in percent. The sparkline shows the last seven plus the current run, and rings the last one as the baseline.
onRun(suite: EvalSuiteData, context: { signal: AbortSignal; started: (caseId: string) => void }) => AsyncIterable<EvalCaseResult> | Promise<EvalCaseResult[]>–Runs the suite. Yield each EvalCaseResult { caseId, outcome, output?, scores?, rationale?, error?, costUsd? } as it is scored to fill the grid live, or resolve every result at once. Call started(caseId) to show a case as in flight. Stop aborts the signal. Throw to show the failed state with Try again. Without it, the run is simulated on eight workers and announced as simulated.
onTriage(caseId: string, action: "expected" | "issue") => void | string | Promise<void | string>–Called by Mark as expected and Open issue. Return or resolve an issue key such as "SUP-2481" for an issue; reject to restore the buttons. Without it, triage is simulated and says so.
defaultFilter"all" | "failed" | "regressions" | "improved""regressions"The filter the case list opens with.
classNamestring–Class on the root element.

Keyboard interactions

KeysAction
TabMoves through Run, the run history, the case filter, each case row, Show more, and inside an open case the triage buttons.
Enter, SpaceOn Run, starts the run; while running the same button stops it. On a case row, opens or closes its drilldown. On Mark as expected or Open issue, triages the case and moves focus to Undo or the confirmation that replaces the buttons; Undo brings the buttons back with focus on the first.
Arrow left / Arrow rightOn the case filter, moves between All, Failed, Regressions and Improved. On the run history, steps through the runs and reads out each version, score and date.
Home / EndOn the case filter or the run history, jumps to the first or last item.
EscapeOn the run history, returns the readout to the latest run.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Guidance for AI tools

Blocks are complete, self-contained screens with sample data. Replace the sample data and connect the callbacks described above. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components