Back to Component Explorer
Plan Select Sign Up
signupPricing plan selector (Free/Pro/Team) with dynamic form per plan.
#signup#plan#pricing#saas
Live Interactive Preview
Get started
Choose a plan, then create your account
Component Source Code
Select language in the dropdownPlanSignUp.tsx
1'use client';2import React, { useState } from 'react';3import { Mail, Lock, User, Building2, ArrowRight } from 'lucide-react';45const PLANS = [6 { id: 'free', label: 'Free', price: '$0', desc: 'Perfect to start' },7 { id: 'pro', label: 'Pro', price: '$12', desc: 'For professionals' },8 { id: 'team', label: 'Team', price: '$49', desc: 'Built for teams' },9];1011export default function PlanSignUp() {12 const [plan, setPlan] = useState('free');13 const [loading, setLoading] = useState(false);14 const submit = (e: React.FormEvent) => { e.preventDefault(); setLoading(true); setTimeout(() => setLoading(false), 1500); };15 return (16 <div className="w-full max-w-md rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 p-8 shadow-lg">17 <div className="mb-6">18 <h2 className="text-xl font-bold text-zinc-900 dark:text-zinc-100">Get started</h2>19 <p className="mt-1 text-xs text-zinc-500">Choose a plan, then create your account</p>20 </div>2122 {/* Plan selector */}23 <div className="grid grid-cols-3 gap-2 mb-6">24 {PLANS.map((p) => (25 <button26 key={p.id}27 type="button"28 onClick={() => setPlan(p.id)}29 className={`flex flex-col items-center rounded-xl border-2 p-3 text-center transition ${plan === p.id ? 'border-blue-600 bg-blue-50 dark:bg-blue-950' : 'border-zinc-200 dark:border-zinc-800 hover:border-zinc-300 dark:hover:border-zinc-700'}`}30 >31 <span className={`text-xs font-bold ${plan === p.id ? 'text-blue-600 dark:text-blue-400' : 'text-zinc-700 dark:text-zinc-300'}`}>{p.label}</span>32 <span className={`text-base font-extrabold ${plan === p.id ? 'text-blue-600 dark:text-blue-400' : 'text-zinc-900 dark:text-zinc-100'}`}>{p.price}</span>33 <span className="text-[10px] text-zinc-400 mt-0.5">{p.desc}</span>34 </button>35 ))}36 </div>3738 <form onSubmit={submit} className="space-y-3.5">39 <div className="grid grid-cols-2 gap-3">40 <div>41 <label className="block text-xs font-semibold text-zinc-700 dark:text-zinc-300 mb-1.5">First name</label>42 <div className="relative">43 <User className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-zinc-400" />44 <input type="text" required placeholder="Alex" className="w-full rounded-lg border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800 py-2.5 pl-8 pr-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 outline-none focus:border-blue-500 transition" />45 </div>46 </div>47 <div>48 <label className="block text-xs font-semibold text-zinc-700 dark:text-zinc-300 mb-1.5">Last name</label>49 <input type="text" required placeholder="Johnson" className="w-full rounded-lg border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800 px-3 py-2.5 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 outline-none focus:border-blue-500 transition" />50 </div>51 </div>52 <div>53 <label className="block text-xs font-semibold text-zinc-700 dark:text-zinc-300 mb-1.5">Work email</label>54 <div className="relative">55 <Mail className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400" />56 <input type="email" required placeholder="you@company.com" className="w-full rounded-lg border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800 py-2.5 pl-9 pr-3 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 outline-none focus:border-blue-500 transition" />57 </div>58 </div>59 {plan !== 'free' && (60 <div>61 <label className="block text-xs font-semibold text-zinc-700 dark:text-zinc-300 mb-1.5">Company</label>62 <div className="relative">63 <Building2 className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400" />64 <input type="text" placeholder="Acme Corp" className="w-full rounded-lg border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800 py-2.5 pl-9 pr-3 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 outline-none focus:border-blue-500 transition" />65 </div>66 </div>67 )}68 <div>69 <label className="block text-xs font-semibold text-zinc-700 dark:text-zinc-300 mb-1.5">Password</label>70 <div className="relative">71 <Lock className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400" />72 <input type="password" required placeholder="Create password" className="w-full rounded-lg border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-800 py-2.5 pl-9 pr-3 text-sm text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 outline-none focus:border-blue-500 transition" />73 </div>74 </div>75 <button type="submit" disabled={loading} className="flex w-full items-center justify-center gap-2 rounded-lg bg-blue-600 hover:bg-blue-700 py-2.5 text-sm font-semibold text-white transition disabled:opacity-60">76 {loading ? 'Creating...' : <><span>Start {PLANS.find(p => p.id === plan)?.label} Plan</span><ArrowRight className="h-4 w-4" /></>}77 </button>78 </form>79 </div>80 );81}Installation & Integration Guide
Step 1: Tailwind CSS v4 Setup
Tailwind DocsIf you do not have Tailwind installed yet, run this installation command:
Terminal
npm install tailwindcss @tailwindcss/postcss postcss
Then add the Tailwind directive to your main stylesheet (globals.css):
@import "tailwindcss";
Step 2: Install Icon Dependencies
npm install lucide-react react-icons
Step 3: Add Component File
Create a new file in your project at src/components/signup/PlanSignUp.tsx and paste the copied code from the source viewer above.
Step 4: Usage Example
ExamplePage.tsx
1import PlanSelectSignUp from '@/components/signup/PlanSignUp';23export default function ExamplePage() {4 return (5 <main className="p-8 flex items-center justify-center min-h-screen">6 <PlanSelectSignUp />7 </main>8 );9}