AuthForm
A flexible authentication form component supporting both sign in and sign up flows.
Usage
YourBanK
Sign In
Please enter your details
1
2
3
4
5
6
7
8
9
import AuthForm from "@/components/AuthForm"
export default function LoginPage() {
return (
<div className="max-w-sm mx-auto">
<AuthForm type="login" />
</div>
)
}Props
variant
The form variant to display: "login" or "register".
Type: "login" | "register" (optional, defaults to "login")
onSubmit
Callback function called when the form is submitted.
Type: (data: AuthFormData) => Promise<void> (optional)
className
Additional CSS classes to apply to the form container.
Type: string (optional)
Implementation
The complete implementation of the AuthForm component:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"use client"
import * as React from "react"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { cn } from "@/lib/utils"
const authFormSchema = z.object({
email: z.string().email("Please enter a valid email address"),
password: z
.string()
.min(8, "Password must be at least 8 characters")
.max(100, "Password must be less than 100 characters"),
})
export type AuthFormData = z.infer<typeof authFormSchema>
interface AuthFormProps {
variant?: "login" | "register"
onSubmit?: (data: AuthFormData) => Promise<void>
className?: string
}
export function AuthForm({
variant = "login",
onSubmit,
className,
}: AuthFormProps) {
const [isLoading, setIsLoading] = React.useState(false)
const form = useForm<AuthFormData>({
resolver: zodResolver(authFormSchema),
defaultValues: {
email: "",
password: "",
},
})
async function handleSubmit(data: AuthFormData) {
setIsLoading(true)
try {
await onSubmit?.(data)
} catch (error) {
console.error(error)
} finally {
setIsLoading(false)
}
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(handleSubmit)}
className={cn("space-y-6", className)}
>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input
placeholder="m@example.com"
type="email"
disabled={isLoading}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input
placeholder="••••••••"
type="password"
disabled={isLoading}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
className="w-full bg-[#39A36A] hover:bg-[#2E8754]"
disabled={isLoading}
>
{variant === "login" ? "Sign In" : "Sign Up"}
</Button>
</form>
</Form>
)
}