Pricing Blocks for Shadcn and React
One time purchase pricing grid
import { ArrowRightIcon, CheckIcon } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card'
import { cn } from '@/lib/utils'
interface PricingTier {
id: string
name: string
description: string
price?: number
currency?: string
priceText?: string
features: string[]
highlighted?: boolean
buttonText?: string
buttonVariant?: 'default' | 'outline'
}
interface Props {
title?: string
description?: string
tiers?: PricingTier[]
}
const sampleTiers: PricingTier[] = [
{
id: 'starter',
name: 'Starter',
description: 'Perfect for individuals and small projects',
price: 29,
currency: '$',
features: [
'Up to 10 projects',
'Basic analytics',
'Email support',
'5GB storage',
'Community access',
],
buttonText: 'Get Started',
buttonVariant: 'outline',
},
{
id: 'pro',
name: 'Pro',
description: 'Best for growing teams and businesses',
price: 99,
currency: '$',
features: [
'Unlimited projects',
'Advanced analytics',
'Priority support',
'100GB storage',
'Team collaboration',
'Custom integrations',
'API access',
],
highlighted: true,
buttonText: 'Get Started',
buttonVariant: 'default',
},
{
id: 'enterprise',
name: 'Enterprise',
description: 'For large organizations with custom needs',
priceText: 'Custom',
features: [
'Everything in Pro',
'Dedicated support',
'Unlimited storage',
'Advanced security',
'Custom SLA',
'White-label options',
'On-premise deployment',
],
buttonText: 'Contact Sales',
buttonVariant: 'outline',
},
]
export default function PricingOne({
title = 'Simple, Transparent Pricing',
description = 'Choose the perfect plan for your needs. No hidden fees, no subscriptions.',
tiers = sampleTiers,
}: Props) {
return (
<section className="w-full bg-background py-12 md:py-16 px-4 sm:px-6 lg:px-8">
<div className="container mx-auto px-4 md:px-6">
<div className="mb-12 text-center md:mb-16">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl">
{title}
</h2>
<p className="mt-3 mx-auto max-w-2xl sm:text-lg text-muted-foreground">
{description}
</p>
</div>
<div className="mx-auto grid max-w-6xl gap-4 lg:gap-8 md:grid-cols-3">
{tiers.map(tier => (
<Card
key={tier.id}
className={cn(
'relative flex flex-col',
tier.highlighted && 'shadow-xl ring-4 ring-ring/20',
)}
>
<CardHeader>
<CardTitle className="flex items-center gap-2 text-2xl">
{tier.name}
{tier.highlighted && (
<Badge className="h-6 uppercase tracking-wider">
Most Popular
</Badge>
)}
</CardTitle>
<CardDescription className="text-sm">
{tier.description}
</CardDescription>
</CardHeader>
<CardContent className="flex-1">
<div className="mb-6">
<div className="flex items-baseline gap-1">
<span className="text-2xl text-muted-foreground">
{tier.currency && tier.currency}
</span>
<span className="text-4xl lg:text-5xl font-bold tracking-tight">
{tier.priceText ? tier.priceText : tier.price}
</span>
{!tier.priceText && <span className="text-muted-foreground">/one-time</span>}
</div>
</div>
<ul className="space-y-3">
{tier.features.map(feature => (
<li key={feature} className="flex items-center gap-2">
<div className="size-5 flex items-center justify-center rounded-full border bg-muted p-1">
<CheckIcon className="size-full shrink-0" />
</div>
<span className="text-sm text-muted-foreground">{feature}</span>
</li>
))}
</ul>
</CardContent>
<CardFooter>
<Button
className="group w-full flex justify-between"
variant={tier.buttonVariant || 'default'}
size="lg"
>
{tier.buttonText || 'Get Started'}
<ArrowRightIcon className="size-4 transition-transform group-hover:translate-x-0.5" />
</Button>
</CardFooter>
</Card>
))}
</div>
{/* Footer Note */}
<p className="mt-12 text-center text-sm text-muted-foreground">
All plans include a 30-day money-back guarantee. Questions?
{' '}
<a href="#" className="font-medium text-primary hover:underline">
Contact our sales team
</a>
</p>
</div>
</section>
)
} Block details
A clean one-time purchase pricing section with a 3-column grid layout. Features customizable pricing tiers, feature lists with checkmark icons, highlighted popular plans, and flexible button variants. Perfect for showcasing non-subscription products or services.
| Dependency | Source |
|---|---|
| Card (shadcn) | Registry |
| Badge (shadcn) | Registry |
| Button (shadcn) | Registry |
| Lucide React | NPM |
Horizontal pricing card
import { Check } from 'lucide-react'
import { Button } from '@/components/ui/button'
interface PricingPlan {
id: string
name: string
description: string
amount: string | number
currency: string
features: string[]
buttonText?: string
buttonHref?: string
}
interface Props {
title?: string
description?: string
plans?: PricingPlan[]
priceLabel?: string
}
const samplePlans: PricingPlan[] = [
{
id: 'all-access',
name: 'All Access',
description:
'Get lifetime access to all current and future components, blocks, and templates. No recurring fees, no hidden costs.',
amount: '$99',
currency: '/one-time',
features: [
'All components',
'Lifetime updates',
'Premium support',
'Commercial license',
'Source code access',
'Figma design files',
],
buttonText: 'Get All Access',
buttonHref: '#',
},
]
export default function PricingTwo({
plans = samplePlans,
priceLabel = 'Pay once, own it forever',
title = 'Simple Pricing',
description = 'Choose the plan that best fits your needs.',
}: Props) {
return (
<section className="w-full bg-background py-12 md:py-16 px-4 sm:px-6 lg:px-8">
<div className="container mx-auto flex flex-col gap-8 px-4 md:px-6">
<div className="text-center">
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl">
{title}
</h2>
<p className="mt-3 mx-auto max-w-2xl sm:text-lg text-muted-foreground">
{description}
</p>
</div>
{plans.map(plan => (
<div
key={plan.id}
className="mx-auto rounded-3xl border lg:mx-0 lg:flex lg:max-w-none"
>
<div className="flex flex-col justify-between p-4 sm:p-8 lg:flex-auto">
<div>
<h3 className="text-2xl font-bold tracking-tight">
{plan.name}
</h3>
<p className="mt-2 text-muted-foreground">{plan.description}</p>
</div>
<div className="mt-6">
<div className="flex items-center gap-x-2">
<p className="flex-none text-sm font-semibold">
What you will get
</p>
<hr className="h-px flex-auto bg-border" />
</div>
<ul role="list" className="mt-3 grid sm:grid-cols-2 gap-3 text-sm text-muted-foreground">
{plan.features.map(feature => (
<li key={feature} className="flex gap-x-2 items-center">
<Check className="size-5 shrink-0 text-foreground" />
{feature}
</li>
))}
</ul>
</div>
</div>
<div className="-mt-2 grow p-2 lg:mt-0 lg:w-full lg:max-w-md">
<div className="flex h-full flex-col justify-center rounded-2xl border bg-muted/50 py-10 text-center ring-inset lg:py-16">
<div className="mx-auto max-w-xs px-4">
<p className="text-base font-semibold text-muted-foreground">
{priceLabel}
</p>
<p className="mt-6 flex items-baseline justify-center gap-x-1">
<span className="text-5xl font-semibold tracking-tight text-foreground">
{plan.amount}
</span>
<span className="font-semibold tracking-wide text-muted-foreground">
{plan.currency}
</span>
</p>
<Button
asChild
size="lg"
className="mt-6 w-full"
>
<a
href={plan.buttonHref || '#'}
rel="noopener noreferrer nofollow"
>
{plan.buttonText || 'Get All Access'}
</a>
</Button>
</div>
</div>
</div>
</div>
))}
</div>
</section>
)
} Block details
A horizontal pricing card layout with a two-column design. Features a left section for plan details and features list, and a right section with centered pricing and call-to-action. Perfect for showcasing a single premium plan.
| Dependency | Source |
|---|---|
| Button (shadcn) | Registry |
| Lucide React | NPM |
Frequently asked questions
How do I customize the pricing tiers?
Pass a `tiers` prop with an array of pricing tier objects. Each tier includes id, name, description, price, currency, features array, and optional highlighted flag. The buttonText and buttonVariant properties allow you to customize each tier's call-to-action independently.
Can I highlight a specific pricing tier as "Most Popular"?
Yes! Set the `highlighted` property to `true` on any pricing tier object. This will add a "Most Popular" badge, apply primary border styling, and add a subtle ring effect to make the tier stand out from the others.
Is this pricing block responsive?
Absolutely. The pricing grid uses a responsive layout that displays as a single column on mobile, and 3 columns on desktop (lg breakpoint). All cards maintain consistent height and spacing across breakpoints.
How do I change the currency symbol or pricing display?
Each pricing tier has a `currency` property (default is "$") and a `price` number. You can customize these per tier.
Can I customize the features list for each tier?
Yes, each tier accepts a `features` array of strings. The component automatically renders each feature with a check icon. Features can be different for each tier - use "Everything in [Plan]" to indicate plan inheritance clearly.
How do I change the button text and style for each tier?
Use the `buttonText` property to set custom text (e.g., "Get Started", "Contact Sales") and `buttonVariant` to choose between "default" (filled) or "outline" styles. This allows you to differentiate tiers with different calls-to-action.
Are the pricing blocks free to use?
We offer both free and premium pricing blocks. The free blocks are completely free to use in personal and commercial projects. Premium blocks require a one-time purchase for access to more advanced designs.
How do I use these pricing blocks in my project?
Simply browse our collection, click on the "Copy Code" button for your chosen block, and paste it into your Shadcn React project. All components are built with Tailwind CSS & Shadcn React, so they'll work seamlessly with your existing setup.
Can I customize the pricing blocks?
Absolutely! All our pricing blocks are fully customizable. You can easily modify colors, spacing, typography, and layout by adjusting the Tailwind CSS classes in the component code.