Plan comparison

Compare meaningful differences between plans and billing periods.

Preview
Plan comparison preview

Room for the way you work

Only the details that change between plans. Switch billing to see what you would pay.

Billed month to month

Compare plans

8 of 8 features
What changes

Team

For smaller teams
$13per seat / month

Studio

For work across teams
$27per seat / month
Active projects
TeamUnlimited
StudioUnlimited
Shared workspaces
Team1 workspace
StudioUnlimited
Guest reviewers
Team5 per project
StudioUnlimited
Version history
Team30 days
StudioUnlimited
Approval flows
TeamNot included
StudioIncluded
Custom roles
TeamNot included
StudioIncluded
Source exports
TeamIncluded
StudioIncluded
Support
TeamEmail
StudioPriority email

When to use

  • Comparing two tiers side by side with a feature matrix.
  • Pricing pages that switch between monthly and yearly prices.
  • Long feature lists where people want to see only the differences.

When not to use

  • Use usage-pricing when price depends on seats or volume.
  • Use segmented-control alone for a simple billing toggle.
  • Use cancel-flow for downgrade or cancellation decisions.

shadcn CLI

Also installs (4)

  • manicat-foundation
  • button
  • segmented-control
  • switch
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "plan-comparison",
  "type": "registry:block",
  "title": "Plan comparison",
  "description": "Compare meaningful differences between plans and billing periods.",
  "categories": [
    "blocks"
  ],
  "dependencies": [
    "@radix-ui/react-switch",
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json",
    "https://manicat.viraza.net/r/button.json",
    "https://manicat.viraza.net/r/segmented-control.json",
    "https://manicat.viraza.net/r/switch.json"
  ],
  "files": [
    {
      "path": "registry/blocks/plan-comparison/plan-comparison.tsx",
      "type": "registry:component",
      "target": "@components/manicat/blocks/plan-comparison/plan-comparison.tsx"
    },
    {
      "path": "registry/blocks/plan-comparison/plan-comparison.module.css",
      "type": "registry:component",
      "target": "@components/manicat/blocks/plan-comparison/plan-comparison.module.css"
    },
    {
      "path": "registry/components/switch/switch.tsx",
      "type": "registry:component",
      "target": "@components/manicat/switch/switch.tsx"
    },
    {
      "path": "registry/components/switch/switch.module.css",
      "type": "registry:component",
      "target": "@components/manicat/switch/switch.module.css"
    },
    {
      "path": "registry/components/segmented-control/segmented-control.tsx",
      "type": "registry:component",
      "target": "@components/manicat/segmented-control/segmented-control.tsx"
    },
    {
      "path": "registry/components/segmented-control/segmented-control.module.css",
      "type": "registry:component",
      "target": "@components/manicat/segmented-control/segmented-control.module.css"
    },
    {
      "path": "registry/components/button/button.tsx",
      "type": "registry:component",
      "target": "@components/manicat/button/button.tsx"
    },
    {
      "path": "registry/components/button/button.module.css",
      "type": "registry:component",
      "target": "@components/manicat/button/button.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/blocks/plan-comparison",
  "meta": {
    "tier": "free",
    "kind": "block",
    "docs": "https://manicat.viraza.net/components/blocks/plan-comparison",
    "markdown": "https://uiarc.dev/components/blocks/plan-comparison/markdown"
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { PlanComparison } from "manicat/registry/blocks/plan-comparison/plan-comparison";

export function PlanComparisonExample() {
  return <PlanComparison />;
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Pricing page Drop the plan comparison on a pricing route as is.

Pricing page Drop the plan comparison on a pricing route as is. preview

Room for the way you work

Only the details that change between plans. Switch billing to see what you would pay.

Billed month to month

Compare plans

8 of 8 features
What changes

Team

For smaller teams
$13per seat / month

Studio

For work across teams
$27per seat / month
Active projects
TeamUnlimited
StudioUnlimited
Shared workspaces
Team1 workspace
StudioUnlimited
Guest reviewers
Team5 per project
StudioUnlimited
Version history
Team30 days
StudioUnlimited
Approval flows
TeamNot included
StudioIncluded
Custom roles
TeamNot included
StudioIncluded
Source exports
TeamIncluded
StudioIncluded
Support
TeamEmail
StudioPriority email

Accessibility

  • The matrix uses table, row, columnheader, rowheader, and cell roles.
  • Prices are aria-live with aria-atomic so the full value is read.
  • The chosen plan is announced in a role="status" footer.

Motion

  • Prices count between billing periods and the selection highlight moves with layoutId.
  • Extra feature rows expand in height with a light blur.
  • Reduced motion jumps to the final values and disables height animation.

Responsive behavior

  • Below 640px the feature header column hides and each feature name spans the row above its two values.
  • Below 365px plan and value padding tighten so both plans still fit side by side.

Performance

  • Prices tween with a single animate call per value; the selection highlight uses one layoutId.
  • Showing extra rows animates height, so keep the matrix to a few dozen features.

Notes for AI

  • Use when people compare two tiers side by side.
  • Edit the pricing and features constants; there is no selection callback, so wire the Button onClick yourself.
  • Composes Arc Button, SegmentedControl, and Switch.