PriceCard

A pricing plan card with a name, price, period, description, feature list, and CTA button. A highlightedprop adds a primary border, shadow, and "Most Popular" badge to emphasize a recommended plan.

Anatomy

Built on Card. The header contains plan name, description, and price. The content holds the feature list with check / cross icons. The footer has the CTA button. When highlighted, a "Most Popular" Badge is absolutely positioned above the card.

Most Popular
Pro
For growing teams.
$29/month
  • Unlimited projects
  • Advanced analytics
  • Priority support
  • Custom domain
  • Up to 10 members

Three-Tier Pricing

The standard pricing page pattern — three plans with the middle plan highlighted as the recommended option.

Starter
For individuals and small projects.
$9/month
  • 5 projects
  • Basic analytics
  • Email support
  • Custom domain
  • Team members
Most Popular
Pro
For growing teams and businesses.
$29/month
  • Unlimited projects
  • Advanced analytics
  • Priority support
  • Custom domain
  • Up to 10 members
Enterprise
For large organizations.
$99/month
  • Unlimited everything
  • Custom analytics
  • 24/7 phone support
  • Custom domain
  • Unlimited members

Custom Period

Override the period prop (default: "/month") for annual pricing or one-time payments.

Annual Pro
Save 2 months with annual billing.
$290/year
  • Everything in Pro
  • 2 months free
  • Annual invoice
Lifetime
Pay once, use forever.
$499 one-time
  • Lifetime updates
  • All future features
  • Priority support

Design Guidelines

Do

  • Highlight the plan you want to sell. Use highlightedon the middle or most popular plan to guide the user's eye.
  • Keep feature lists to 4–6 items. More than six features creates visual overload — link to a full comparison table instead.
  • Add padding above a highlighted card. The absolute-positioned badge needs room — add pt-6 to the grid container.

Don't

  • Don't highlight multiple plans. Highlighting more than one plan dilutes the "recommended" signal.
  • Don't use inconsistent feature counts. Cards with different numbers of features have different heights — keep counts consistent across plans.
  • Don't bury the price. The price is the first decision factor — it should be immediately visible, not hidden below a long feature list.

Developer Reference

Props

  • name (required) — plan name, rendered as CardTitle.
  • price(required) — price string (e.g. "$29"), rendered in text-4xl font-bold.
  • period(optional, default: "/month") — appended to price in muted text.
  • description (required) — short plan tagline shown as CardDescription.
  • features (required) — array of { text: string; included: boolean }. included: true shows a success check; false shows a muted cross.
  • highlighted (optional) — adds border-primary, shadow-lg, and a "Most Popular" Badge.
  • ctaLabel(optional, default: "Get Started") — CTA button text.
  • onCtaClick (optional) — CTA button click handler.

Usage

import { OriginUiPriceCard } from "@/components/branding/origin-ui-price-card"

<div className="grid gap-6 pt-4 sm:grid-cols-3">
  <OriginUiPriceCard
    name="Starter"
    price="$9"
    description="For individuals and small projects."
    features={[
      { text: "5 projects", included: true },
      { text: "Email support", included: true },
      { text: "Custom domain", included: false },
    ]}
    onCtaClick={() => router.push("/checkout?plan=starter")}
  />
  <OriginUiPriceCard
    name="Pro"
    price="$29"
    description="For growing teams."
    highlighted   // adds border-primary + "Most Popular" badge
    features={[
      { text: "Unlimited projects", included: true },
      { text: "Priority support", included: true },
      { text: "Custom domain", included: true },
    ]}
    onCtaClick={() => router.push("/checkout?plan=pro")}
  />
  <OriginUiPriceCard
    name="Enterprise"
    price="$99"
    description="For large organizations."
    ctaLabel="Contact Sales"
    features={[
      { text: "Unlimited everything", included: true },
      { text: "24/7 phone support", included: true },
      { text: "Custom domain", included: true },
    ]}
    onCtaClick={() => openSalesForm()}
  />
</div>