# Comparison

> Three ways to compare — spring-grown benchmark bars with a ratio callout, a sticky-header feature matrix with a highlighted column, and a before/after toggle that morphs scattered tools into a connected hub.

- Collection: Blocks
- Tier: pro
- Docs: https://geturui.com/docs/comparison
- Install: `npx shadcn@latest add @geturui-pro/comparison`
- Dependencies: motion, lucide-react

## Variants

### Bar comparison

Benchmark bars grow on a spring when scrolled into view, re-sort per metric tab, and a ratio callout rolls to show how far ahead you are.

Install: `npx shadcn@latest add @geturui-pro/comparison-bar-comparison`

```tsx
import { BarComparison } from "@/components/blocks/comparison/bar-comparison";

export default function Benchmarks() {
  return (
    <BarComparison
      benchmarks={[
        {
          id: "cold",
          label: "Cold start",
          unit: "ms",
          lowerIsBetter: true,
          callout: "faster cold starts",
          entries: [
            { name: "Vessel", value: 38, highlight: true },
            { name: "Runtime A", value: 142 },
          ],
        },
      ]}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| benchmarks | `Benchmark[]` | — | { id, label, unit, lowerIsBetter?, decimals?, entries, method?, callout? }. One tab per benchmark. |
| benchmarks[].entries | `{ name: string; value: number; highlight?: boolean }[]` | — | highlight marks your product with the volt bar and the ratio callout. |
| defaultBenchmark | `string` | — | Id of the tab shown first. |
| eyebrow / heading / subheading | `string` | — | Header copy. |
| className | `string` | — | Classes for the outer section. |

### Feature matrix

Scrollable feature table with a sticky header and first column, a volt-banded highlight column, group headings and a Differences only switch.

Install: `npx shadcn@latest add @geturui-pro/comparison-feature-matrix`

```tsx
import { FeatureMatrix } from "@/components/blocks/comparison/feature-matrix";

export default function Compare() {
  return (
    <FeatureMatrix
      products={[
        { id: "us", name: "Beacon", note: "$12 / seat", highlight: true },
        { id: "them", name: "Legacy suite", note: "$38 / seat" },
      ]}
      groups={[{ title: "Monitoring", rows: [{ label: "Uptime checks", values: { us: "30 s", them: "60 s" } }] }]}
    />
  );
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| products | `MatrixProduct[]` | — | { id, name, note?, highlight? } — one column each. |
| groups | `MatrixGroup[]` | — | { title, rows: { label, hint?, values: Record<productId, boolean | string> }[] }. |
| maxHeight | `number` | 460 | Height of the scroll area; the header stays pinned inside it. |
| heading / subheading | `string` | — | Header copy. |
| className | `string` | — | Classes for the outer section. |

### Before and after

A toggle morphs six scattered, tangled tools into a hub-and-spoke system with travelling pulses, while the side stats crossfade.

Install: `npx shadcn@latest add @geturui-pro/comparison-before-after`

```tsx
import { BeforeAfter } from "@/components/blocks/comparison/before-after";

export default function Story() {
  return <BeforeAfter hub="Tandem" defaultMode="before" />;
}
```

| Prop | Type | Default | Description |
|---|---|---|---|
| tools | `string[]` | — | Six tool names read best; they orbit the hub in the after state. |
| hub | `string` | "Tandem" | Name on the central hub. |
| beforeLabel / afterLabel | `string` | — | Toggle labels. |
| beforeStats / afterStats | `{ value: string; label: string }[]` | — | Three stats for each state. |
| defaultMode | `"before" | "after"` | "after" | Uncontrolled starting state. |
| mode / onModeChange | `"before" | "after" / (mode) => void` | — | Controlled state. |
| className | `string` | — | Classes for the outer section. |

## Accessibility

- Benchmark values are real text beside each bar; the matrix is a semantic table with row, column and group headers and screen-reader labels for checks and dashes.
- The before/after diagram is a single labelled image describing both states; stats update in a polite live region.
- Bar growth, node morphing and pulses are skipped under reduced motion; tabs and switches are keyboard operable.

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
