PricingCard.tsx
A feature-rich pricing card component with Stripe integration, discount support, and checkout functionality.
The PricingCard component displays product pricing with Stripe integration, automatic discount calculations, and built-in checkout functionality. It's designed for subscription and one-time payment products.
Props
| PricingCard Props | Type | Default |
|---|---|---|
name | string | - |
description | string | - |
unitAmount | number | - |
currency | string | - |
priceType | string | - |
priceId | string | - |
couponId | string | null | - |
amountOff | number | null | - |
percentOff | number | null | - |
isCouponValid | boolean | - |
marketingFeatures | Array<{ name: string }> | - |
cta | { text: string } | - |
className? | string | - |
Usage
Basic Pricing Card
import { PricingCard } from '@/components/pricing/PricingCard';
export default function PricingPage() {
return (
<PricingCard
name="Pro"
description="Perfect for growing teams"
unitAmount={2999}
currency="usd"
priceType="recurring"
priceId="price_1234567890"
couponId={null}
amountOff={null}
percentOff={null}
isCouponValid={false}
marketingFeatures={[
{ name: 'Unlimited projects' },
{ name: 'Priority support' },
{ name: 'Advanced analytics' },
]}
cta={{ text: 'Get Started' }}
/>
);
}With Discount Coupon
<PricingCard
name="Enterprise"
description="For large organizations"
unitAmount={9999}
currency="usd"
priceType="recurring"
priceId="price_0987654321"
couponId="SAVE20"
amountOff={null}
percentOff={20}
isCouponValid={true}
marketingFeatures={[
{ name: 'Unlimited everything' },
{ name: 'Dedicated support' },
{ name: 'Custom integrations' },
]}
cta={{ text: 'Contact Sales' }}
/>Fetching from Stripe API
import { PricingCard } from '@/components/pricing/PricingCard';
async function getPricingData() {
const res = await fetch('/api/stripe/products');
return res.json();
}
export default async function PricingPage() {
const { products, coupons } = await getPricingData();
return (
<div className="grid grid-cols-3 gap-6">
{products.map((product) => (
<PricingCard
key={product.priceId}
name={product.name}
description={product.description}
unitAmount={product.unitAmount}
currency={product.currency}
priceType={product.priceType}
priceId={product.priceId}
couponId={coupons[0]?.id || null}
amountOff={coupons[0]?.amountOff || null}
percentOff={coupons[0]?.percentOff || null}
isCouponValid={coupons[0]?.valid || false}
marketingFeatures={product.marketingFeatures}
cta={{ text: 'Subscribe' }}
/>
))}
</div>
);
}Features
- Stripe Integration: Built-in form submission to
/api/stripe/checkout - Discount Calculation: Automatic price calculation for fixed and percentage discounts
- Responsive Design: Adapts to mobile, tablet, and desktop screens
- Visual Feedback: Hover effects and border highlights
- Feature List: Displays marketing features with checkmark icons
- Flexible Pricing: Supports recurring subscriptions and one-time payments
Implementation Details
Discount Logic
The component calculates discounts using the checkDiscount function:
- Fixed Amount: Subtracts
amountOfffromunitAmount - Percentage: Calculates percentage of
unitAmount - Validation: Only applies discount if
isCouponValidis true
Checkout Flow
The component renders a form that submits to /api/stripe/checkout:
- User clicks the CTA button
- Form submits
priceIdand optionalcouponId - API route creates Stripe checkout session
- User redirects to Stripe checkout page
Styling
The component uses Tailwind CSS with custom design tokens:
bg-surface- Card backgroundborder-neutral- Default border colorborder-brand-highlight- Hover border colortext-brand-highlight- Tier name colortext-foreground- Price colortext-neutral-foreground- Description and features color
Related
- Pricing.tsx - Pricing section wrapper
- Stripe Integration - Payment setup
- Button.tsx - CTA button component
How is this guide ?
Last updated on