Login Form
Clean sign-in form with email, password, remember-me checkbox, and inline validation. Built with react-hook-form and Zod for type-safe schema validation — errors appear instantly on blur.
Welcome back
Sign in to your account to continue
No account? Create one
import { LoginForm } from "@aetherstack/patterns"
Installation
terminal
pnpm add react-hook-form zod @hookform/resolversImport
import.tsx
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Button, Input, Label, Checkbox } from "@aetherstack/ui"
import { toast } from "@aetherstack/ui"Usage
login-form.tsx
const schema = z.object({
email: z.string().email("Enter a valid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
remember: z.boolean().optional(),
})
type FormValues = z.infer<typeof schema>
export function LoginForm() {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<FormValues>({
resolver: zodResolver(schema),
})
async function onSubmit(data: FormValues) {
await signIn(data.email, data.password)
toast({ variant: "success", title: "Signed in", description: `Welcome back, ${data.email}` })
}
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4" noValidate>
<div className="space-y-1.5">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" {...register("email")} />
{errors.email && <p className="text-xs text-destructive">{errors.email.message}</p>}
</div>
<div className="space-y-1.5">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" placeholder="••••••••" {...register("password")} />
{errors.password && <p className="text-xs text-destructive">{errors.password.message}</p>}
</div>
<div className="flex items-center gap-2">
<Checkbox id="remember" {...register("remember")} />
<Label htmlFor="remember" className="font-normal">Remember me</Label>
</div>
<Button type="submit" className="w-full" disabled={isSubmitting}>
{isSubmitting ? "Signing in…" : "Sign in"}
</Button>
</form>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| schema | ZodObject | — | Zod validation schema. Email must be a valid address; password requires minimum 8 characters. |
| register | UseFormRegister<FormValues> | — | react-hook-form register function — wires native inputs to the form state. |
| handleSubmit | (handler) => FormEventHandler | — | Wraps your submit handler to run validation first and only call your function when the form is valid. |
| errors | FieldErrors<FormValues> | — | Validation error messages keyed by field name, displayed as red helper text beneath each input. |
| isSubmitting | boolean | — | True while the submit handler is pending. Used to disable the submit button and show a loading label. |
* Required
Accessibility
- →All inputs have explicit <Label> elements connected via htmlFor/id pairs.
- →aria-invalid is set on inputs that have validation errors.
- →Error messages are rendered in <p> elements adjacent to the field — screen readers read them in context.
- →The submit button is disabled while submitting to prevent duplicate submissions.
- →noValidate on the form disables native browser validation so custom messages are always shown.