Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Two Field Form for React

A short contact form with name and email, a description under each, and a separate error for each field.

Name needs 2 characters and says Your full name. Email must be an address and says Your email address. Both start empty. Submit checks them together.

Use it for a contact request or a waitlist. A message as well means adding a Textarea. In React, Base UI does not write the descriptions.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Usage

<form className="w-full max-w-md" onSubmit={form.handleSubmit(onSubmit)}>
  <FieldGroup>
    <Controller
      control={form.control}
      name="name"
      render={({ field, fieldState }) => (
        <Field invalid={fieldState.invalid}>
          <FieldLabel htmlFor="two-field-form-name">Name</FieldLabel>
          <Input
            {...field}
            id="two-field-form-name"
            placeholder="John Doe"
          />
          <FieldDescription>Your full name.</FieldDescription>
          <FieldError>{fieldState.error?.message}</FieldError>
        </Field>
      )}
    />
    <Controller
      control={form.control}
      name="email"
      render={({ field, fieldState }) => (
        <Field invalid={fieldState.invalid}>
          <FieldLabel htmlFor="two-field-form-email">Email</FieldLabel>
          <Input
            {...field}
            id="two-field-form-email"
            placeholder="john@example.com"
            type="email"
          />
          <FieldDescription>Your email address.</FieldDescription>
{/* The rest of the file is under Installation. */}

FAQ

Which two fields does this form register?

name is z.string().min(2, …) with "Name must be at least 2 characters." email is z.email(…) with "Please enter a valid email address." Each has its own Controller, and the input takes the controller's field props.

What do the descriptions say?

Name's FieldDescription is "Your full name." Email's is "Your email address." The placeholders are John Doe and john@example.com.

How is the email input different from name?

It sets type="email", so phones show an email keyboard; name is a text input. Each FieldLabel has an htmlFor that matches its input's id, such as two-field-form-email.

What are the starting values?

defaultValues sets email and name to empty strings, so an empty submit fails both rules. The form is w-full max-w-md.

What does Submit pass to onSubmit?

Submit is a type="submit" button. form.handleSubmit(onSubmit) calls the handler with { email, name } only after the schema passes, and the demo logs that object to the console.

When do the name and email errors show?

useForm doesn't set mode, so the resolver runs on submit, then again on each change once a field has an error. The Field gets invalid and its FieldError shows the field's message under the description.

API Reference

Field

Sets invalid={fieldState.invalid}, htmlFor="two-field-form-name", htmlFor="two-field-form-email" and orientation="horizontal". The rest is on the Field page.

Input

Sets field, id="two-field-form-name", placeholder="John Doe", id="two-field-form-email", placeholder="john@example.com" and type="email". The rest is on the Input page.

Button

Sets type="submit". The rest is on the Button page.