Form
Fully-featured form component with validation, error messages, and more. Built on top of React Hook Form and zod.
Installation
npx @rahimstack@latest add formUsage
import {defineSchema, Field, Form} from "@/workshop/form"
 
const schema = defineSchema(({ z, presets }) => z.object({
    name: z.string().min(2),
    birthday: presets.datePicker,
    bounty: z.string()
        .refine(v => Number(v) >= 3_000_000_000,
            { message: "Bounty must be at least ฿3,000,000,000" })
}))
 
export function FormDemo() {
    return (
        <Form
            schema={schema}
            onSubmit={data => {/* ... */}}
            defaultValues={/* ... */}
        >
            <div className="flex gap-3">
                <Field.Text name="name" label="Name" />
                <Field.DatePicker name="birthday" label="Birthday" />
            </div>
            <Field.Currency
                name="bounty"
                label="Bounty"
                prefix="฿"
            />
            <Field.Submit role="save">Save</Field.Submit>
        </Form>
    )
}Define a schema
You can define a schema using the defineSchema function. This function takes a callback function that provides you with a z object and a presets object.
The z object is the zod library, and the presets object contains some useful presets for common form fields.
You can see or edit the presets in @/components/ui/form/schema-presets.ts.
Example
import { defineSchema } from "@/components/ui/form"
 
const schema = defineSchema(({z, presets}) => z.object({
    name: z.string().min(2),
    birthday: presets.datePicker,
    phone: presets.phone,
    profilePicture: presets.files,
    // ...
}))Render the form
import { Form, Field, defineSchema } from "@/components/ui/form"
 
const schema = defineSchema(({ z, presets }) => z.object({
    full_name: z.string().min(2),
    phone: presets.phone,
}))
 
export function FormDemo() {
    return (
        <Form
            schema={schema}
            onSubmit={data => { // `data` is correctly typed
                console.log("full_name", data.full_name)
                console.log("phone", data.phone)
            }}
        >
            <Field.Text
                label="Full name"
                name="full_name"
            />
            <Field.PhoneNumber
                label="Phone"
                name="phone"
            />
            <Field.Submit>Submit</Field.Submit>
        </Form>
    )
}Field
Field is a polymorphic component made with pre-built input components.
You can see the implementation of these inputs in @/components/ui/form/fields.tsx.
Submit
Field.Submit is a button that submits the form. It has some built-in features:
- Setting disableIfInvalidtotruewill disable the button if the form is invalid.
- Setting showLoadingOverlayOnCreatetotruewill render a loading overlay when theroleis"create"and the form is submitted. (This istrueby default)
- Setting showLoadingOverlayOnSuccesstotruewill render a loading overlay when the form is submitted.
- Setting disableOnSuccesstotruewill disable the button when the form is submitted. (This istrueby default whenroleis"create")
API Reference
No styles