Spec comparePro
Products side by side, built around what differs, with the best value ticked and matching specs folded.
On this page
Installation
Usage
import { SpecCompare } from "@/components/ui/chatcn/pro/spec-compare"
<SpecCompare
products={picks}
specs={[
{ id: "wt", label: "Weight", values: { tarn: 840, cairn: 690 }, unit: "g", better: "lower" },
{ id: "water", label: "Waterproof", values: { tarn: true, cairn: true } },
]}
recommendedId="tarn"
defaultOnlyDifferences
onChoose={choose}
/>A row whose values differ gets a thin accent rule at its start edge and full ink; a row every product shares turns a gray step quieter. Give a numeric row better and its best value gets a tick (a tie across every product marks nothing). Only differences folds the shared rows into one line that says how many match and opens them again. Booleans read as a tick or a dash with Yes or No for screen readers; a missing value says Not listed. The spec column is sticky, so on a phone the products scroll under it.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
products | { id, title, image?, merchant?, price, salePrice? }[] | Two to four |
specs | { id, label, values, better?: "higher" | "lower", unit? }[] | Values by product id: text, number, boolean or null |
currency, locale | string | Prices format with Intl, tabular figures. Default USD, en-US |
onlyDifferences, defaultOnlyDifferences, onOnlyDifferencesChange | boolean | Fold shared rows |
recommendedId | string | Marks the agent's pick |
onChoose, chosenId | (id) => void, string | Adds Choose under each column |
loading | boolean | Skeleton columns |
labels | Partial<SpecCompareLabels> | Every string, for translation |
Keyboard
| Key | Action |
|---|---|
| Tab | The switch, the fold line, then each Choose |
| Space | Toggle Only differences |
Accessibility
- A real table with a caption, column headers per product and row headers per spec.
- Best values carry the word Best (visible from 640 px, hidden text below).
- Choose buttons use
aria-pressed; the fold line usesaria-expanded.
Motion
The switch thumb slides in 150 ms and the fold chevron turns in 150 ms. Rows appear without animation, so a long table never shuffles while you read it.