Three plans in joined pricing cells with none featured, each listing the same four highlights with a check or a muted minus mark so the plans compare at a glance. Pairs with pricing-11.
import { CheckIcon, MinusIcon } from "@phosphor-icons/react/dist/ssr"
import { cn } from "cn"
import { Heading } from "@/components/editorial/heading"
import {
Pricing,
PricingCardAmount,
PricingCardContent,
PricingCardDescription,
PricingCardFeature,
PricingCardFeatures,
PricingCardFooter,
PricingCardHeader,
PricingCardPeriod,
PricingCardPrice,
PricingCardTitle,
PricingCellCard,
} from "@/components/editorial/pricing"
import {
Section,
SectionContent,
SectionDescription,
SectionHeader,
SectionTitleGroup,
} from "@/components/editorial/section"
import { buttonVariants } from "@/components/ui/button"
// The copy: change text here, not in the markup.
const COPY = {
title: "Pricing that grows with the team",
body: "Every plan answers email, chat and forms.",
period: "/ month",
included: "Included",
excluded: "Not included",
cta: (name: string) => `Start with ${name}`,
} as const
const PLANS = [
{
name: "Starter",
price: "$29",
description: "One shared inbox for a small team.",
highlights: [
{ label: "Email and chat", on: true },
{ label: "Saved replies", on: true },
{ label: "Routing rules", on: false },
{ label: "Single sign-on", on: false },
],
},
{
name: "Growth",
price: "$89",
description: "Routing and reports for several teams.",
highlights: [
{ label: "Email and chat", on: true },
{ label: "Saved replies", on: true },
{ label: "Routing rules", on: true },
{ label: "Single sign-on", on: false },
],
},
{
name: "Scale",
price: "$249",
description: "Security reviews and a named contact.",
highlights: [
{ label: "Email and chat", on: true },
{ label: "Saved replies", on: true },
{ label: "Routing rules", on: true },
{ label: "Single sign-on", on: true },
],
},
] as const
// true and false draw a mark.
function Mark({ value }: { value: boolean | string }) {
if (typeof value === "string") return <>{value}</>
return value ? (
<>
<CheckIcon weight="bold" aria-hidden="true" className="inline size-4" />
<span className="sr-only">{COPY.included}</span>
</>
) : (
<>
<MinusIcon
aria-hidden="true"
className="inline size-4 text-muted-foreground"
/>
<span className="sr-only">{COPY.excluded}</span>
</>
)
}
export default function ThreePlanPricing02() {
return (
<Section>
<SectionHeader align="center">
<SectionTitleGroup>
<Heading size="sm">{COPY.title}</Heading>
</SectionTitleGroup>
<SectionDescription>{COPY.body}</SectionDescription>
</SectionHeader>
<SectionContent>
<Pricing cols={3} variant="cells">
{PLANS.map((plan) => (
<PricingCellCard key={plan.name}>
<PricingCardHeader>
<PricingCardTitle>{plan.name}</PricingCardTitle>
<PricingCardPrice>
<PricingCardAmount>{plan.price}</PricingCardAmount>
<PricingCardPeriod>{COPY.period}</PricingCardPeriod>
</PricingCardPrice>
<PricingCardDescription>
{plan.description}
</PricingCardDescription>
</PricingCardHeader>
<PricingCardContent>
<PricingCardFeatures>
{plan.highlights.map((h) => (
<PricingCardFeature
key={h.label}
className={h.on ? undefined : "text-muted-foreground"}
>
<Mark value={h.on} />
<span>{h.label}</span>
</PricingCardFeature>
))}
</PricingCardFeatures>
</PricingCardContent>
<PricingCardFooter>
<a
href="#"
data-slot="button"
className={cn(buttonVariants({ variant: "outline" }))}
>
{COPY.cta(plan.name)}
</a>
</PricingCardFooter>
</PricingCellCard>
))}
</Pricing>
</SectionContent>
</Section>
)
}
pnpm dlx shadcn add @01orbital/three-plan-pricing-02npx shadcn add @01orbital/three-plan-pricing-02yarn shadcn add @01orbital/three-plan-pricing-02bunx --bun shadcn add @01orbital/three-plan-pricing-02Free under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.
It lands at components/blocks/pricing/three-plan-pricing-02/index.tsx, as source you own and edit.
import ThreePlanPricing02 from "@/components/blocks/pricing/three-plan-pricing-02"
export default function Example() {
return <ThreePlanPricing02 />
}npm: @phosphor-icons/react, cn. The CLI installs them for you.
Registry pieces it installs with it:
Single Plan Pricing
Single-price section: an Instrument Serif heading, description and trial button on one side, and a PricingCard with a large display amount and a checklist of features on the other.
Three-Plan Pricing with Toggle
Three-plan pricing with a monthly or yearly PricingToggle that swaps the amounts, a featured middle plan marked by a Team favorite badge and solid button, and check-marked feature lists. Client component.