Auto Form
Component creates form based on Zod schemas & react-hook-form with validation
Preview
Usage
import { AutoForm } from "@vitnode/core/components/form/auto-form";
import { AutoFormCheckbox } from "@vitnode/core/components/form/fields/checkbox";
import { AutoFormInput } from "@vitnode/core/components/form/fields/input";
import { AutoFormSelect } from "@vitnode/core/components/form/fields/select";
import { AutoFormTextarea } from "@vitnode/core/components/form/fields/textarea";
import { z } from "zod";const formSchema = z.object({
username: z.string().min(3, "Username must be at least 3 characters"),
email: z
.email("Please enter a valid email address")
.describe("We'll use this email to contact you. (from zod schema)"),
user_type: z.enum(["admin", "editor", "viewer"]),
accept_terms: z.boolean().refine(val => val, {
message: "You must accept the terms and conditions",
}),
description: z.string().min(10, "Description must be at least 10 characters"),
});<AutoForm
fields={[
{
id: "username",
component: props => (
<AutoFormInput
{...props}
description="This is the username for your application. It should be unique and not shared with anyone."
label="Username"
/>
),
},
{
id: "email",
component: props => <AutoFormInput {...props} label="Email Address" />,
},
{
id: "user_type",
component: props => (
<AutoFormSelect
{...props}
description="Select the type of user."
label="User Type"
labels={[
{ value: "admin", label: "Admin" },
{ value: "editor", label: "Editor" },
{ value: "viewer", label: "Viewer" },
]}
/>
),
},
{
id: "accept_terms",
component: props => (
<AutoFormCheckbox
{...props}
label="I accept the terms and conditions"
/>
),
},
{
id: "description",
component: props => (
<AutoFormTextarea
{...props}
description="Write a short description of your application."
label="Description"
placeholder="My application is..."
/>
),
},
]}
formSchema={formSchema}
/>Zod Schema Configuration
Auto Form is deeply integrated with Zod, supporting Zod validators. HTML input attributes are automatically applied based on your schema constraints.
Required vs Optional Fields
By default, all fields are required. Make a field optional using the optional method:
const formSchema = z.object({
username: z.string(), // Required field
bio: z.string().optional(), // Optional field
});Labels
Set field labels using the label property in the field definition:
{
id: 'username',
component: props => (
<AutoFormInput {...props} label="Username" />
),
}Right Labels
You can also add a label on the right side of the field using the labelRight property:
{
id: 'username',
component: props => (
<AutoFormInput {...props} label="Username" labelRight="Required" />
),
}Descriptions
Add descriptions to fields using the description property:
{
id: 'username',
component: props => (
<AutoFormInput
{...props}
label="Username"
description="This is the username for your application."
/>
),
}or using the describe method in Zod:
const formSchema = z.object({
username: z.string().describe("This is the username for your application."),
});Default Values
Set default values for fields using the default method:
const formSchema = z.object({
username: z.string().default("user123"),
role: z.enum(["user", "admin"]).default("user"),
});Advanced Validation
Auto Form supports all Zod validators:
const formSchema = z.object({
username: z.string().min(3).max(20),
email: z.email(),
age: z.number().min(18).max(120),
password: z
.string()
.min(8)
.refine(val => /[A-Z]/.test(val), {
message: "Password must contain at least one uppercase letter",
}),
});Custom Fields
This documentation is under construction! 🚧
We're working hard to bring you the best documentation experience.
Form Submission
To activate submit button and handle form submission with the onSubmit callback:
<AutoForm
fields={[
{
id: "username",
component: props => (
<AutoFormInput
{...props}
description="This is the username for your application."
label="Username"
/>
),
},
]}
formSchema={formSchema}
onSubmit={values => {
// Handle form submission
}}
/>Accessing the Form Instance
The onSubmit callback provides access to the React Hook Form instance as a second parameter:
<AutoForm
fields={
[
/* ...field definitions */
]
}
formSchema={formSchema}
onSubmit={(values, form) => {
// Access form methods
form.setError("username", {
type: "manual",
message: "Username already taken",
});
}}
/>You can also define the submission handler separately:
import type { AutoFormOnSubmit } from "@vitnode/core/components/form/auto-form";const onSubmit: AutoFormOnSubmit<typeof formSchema> = async (values, form) => {
try {
await saveData(values);
toast.success("Form submitted successfully");
} catch (error) {
form.setError("root", {
type: "manual",
message: "Failed to submit form",
});
}
};
// Then in your component
<AutoForm
fields={
[
/* ...field definitions */
]
}
formSchema={formSchema}
onSubmit={onSubmit}
/>;Customizing the Submit Button
Customize the submit button using the submitButtonProps:
<AutoForm
fields={
[
/* ...field definitions */
]
}
formSchema={formSchema}
submitButtonProps={{
variant: "outline",
size: "lg",
children: "Save Changes",
className: "w-full mt-4",
}}
onSubmit={values => {
console.log("Form submitted", values);
}}
/>Form Layout and Styling
You can control the form layout using standard CSS techniques:
<AutoForm
className="grid grid-cols-1 gap-4 md:grid-cols-2"
fields={
[
/* ...field definitions */
]
}
formSchema={formSchema}
/>