Component

Form

Accessible form primitives built on react-hook-form. They wire labels, controls, descriptions, and error messages together with the correct ids and ARIA attributes, so any input becomes a fully-labelled, validated field.

Basic field

Spread useForm() into Form, then compose FormField FormItem FormLabel/FormControl/FormDescription/FormMessage.

This is your public display name.

Installation

$pnpm add @refraction-ui/react-form

Usage

tsx
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
  useForm,
} from '@refraction-ui/react/form'

export function SignUpForm() {
  const form = useForm({ defaultValues: { email: '' } })
  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(console.log)}>
        <FormField
          control={form.control}
          name="email"
          rules={{ required: 'Email is required.' }}
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <input placeholder="you@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <button type="submit">Submit</button>
      </form>
    </Form>
  )
}

Validation

Pass RHF rules to FormField. FormMessage renders the error and the label turns destructive automatically. Submit an empty or malformed email to see it.

Primitives

PropTypeDefaultDescription
FormFormProvider--React Hook Form provider. Spread the result of `useForm()` into it so descendants can read form state. Renders no DOM of its own.
FormFieldControllerProps--Connects a named field to RHF’s Controller and supplies field-name context to the descendant primitives. Accepts `control`, `name`, `rules`, and a `render` prop.
FormItemHTMLAttributes<HTMLDivElement>--Wraps one field and emits a stable id used by Label, Control, Description, and Message.
FormLabelLabelHTMLAttributes<HTMLLabelElement>--Field label, wired to the control via `htmlFor`. Turns destructive when the field is invalid.
FormControlHTMLAttributes<HTMLElement>--Slot that injects `id`, `aria-describedby`, and `aria-invalid` onto the input it wraps (a single child).
FormDescriptionHTMLAttributes<HTMLParagraphElement>--Helper text linked to the control via `aria-describedby`.
FormMessageHTMLAttributes<HTMLParagraphElement>--Renders the field’s validation error message (or its children when there is no error). Returns null when empty.
useFormField() => { id, name, error, invalid, … }--Hook exposing the current field’s ids and live error state — for building custom controls.