improve(public): list all prices instead of slider + rewrite article
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { cn } from '@/lib/utils';
|
||||
import { PRICING } from '@openpanel/payments/src/prices';
|
||||
import { CheckIcon, ChevronRightIcon, DollarSignIcon } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { DoubleSwirl } from '../Swirls';
|
||||
import { PricingSlider } from '../pricing-slider';
|
||||
import { Section, SectionHeader } from '../section';
|
||||
import { Tag } from '../tag';
|
||||
import { Button } from '../ui/button';
|
||||
import { Tooltiper } from '../ui/tooltip';
|
||||
|
||||
export default Pricing;
|
||||
export function Pricing({ className }: { className?: string }) {
|
||||
@@ -17,7 +18,7 @@ export function Pricing({ className }: { className?: string }) {
|
||||
)}
|
||||
>
|
||||
<DoubleSwirl className="absolute top-0 left-0" />
|
||||
<div className="container relative z-10">
|
||||
<div className="container relative z-10 col">
|
||||
<SectionHeader
|
||||
tag={
|
||||
<Tag variant={'dark'}>
|
||||
@@ -29,11 +30,10 @@ export function Pricing({ className }: { className?: string }) {
|
||||
description="Just pick how many events you want to track each month. No hidden costs."
|
||||
/>
|
||||
|
||||
<div className="grid md:grid-cols-[400px_1fr] gap-8">
|
||||
<div className="grid self-center md:grid-cols-[200px_1fr] lg:grid-cols-[300px_1fr] gap-8">
|
||||
<div className="col gap-4">
|
||||
<h3 className="font-medium text-xl text-background/90 dark:text-foreground/90">
|
||||
Stop overpaying <br />
|
||||
for features
|
||||
Stop overpaying for features
|
||||
</h3>
|
||||
<ul className="gap-1 col text-background/70 dark:text-foreground/70">
|
||||
<li className="flex items-center gap-2">
|
||||
@@ -56,6 +56,10 @@ export function Pricing({ className }: { className?: string }) {
|
||||
<CheckIcon className="text-background/30 dark:text-foreground/30 size-4" />{' '}
|
||||
Unlimited tracked profiles
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="text-background/30 dark:text-foreground/30 size-4" />{' '}
|
||||
Yes, we have no limits or hidden costs
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<Button
|
||||
@@ -71,10 +75,112 @@ export function Pricing({ className }: { className?: string }) {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="col justify-between pt-14 gap-4">
|
||||
<PricingSlider />
|
||||
<div className="col justify-between gap-4 max-w-lg">
|
||||
<div className="space-y-2">
|
||||
{PRICING.map((tier) => (
|
||||
<div
|
||||
key={tier.events}
|
||||
className={cn(
|
||||
'group col',
|
||||
'backdrop-blur-3xl bg-foreground/70 dark:bg-background-dark/70',
|
||||
'p-4 py-2 border border-background/20 dark:border-foreground/20 rounded-lg hover:bg-background/5 dark:hover:bg-foreground/5 transition-colors',
|
||||
'mx-2',
|
||||
tier.discount &&
|
||||
'mx-0 px-6 py-3 !bg-emerald-900/20 hover:!bg-emerald-900/30',
|
||||
tier.popular &&
|
||||
'mx-0 px-6 py-3 !bg-orange-900/20 hover:!bg-orange-900/30',
|
||||
)}
|
||||
>
|
||||
<div className="row justify-between">
|
||||
<div>
|
||||
{new Intl.NumberFormat('en-US', {}).format(tier.events)}{' '}
|
||||
<span className="text-muted-foreground text-sm max-[420px]:hidden">
|
||||
events / month
|
||||
</span>
|
||||
</div>
|
||||
<div className="row gap-4">
|
||||
{tier.popular && (
|
||||
<>
|
||||
<Tag variant="dark" className="hidden md:inline-flex">
|
||||
🔥 Popular
|
||||
</Tag>
|
||||
<span className="md:hidden">🔥</span>
|
||||
</>
|
||||
)}
|
||||
{tier.discount && (
|
||||
<>
|
||||
<Tag
|
||||
variant="dark"
|
||||
className="hidden md:inline-flex whitespace-nowrap"
|
||||
>
|
||||
💸 Discount
|
||||
</Tag>
|
||||
<span className="md:hidden">💸</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<div className="row gap-1">
|
||||
{tier.discount && (
|
||||
<span className={cn('text-md font-semibold')}>
|
||||
{new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD',
|
||||
}).format(tier.price * (1 - tier.discount.amount))}
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
className={cn(
|
||||
'text-md font-semibold',
|
||||
tier.discount && 'line-through opacity-50',
|
||||
)}
|
||||
>
|
||||
{new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD',
|
||||
}).format(tier.price)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{tier.discount && (
|
||||
<div className="text-sm text-muted-foreground mt-2">
|
||||
Limited discount code available:{' '}
|
||||
<Tooltiper
|
||||
content={`Get ${tier.discount.amount * 100}% off your first year`}
|
||||
delayDuration={0}
|
||||
side="bottom"
|
||||
>
|
||||
<strong>{tier.discount.code}</strong>
|
||||
</Tooltiper>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<div
|
||||
className={cn(
|
||||
'group',
|
||||
'row justify-between p-4 py-2 border border-background/20 dark:border-foreground/20 rounded-lg hover:bg-background/5 dark:hover:bg-foreground/5 transition-colors',
|
||||
'mx-2',
|
||||
)}
|
||||
>
|
||||
<div className="whitespace-nowrap">
|
||||
Over{' '}
|
||||
{new Intl.NumberFormat('en-US', {}).format(
|
||||
PRICING[PRICING.length - 1].events,
|
||||
)}
|
||||
</div>
|
||||
<div className="text-md font-semibold">
|
||||
<Link
|
||||
href="mailto:support@openpanel.dev"
|
||||
className="group-hover:underline"
|
||||
>
|
||||
Contact us
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="self-center text-sm text-muted-foreground mt-4 text-center max-w-[70%] w-full">
|
||||
<strong className="text-background/80 dark:text-foreground/80">
|
||||
All features are included upfront - no hidden costs.
|
||||
</strong>{' '}
|
||||
|
||||
Reference in New Issue
Block a user