Pricing Section
Pricing tiers and plans with feature comparison
Pricing Section
The <Pricing> section displays pricing tiers and plans in a clear, scannable format. It helps visitors compare options and choose the right plan for their needs.
Interface
import type { PricingProps } from 'mdxui'
interface PricingProps {
/** Section title */
title?: string
/** Section description */
description?: string
/** Pricing tiers */
tiers: PricingTier[]
/** Show annual/monthly toggle */
showToggle?: boolean
}
interface PricingTier {
/** Tier name */
name: string
/** Price display (e.g., "$29/mo") */
price: string
/** Tier description */
description?: string
/** Feature list */
features: string[]
/** CTA button */
cta: CTA
/** Whether this tier is highlighted */
highlighted?: boolean
}
interface CTA {
text: string
href: string
}Usage
Basic Example
import { Pricing } from '@mdxui/beacon'
<Pricing
tiers={[
{
name: "Starter",
price: "$29/mo",
features: [
"Up to 10 users",
"10GB storage",
"Email support"
],
cta: { text: "Start Free Trial", href: "/signup?plan=starter" }
},
{
name: "Pro",
price: "$99/mo",
features: [
"Unlimited users",
"100GB storage",
"Priority support",
"Advanced analytics"
],
cta: { text: "Start Free Trial", href: "/signup?plan=pro" },
highlighted: true
}
]}
/>With Title and Description
<Pricing
title="Simple, transparent pricing"
description="Choose the plan that's right for your team. All plans include a 14-day free trial."
tiers={[...]}
/>With Annual/Monthly Toggle
<Pricing
title="Pricing that scales with you"
showToggle={true}
tiers={[
{
name: "Starter",
price: "$29/mo",
description: "Perfect for small teams",
features: [
"Up to 5 team members",
"5GB storage",
"Basic analytics",
"Email support"
],
cta: { text: "Get Started", href: "/signup?plan=starter" }
},
{
name: "Professional",
price: "$99/mo",
description: "For growing businesses",
features: [
"Up to 25 team members",
"50GB storage",
"Advanced analytics",
"Priority support",
"Custom integrations"
],
cta: { text: "Get Started", href: "/signup?plan=pro" },
highlighted: true
},
{
name: "Enterprise",
price: "Custom",
description: "For large organizations",
features: [
"Unlimited team members",
"Unlimited storage",
"Advanced security",
"Dedicated support",
"Custom SLA",
"On-premise option"
],
cta: { text: "Contact Sales", href: "/contact" }
}
]}
/>Three-Tier Layout
<Pricing
title="Find your perfect plan"
tiers={[
{
name: "Free",
price: "$0",
description: "For individuals and hobby projects",
features: [
"1 user",
"1GB storage",
"Community support"
],
cta: { text: "Sign Up Free", href: "/signup?plan=free" }
},
{
name: "Team",
price: "$49/mo",
description: "For small teams and startups",
features: [
"Up to 10 users",
"20GB storage",
"Email support",
"Basic analytics"
],
cta: { text: "Try Free for 14 Days", href: "/signup?plan=team" },
highlighted: true
},
{
name: "Business",
price: "$199/mo",
description: "For larger teams and businesses",
features: [
"Unlimited users",
"200GB storage",
"Priority support",
"Advanced analytics",
"Custom integrations",
"SSO"
],
cta: { text: "Try Free for 14 Days", href: "/signup?plan=business" }
}
]}
/>Props
title (optional)
Type: string
Section heading displayed above pricing tiers.
<Pricing
title="Pricing that works for everyone"
tiers={[...]}
/>description (optional)
Type: string
Supporting text below the title. Often mentions free trials or guarantees.
<Pricing
title="Simple pricing"
description="All plans include a 14-day free trial. No credit card required."
tiers={[...]}
/>tiers (required)
Type: PricingTier[]
Array of pricing tier objects.
interface PricingTier {
name: string // Plan name (e.g., "Pro", "Enterprise")
price: string // Price display (e.g., "$29/mo", "Custom")
description?: string // Plan description/subtitle
features: string[] // List of included features
cta: CTA // Call-to-action button
highlighted?: boolean // Highlight this tier (most popular)
}
<Pricing
tiers={[
{
name: "Starter",
price: "$29/mo",
description: "For small teams",
features: ["10 users", "10GB storage"],
cta: { text: "Get Started", href: "/signup" },
highlighted: false
}
]}
/>showToggle (optional)
Type: boolean
Default: false
Show a toggle to switch between monthly and annual pricing.
<Pricing
showToggle={true}
tiers={[...]}
/>Note: When enabled, the implementation handles price switching. You may need to provide both monthly and annual prices in your data structure.
Tier Props
name (required)
Type: string
The plan name displayed prominently at the top of each tier.
{ name: "Professional" }
{ name: "Enterprise" }
{ name: "Free" }price (required)
Type: string
Price display string. Can be a number, range, or custom text.
{ price: "$29/mo" }
{ price: "$99/month" }
{ price: "Custom" }
{ price: "Contact Sales" }
{ price: "$0" }description (optional)
Type: string
Subtitle explaining who the plan is for.
{ description: "Perfect for small teams" }
{ description: "For growing businesses" }
{ description: "Enterprise-grade solution" }features (required)
Type: string[]
List of features included in the tier. Keep them concise and scannable.
{
features: [
"Up to 10 users",
"10GB storage",
"Email support",
"Basic analytics",
"API access"
]
}cta (required)
Type: CTA
Call-to-action button for this tier.
interface CTA {
text: string // Button text
href: string // Destination URL
}
{
cta: {
text: "Start Free Trial",
href: "/signup?plan=pro"
}
}highlighted (optional)
Type: boolean
Default: false
Visually emphasize this tier (usually "most popular").
{
name: "Pro",
highlighted: true // Adds border, badge, or background
}Implementation Details
The reference implementation from @mdxui/beacon includes:
Features
- Responsive Grid - Stacks on mobile, grid on desktop
- Highlighted Tier - Visual emphasis for recommended plan
- Feature Lists - Clean, scannable feature lists
- CTA Buttons - Prominent call-to-action per tier
- Toggle Support - Monthly/annual pricing switcher
- Accessibility - Semantic HTML and ARIA labels
Structure
<section className="pricing">
{(title || description) && (
<div className="pricing-header">
{title && <h2>{title}</h2>}
{description && <p>{description}</p>}
</div>
)}
{showToggle && (
<div className="pricing-toggle">
<button>Monthly</button>
<button>Annual</button>
</div>
)}
<div className="pricing-grid">
{tiers.map(tier => (
<div
key={tier.name}
className={tier.highlighted ? 'tier highlighted' : 'tier'}
>
{tier.highlighted && (
<span className="badge">Most Popular</span>
)}
<h3>{tier.name}</h3>
{tier.description && <p>{tier.description}</p>}
<div className="price">{tier.price}</div>
<ul className="features">
{tier.features.map(feature => (
<li key={feature}>{feature}</li>
))}
</ul>
<Button href={tier.cta.href}>
{tier.cta.text}
</Button>
</div>
))}
</div>
</section>Real-World Examples
SaaS Pricing
<Pricing
title="Choose your plan"
description="All plans include 14-day free trial. No credit card required."
showToggle={true}
tiers={[
{
name: "Starter",
price: "$29/mo",
description: "For individuals and small teams",
features: [
"Up to 5 team members",
"5GB file storage",
"Basic reporting",
"Email support",
"Mobile app access"
],
cta: { text: "Start Free Trial", href: "/signup?plan=starter" }
},
{
name: "Professional",
price: "$99/mo",
description: "For growing businesses",
features: [
"Up to 25 team members",
"50GB file storage",
"Advanced reporting & analytics",
"Priority email & chat support",
"API access",
"Custom integrations",
"Advanced permissions"
],
cta: { text: "Start Free Trial", href: "/signup?plan=pro" },
highlighted: true
},
{
name: "Enterprise",
price: "Custom",
description: "For large organizations",
features: [
"Unlimited team members",
"Unlimited storage",
"Custom reporting",
"Dedicated account manager",
"99.99% SLA",
"SSO & SAML",
"On-premise deployment",
"Custom contracts"
],
cta: { text: "Contact Sales", href: "/contact" }
}
]}
/>Developer Platform Pricing
<Pricing
title="Pay for what you use"
description="Start free, scale as you grow"
tiers={[
{
name: "Hobby",
price: "$0",
description: "For personal projects",
features: [
"100,000 API calls/mo",
"1GB bandwidth",
"Community support",
"Public repos only"
],
cta: { text: "Get Started Free", href: "/signup" }
},
{
name: "Pro",
price: "$49/mo",
description: "For professional developers",
features: [
"1M API calls/mo",
"10GB bandwidth",
"Email support",
"Private repos",
"Advanced analytics",
"Priority builds"
],
cta: { text: "Start Free Trial", href: "/signup?plan=pro" },
highlighted: true
},
{
name: "Team",
price: "$199/mo",
description: "For development teams",
features: [
"10M API calls/mo",
"100GB bandwidth",
"Priority support",
"Unlimited private repos",
"Team collaboration",
"Custom domains",
"SSO"
],
cta: { text: "Start Free Trial", href: "/signup?plan=team" }
}
]}
/>Content Platform Pricing
<Pricing
title="Pricing for creators"
tiers={[
{
name: "Free",
price: "$0",
features: [
"Up to 100 subscribers",
"Basic email templates",
"Limited analytics"
],
cta: { text: "Start Free", href: "/signup" }
},
{
name: "Creator",
price: "$15/mo",
description: "Most popular",
features: [
"Up to 1,000 subscribers",
"Custom email templates",
"Full analytics",
"No platform fees",
"Custom domain"
],
cta: { text: "Start Free Trial", href: "/signup?plan=creator" },
highlighted: true
},
{
name: "Business",
price: "$49/mo",
features: [
"Up to 10,000 subscribers",
"Advanced automation",
"A/B testing",
"Priority support",
"API access",
"Remove branding"
],
cta: { text: "Start Free Trial", href: "/signup?plan=business" }
}
]}
/>Pricing Toggle
Implementation
The toggle switches between monthly and annual pricing:
const [interval, setInterval] = useState<'monthly' | 'annual'>('monthly')
<div className="pricing-toggle">
<button
className={interval === 'monthly' ? 'active' : ''}
onClick={() => setInterval('monthly')}
>
Monthly
</button>
<button
className={interval === 'annual' ? 'active' : ''}
onClick={() => setInterval('annual')}
>
Annual
<span className="badge">Save 20%</span>
</button>
</div>Data Structure
Provide both monthly and annual prices:
const tiers = [
{
name: "Pro",
monthlyPrice: "$29/mo",
annualPrice: "$24/mo",
annualNote: "Billed annually ($288/year)",
features: [...],
cta: { text: "Start Trial", href: "/signup" }
}
]
// Display logic
const displayPrice = interval === 'monthly'
? tier.monthlyPrice
: tier.annualPriceAccessibility
The reference implementation includes:
- Semantic HTML - Uses
<section>,<h2>,<h3>,<ul>,<li> - ARIA Labels - Proper labeling for pricing cards
- Keyboard Navigation - All CTAs keyboard accessible
- Focus Management - Visible focus states
- Screen Readers - Descriptive content for assistive tech
<section className="pricing" aria-labelledby="pricing-title">
<h2 id="pricing-title">{title}</h2>
<div className="pricing-grid" role="list">
{tiers.map(tier => (
<article
className="pricing-tier"
role="listitem"
aria-label={`${tier.name} plan, ${tier.price}`}
>
<h3>{tier.name}</h3>
<p className="price" aria-label={`Price: ${tier.price}`}>
{tier.price}
</p>
<ul aria-label={`${tier.name} features`}>
{tier.features.map(feature => (
<li key={feature}>{feature}</li>
))}
</ul>
<a href={tier.cta.href} className="cta">
{tier.cta.text}
</a>
</article>
))}
</div>
</section>Best Practices
Tier Naming
- Keep it simple: "Starter", "Pro", "Enterprise"
- Avoid clever names: Clear > cute
- Be consistent: Don't mix styles
- Show progression: Free → Pro → Enterprise
Price Display
- Be clear: Include billing period
- Use consistent format: Pick one style
- Highlight savings: "Save 20%" for annual
- Explain custom pricing: "Contact Sales" > "Custom"
Features
- Be specific: "100GB storage" > "More storage"
- Order by value: Most important first
- Keep it scannable: 5-10 features per tier
- Use plain language: Avoid jargon
Highlighted Tier
- One per section: Don't highlight multiple
- Make it obvious: Clear visual distinction
- Label it: "Most Popular", "Best Value"
- Place in center: On desktop layouts
CTAs
- Vary by tier: Free = "Sign Up", Paid = "Start Trial"
- Be specific: "Start 14-Day Trial" > "Get Started"
- Use action verbs: "Start", "Try", "Contact"
- Keep consistent: Same CTA text for similar tiers
Composition
In LandingPage
Pricing typically follows features:
<LandingPage>
<Hero {...heroProps} />
<Features {...featuresProps} />
<Pricing {...pricingProps} />
<Testimonials {...testimonialsProps} />
<FAQ {...faqProps} />
<CTA {...ctaProps} />
</LandingPage>With FAQ
Place FAQ after pricing to address price objections:
<Pricing {...pricingProps} />
<FAQ
title="Pricing FAQ"
items={[
{
question: "Can I change plans anytime?",
answer: "Yes, upgrade or downgrade at any time."
},
{
question: "What payment methods do you accept?",
answer: "We accept all major credit cards and PayPal."
}
]}
/>TypeScript
Full type definitions:
import { z } from 'zod'
import type { Component } from 'mdxui'
import { CTASchema } from 'mdxui/zod'
export const PricingTierSchema = z.object({
name: z.string(),
price: z.string(),
description: z.string().optional(),
features: z.array(z.string()),
cta: CTASchema,
highlighted: z.boolean().default(false),
})
export const PricingPropsSchema = z.object({
title: z.string().optional(),
description: z.string().optional(),
tiers: z.array(PricingTierSchema),
showToggle: z.boolean().default(false),
})
export type PricingTier = z.infer<typeof PricingTierSchema>
export type PricingProps = z.infer<typeof PricingPropsSchema>
export type Pricing = Component<PricingProps>Related Components
- Features Section - Show features before pricing
- FAQ Section - Answer pricing questions
- CTA Section - Convert after showing pricing
- Button - CTA button component