{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "signup", "title": "Sign Up Form", "description": "A dark-themed sign up form with name, email, and password fields, Google OAuth button, and loading state.", "dependencies": [], "registryDependencies": [], "files": [ { "path": "registry/default/signup/signup.tsx", "content": "\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useState } from \"react\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\nexport interface SignupFormProps {\r\n onSubmit?: (values: { name: string; email: string; password: string }) => void;\r\n onGoogleSignIn?: () => void;\r\n onSignIn?: () => void;\r\n className?: string;\r\n}\r\n\r\nexport function SignupForm({\r\n onSubmit,\r\n onGoogleSignIn,\r\n onSignIn,\r\n className,\r\n}: SignupFormProps) {\r\n const [name, setName] = useState(\"\");\r\n const [email, setEmail] = useState(\"\");\r\n const [password, setPassword] = useState(\"\");\r\n const [showPassword, setShowPassword] = useState(false);\r\n const [agreed, setAgreed] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const strength = (() => {\r\n if (password.length === 0) return 0;\r\n let score = 0;\r\n if (password.length >= 8) score++;\r\n if (/[A-Z]/.test(password)) score++;\r\n if (/[0-9]/.test(password)) score++;\r\n if (/[^A-Za-z0-9]/.test(password)) score++;\r\n return score;\r\n })();\r\n\r\n const strengthLabel = [\"\", \"Weak\", \"Fair\", \"Good\", \"Strong\"][strength];\r\n const strengthColor = [\"\", \"bg-red-500\", \"bg-yellow-500\", \"bg-blue-500\", \"bg-green-500\"][strength];\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!agreed) return;\r\n setLoading(true);\r\n await onSubmit?.({ name, email, password });\r\n setLoading(false);\r\n };\r\n\r\n return (\r\n \r\n {/* Header */}\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n

Create an account

\r\n

Start building something great today

\r\n
\r\n\r\n {/* Google Sign-Up */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n Continue with Google\r\n \r\n\r\n {/* Divider */}\r\n
\r\n
\r\n
\r\n
\r\n
\r\n or sign up with email\r\n
\r\n
\r\n\r\n {/* Form */}\r\n
\r\n {/* Name */}\r\n
\r\n \r\n setName(e.target.value)}\r\n placeholder=\"Jane Smith\"\r\n className=\"w-full rounded-xl border border-white/10 bg-white/5 px-4 py-2.5 text-sm text-white placeholder-neutral-600 outline-none transition-all focus:border-white/25 focus:bg-white/8 focus:ring-0\"\r\n />\r\n
\r\n\r\n {/* Email */}\r\n
\r\n \r\n setEmail(e.target.value)}\r\n placeholder=\"you@example.com\"\r\n className=\"w-full rounded-xl border border-white/10 bg-white/5 px-4 py-2.5 text-sm text-white placeholder-neutral-600 outline-none transition-all focus:border-white/25 focus:bg-white/8 focus:ring-0\"\r\n />\r\n
\r\n\r\n {/* Password */}\r\n
\r\n \r\n
\r\n setPassword(e.target.value)}\r\n placeholder=\"Min. 8 characters\"\r\n className=\"w-full rounded-xl border border-white/10 bg-white/5 px-4 py-2.5 pr-10 text-sm text-white placeholder-neutral-600 outline-none transition-all focus:border-white/25 focus:bg-white/8 focus:ring-0\"\r\n />\r\n setShowPassword((v) => !v)}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-neutral-600 hover:text-neutral-300 transition-colors\"\r\n tabIndex={-1}\r\n >\r\n {showPassword ? (\r\n \r\n \r\n \r\n ) : (\r\n \r\n \r\n \r\n \r\n )}\r\n \r\n
\r\n\r\n {/* Password strength bar */}\r\n {password.length > 0 && (\r\n
\r\n
\r\n {[1, 2, 3, 4].map((i) => (\r\n \r\n ))}\r\n
\r\n

\r\n Strength:{\" \"}\r\n \r\n {strengthLabel}\r\n \r\n

\r\n
\r\n )}\r\n
\r\n\r\n {/* Terms */}\r\n