Growth Plans
Growth Plans é um componente para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
UI Layouts
MIT
other
O que é
Growth Plans é um componente para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
Como usar
Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.
Cinco cópias grátis por mês. Sem cartão.
Precisa de
npm i motion
Licença
Este componente vem de UI Layouts e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.
Growth Plans
'use client'
import React, { useState } from 'react'
import { Check } from 'lucide-react'
import { motion } from 'motion/react'
import NumberFlow from '@number-flow/react'
import { useId } from 'react'
// import { Button } from '@repo/ui/shadcn'
import { cn } from '@/lib/utils'
import { Switch, Button } from '@repo/shadcn'
const PLANS = [
{
name: 'Basic Plan',
description: 'Ideal for small businesses',
monthly: 29,
yearly: 23,
features: [
'Unified dashboard',
'Finance management module',
'Inventory control',
'Basic reporting and analytics',
'10 user accounts',
],
variant: 'outline' as const,
},
{
name: 'Business Plan',
description: 'For growing businesses',
monthly: 59,
yearly: 47,
features: [
'Everything in basic plan',
'HR & payroll module',
'Sales & CRM module',
'Workflow automation',
'Advanced analytics & reporting',
],
variant: 'secondary' as const,
featured: true,
},
{
name: 'Premium Plan',
description: 'Ideal for enterprises seeking',
monthly: 99,
yearly: 79,
features: [
'Everything in business plan',
'Custom integrations',
'AI-Driven recommendations',
'Role based access control',
'Unlimited user accounts',
],
variant: 'outline' as const,
},
]
export const GrowthPlans = () => {
const [billing, setBilling] = useState<'monthly' | 'yearly'>('yearly')
const id = useId()
return (
<section className="py-24 bg-white font-dmSans text-black">
<div className="max-w-6xl mx-auto px-6 text-center">
<h2 className="text-4xl font-semibold tracking-tight mb-2 text-balance">
Plans that grow your SASS.
</h2>
<p className="text-neutral-500 mb-5 text-pretty">
Unlock potential with plans designed to fuel growth.
</p>
<div className="flex items-center justify-center gap-4 mb-16 bg-neutral-100 border border-neutral-200 w-fit p-3 mx-auto">
<span
className={cn(
'text-sm transition-colors',
billing === 'monthly'
? 'text-neutral-900 font-medium'
: 'text-neutral-400'
)}
>
Monthly
</span>
<Switch
id={id}
// @ts-ignore
checked={billing === 'yearly'}
className="bg-neutral-300"
// @ts-ignore
onCheckedChange={(checked) =>
setBilling(checked ? 'yearly' : 'monthly')
}
/>
<div className="flex items-center gap-2">
<span
className={cn(
'text-sm transition-colors',
billing === 'yearly'
? 'text-neutral-900 font-medium'
: 'text-neutral-400'
)}
>
Yearly
</span>
<span className="px-2 py-0.5 bg- text-[10px] font-bold rounded-full uppercase">
Save 20%
</span>
</div>
</div>
<div className="grid lg:grid-cols-3 -gap-x-4 items-stretch">
{PLANS.map((plan) => (
<div
key={plan.name}
className={cn(
'rounded-lg p-8 flex flex-col border transition-all',
plan.featured
? 'bg-neutral-950 text-white scale-105 shadow-2xl z-10 border-transparent'
: 'bg-neutral-100 border border-neutral-200'
)}
>
<div className="text-left mb-8">
<h4 className="font-bold text-lg">{plan.name}</h4>
<p
className={cn(
'text-sm',
plan.featured ? 'text-neutral-400' : 'text-neutral-400'
)}
>
{plan.description}
</p>
</div>
<div className="flex items-baseline gap-1 mb-8 text-left">
<span
className={cn(
'text-2xl font-medium',
plan.featured ? 'text-gre' : 'text-neutral-400'
)}
>
$
</span>
<span
className={cn(
'text-5xl font-bold ',
plan.featured ? 'text-white' : 'text-neutral-900'
)}
>
<NumberFlow
value={billing === 'monthly' ? plan.monthly : plan.yearly}
/>
</span>
<span className="text-neutral-400 text-sm">/monthly</span>
</div>
<Button
variant={plan.variant}
className={cn(
'w-full mb-10 rounded-lg h-14',
plan.featured
? 'py-4 bg-neutral-800 border border-neutral-700'
: 'bg-white border-neutral-200 hover:shadow-neutral-200 hover:shadow-lg hover:bg-white'
)}
>
Select Plan
</Button>
<div
className={cn(
'space-y-4 pt-8 border-t text-left',
plan.featured ? 'border-neutral-700' : 'border-neutral-200'
)}
>
{plan.features.map((f, i) => (
<div
key={i}
className={cn(
'flex items-center gap-3 text-sm',
plan.featured ? 'text-neutral-300' : 'text-neutral-600'
)}
>
<Check className="size-4 shrink-0" />
{f}
</div>
))}
</div>
</div>
))}
</div>
</div>
</section>
)
}
import type { Variants } from 'motion/react';
import { type HTMLMotionProps, motion, useInView } from 'motion/react';
import type React from 'react';
type TimelineContentProps<T extends keyof HTMLElementTagNameMap> = {
children?: React.ReactNode;
animationNum: number;
className?: string;
timelineRef: React.RefObject<HTMLElement | null>;
as?: T;
customVariants?: Variants;
once?: boolean;
} & HTMLMotionProps<T>;
export const TimelineAnimation = <T extends keyof HTMLElementTagNameMap = 'div'>({
children,
animationNum,
timelineRef,
className,
as,
customVariants,
once = true,
...props
}: TimelineContentProps<T>) => {
const defaultSequenceVariants = {
visible: (i: number) => ({
filter: 'blur(0px)',
y: 0,
opacity: 1,
transition: {
delay: i * 0.5,
duration: 0.5,
},
}),
hidden: {
filter: 'blur(20px)',
y: 0,
opacity: 0,
},
};
const sequenceVariants = customVariants || defaultSequenceVariants;
const isInView = useInView(timelineRef, {
once,
});
const MotionComponent = motion[as || 'div'] as React.ElementType;
return (
<MotionComponent
initial='hidden'
animate={isInView ? 'visible' : 'hidden'}
custom={animationNum}
variants={sequenceVariants}
className={className}
{...props}
>
{children}
</MotionComponent>
);
};