Form

Form wires React Hook Form to accessible fields, labels, and validation messages.

This is your public display name.

Installation

Nothing to add. This component ships as source in your download, so it is already in your project.

Filesrc/vui/form.tsx
Import from@viliha/vui-react/form

The exported names are at the top of that file. The import path is an alias the download's tsconfig.json points at src/vui/, so you can move that folder and change one line rather than every file that imports from it.

Usage

A thin wrapper over React Hook Form. FormField wires each control to the form; FormMessage renders the field error.

form-demo.tsx
import { useForm } from "react-hook-form";
import {
  Form, FormField, FormItem, FormLabel, FormControl,
  FormDescription, FormMessage,
} from "@viliha/vui-react/form";
import { Input } from "@viliha/vui-react/input";
import { Button } from "@viliha/vui-react/button";

export function Example() {
  const form = useForm({ defaultValues: { username: "" } });
  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(console.log)}>
        <FormField
          control={form.control}
          name="username"
          rules={{ required: "Username is required" }}
          render={({ field }) => (
            <FormItem>
              <FormLabel>Username</FormLabel>
              <FormControl>
                <Input placeholder="viliha" {...field} />
              </FormControl>
              <FormDescription>Your public display name.</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">Submit</Button>
      </form>
    </Form>
  );
}

Validation

Use RHF rules (shown here) or plug in a schema resolver like zod via @hookform/resolvers; both are consumer-side; the package only depends on react-hook-form.

FormControl props

It takes no props of its own. Everything you pass reaches the underlying <p> element, so every attribute it accepts works here unchanged and nothing is invented on top.

FormDescription props

It takes no props of its own. Everything you pass reaches the underlying <p> element, so every attribute it accepts works here unchanged and nothing is invented on top.

FormField props

It takes no props of its own. Everything you pass reaches the underlying ControllerProps<TFieldValues, TName> primitive, so every attribute it accepts works here unchanged and nothing is invented on top.

FormItem props

It takes no props of its own. Everything you pass reaches the underlying <div> element, so every attribute it accepts works here unchanged and nothing is invented on top.

FormLabel props

It takes no props of its own. Everything you pass reaches the underlying LabelPrimitive.Root primitive, so every attribute it accepts works here unchanged and nothing is invented on top.

FormMessage props

It takes no props of its own. Everything you pass reaches the underlying <p> element, so every attribute it accepts works here unchanged and nothing is invented on top.