components
Form field
Every Wolf form uses the same layout — label above control, helper below, error in destructive red. FormField standardises that shape and wires the a11y attributes for you.
Read the full specSign-in form
Label, input and error message bound by context — no manual `htmlFor` or `aria-describedby` required. Try submitting with a bad email to see the error wiring.
tsx
const schema = z.object({
email: z.string().email("Enter a valid email address"),
password: z.string().min(8, "Use at least 8 characters"),
});
const form = useForm<z.infer<typeof schema>>({
resolver: zodResolver(schema),
defaultValues: { email: "", password: "" },
});
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" {...field} />
</FormControl>
<FormDescription>We'll email you a magic link.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
…
<Button type="submit">Sign in</Button>
</form>
</Form>