Extended Form

PreviousNext

Enhanced form component with Zod schema validation and TypeScript support using react-hook-form.

Installation

pnpm dlx shadcn@latest add https://ui.nowts.app/r/extended-form.json

Usage

The ExtendedForm component provides type-safe forms with Zod validation:

import { z } from "zod"
 
import { ExtendedForm, useZodForm } from "@/components/ui/extended-form"
 
const schema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
})
 
export function MyForm() {
  const form = useZodForm({
    schema,
    defaultValues: {
      name: "",
      email: "",
    },
  })
 
  const onSubmit = async (data: z.infer<typeof schema>) => {
    console.log(data) // Fully typed!
  }
 
  return (
    <ExtendedForm form={form} onSubmit={onSubmit}>
      <input {...form.register("name")} />
      <input {...form.register("email")} />
      <button type="submit">Submit</button>
    </ExtendedForm>
  )
}

Features

Automatic Fieldset Management

The form automatically wraps your inputs in a <fieldset> that:

  • Disables all inputs during form submission
  • Can be manually disabled via the disabled prop
  • Prevents duplicate submissions

Type Safety

The useZodForm hook provides full TypeScript support:

const form = useZodForm({ schema })
// form is fully typed based on your Zod schema

Form State

Access form state from the hook:

const form = useZodForm({ schema })
 
console.log(form.formState.isSubmitting) // boolean
console.log(form.formState.errors) // typed errors
console.log(form.formState.isDirty) // boolean

With shadcn/ui Form

You can combine with shadcn/ui's Form components:

import { ExtendedForm, useZodForm } from "@/components/ui/extended-form"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
 
export function MyForm() {
  const form = useZodForm({ schema })
 
  return (
    <ExtendedForm form={form} onSubmit={onSubmit}>
      <FormField
        control={form.control}
        name="email"
        render={({ field }) => (
          <FormItem>
            <FormLabel>Email</FormLabel>
            <FormControl>
              <Input {...field} />
            </FormControl>
          </FormItem>
        )}
      />
    </ExtendedForm>
  )
}

Props

ExtendedForm

PropTypeRequiredDescription
formUseFormReturnYesForm instance from useZodForm
onSubmitSubmitHandlerYesForm submission handler
disabledbooleanNoManually disable the form
...formPropsFormHTMLAttributesNoStandard form attributes

useZodForm

PropTypeRequiredDescription
schemaZodTypeYesZod validation schema
...formPropsUseFormPropsNoreact-hook-form options