Xzero UI
Pro library

Model cardPro

A model details card where switching models rolls every price, limit and score in place, a token slider estimates monthly cost live, and benchmark bars show each model's rank on hover. Compare crossfades to a side-by-side table against any rival with the better values marked, and the card never changes size.

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

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/model-card

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 { ModelCard, type ModelCardModel } from "@/components/xzero/model-card/model-card";
import { ClaudeMark, OpenaiMark } from "@/components/xzero/model-card/model-card-marks";

const sonnet: ModelCardModel = {
  id: "claude-sonnet-5-5",
  name: "Claude Sonnet 5.5",
  provider: "Anthropic",
  mark: <ClaudeMark aria-hidden style={{ color: "#D97757" }} />,
  summary: "The balanced Claude for everyday coding, agents and analysis at scale.",
  modalities: ["text", "image", "pdf", "tools", "reasoning"],
  contextWindow: 1_000_000,
  maxOutput: 64_000,
  knowledgeCutoff: "2026-03",
  pricing: { input: 3, output: 15, cachedInput: 0.3 },
  scores: { "swe-bench": 82.1, gpqa: 85.4 },
};

export function ModelDetails({ rivals, current, onPick }: { rivals: ModelCardModel[]; current: string; onPick: (id: string) => void }) {
  return (
    <ModelCard
      model={sonnet}
      rivals={rivals}
      benchmarks={[
        { id: "swe-bench", name: "SWE-bench Verified", shortName: "SWE-bench", description: "real GitHub issues resolved" },
        { id: "gpqa", name: "GPQA Diamond", shortName: "GPQA", description: "graduate level science questions" },
      ]}
      defaultMonthlyTokens={50_000_000}
      sample={false}
      selected={current === sonnet.id}
      onSelect={model => onPick(model.id)}
      onCopyId={id => console.log("copied", id)}
    />
  );
}

API reference

ModelCard

A model details card for a model picker, docs or a marketplace that keeps one size in every state. The header shows the provider mark, the model name and the provider, with a Compare switch. The details view has a two line summary, all seven modality chips (unsupported ones dashed and muted), context window, max output and knowledge cutoff with a context gauge that reads as pages (1M tokens fits about 1,500 pages), input, output and cached prices per million tokens, a monthly volume slider that rolls the estimated monthly cost live, and benchmark bars against two rivals where hovering or focusing a row shows the exact score, its rank and the gap to the leader. The footer shows the API model id with Copy model id. Compare crossfades to a side by side table against any rival, including the cost at the chosen volume, with a check and the margin (+2.3, −20%, 2x) on the better value and a tally of who leads. Details, compare, loading and error are stacked in one grid cell, so switching models, views or benchmarks never moves the card. Ships with sample data for Claude Opus 5.5 against GPT-6.1 Sol, Gemini 4 Argon and Grok 4.7; prices and scores are labeled as samples.

PropTypeDefaultDescription
modelModelCardModelClaude Opus 5.5 (sample)The model the card describes: { id, name, provider, mark?, summary?, modalities?, contextWindow?, maxOutput?, knowledgeCutoff?, pricing?, scores? }. contextWindow and maxOutput are token counts (1_000_000 reads as 1M). knowledgeCutoff is an ISO month such as "2026-03" (shown as Mar 2026); any other string is shown as is. pricing is { input, output, cachedInput? } per million tokens. scores maps benchmark ids to numbers. A missing value reads as Not listed.
rivalsModelCardModel[]GPT-6.1 Sol, Gemini 4 Argon, Grok 4.7 (sample)Other models. The first two appear under the model in the benchmark rows, ranks count every rival with a score, and every rival can be picked in the compare view. The model itself is filtered out, so one shared pool works for every model. Pass [] to hide the Compare switch.
benchmarksModelCardBenchmark[]SWE-bench Verified, GPQA Diamond, Terminal-Bench 2.0Benchmarks in order: { id, name, shortName?, description?, max?, unit? }. shortName labels the switcher, description follows the name in the caption, max fills a bar (default 100) and unit follows each score (default %). Only benchmarks the model has a score for are offered; with none the section hides.
view"details" | "compare"–Controlled view. Pair it with onViewChange.
defaultView"details" | "compare""details"Starting view when uncontrolled.
onViewChange(view: ModelCardView) => void–Called when the Compare switch changes.
compareWithstring–Controlled id of the rival in the compare view. Pair it with onCompareWithChange.
defaultCompareWithstringfirst rivalStarting rival when uncontrolled.
onCompareWithChange(id: string) => void–Called when a rival is picked from the compare menu.
defaultBenchmarkstringfirst scored benchmarkBenchmark shown first.
onBenchmarkChange(id: string) => void–Called when the benchmark switcher changes.
defaultMonthlyTokensnumber100_000_000Monthly token volume the cost estimator starts at. Snaps to the nearest stop: 1M, 5M, 10M, 25M, 50M, 100M, 250M, 500M or 1B.
onMonthlyTokensChange(tokens: number) => void–Called with the new monthly volume as the slider moves.
inputSharenumber0.75Share of the monthly volume billed at the input price; the rest is billed at the output price.
currencystring"USD"ISO 4217 currency for prices.
samplebooleantrueLabels prices and scores as samples in the benchmark caption and the compare footnote. Set it to false once you wire real figures.
loadingbooleanfalseShows a skeleton of the card, disables Compare and sets aria-busy.
errorstring–Replaces the body with an error message. The header still shows the model.
onRetry() => void–Adds a Retry button to the error state.
onCopyId(id: string) => void–Called after Copy model id writes the id to the clipboard.
onSelect(model: ModelCardModel) => void–Adds a primary Use model button to the footer, for model pickers.
selectedbooleanfalseShows the select button as Selected with a check and aria-pressed.
selectLabelstring"Use model"Label for the select button.
classNamestring–Class on the root article.
styleCSSProperties–Inline style on the root article.

Keyboard interactions

KeysAction
TabMoves through the Compare switch, the monthly volume slider, the benchmark switcher, each benchmark row (focus shows its score and rank), or the rival menu in the compare view, then Copy model id and Use model when present. Hidden views are inert, so Tab never lands in them.
Arrow keys / Page up / Home / EndOn the volume slider, step through the monthly volumes; the estimated cost rolls to the new value.
Space / EnterToggles Compare, copies the model id or selects the model.
Arrow left / Arrow rightMoves between benchmarks in the switcher.
Enter / Arrow downOn the rival menu, opens it; arrows move between rivals and Enter picks one. Escape closes it.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in ai

Guidance for AI tools

Model card: A model details card where switching models rolls every price, limit and score in place, a token slider estimates monthly cost live, and benchmark bars show each model's rank on hover. Compare crossfades to a side-by-side table against any rival with the better values marked, and the card never changes size. 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