Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Form examples · Basic Forms

Simple Text Input Form for React

A form with one username text input that needs at least 2 characters.

Framework
UI library

The smallest validated form: one username field that needs at least 2 characters. useForm takes a Zod schema through zodResolver, a Controller connects the Input, and the Field around it holds the FieldLabel, a FieldDescription and a FieldError that shows the message inline. Start here for profiles, single-field settings or any form that needs typed values and clear errors.

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.

FAQ

How is the username input wired to React Hook Form?

useForm gets resolver: zodResolver(formSchema) and defaultValues of username: "". The Controller for name="username" renders the Input with field spread on it, so its value, onChange, onBlur and ref come from the form. FieldLabel htmlFor matches the input's id, simple-text-input-form-username.

Where does the 2 character error come from?

username is z.string().min(2, "Username must be at least 2 characters."). The Controller gives fieldState: invalid goes on the Field and error.message into FieldError.

What is the line under the input for?

FieldDescription stays on the page with "This is your public display name." The placeholder johndoe is only the empty-field hint.

When does this form validate?

useForm doesn't set mode, so React Hook Form validates on submit, then on each change after a failed submit. onSubmit only runs once the schema passes, and this demo logs the values.

What does the Submit button send?

Submit is a type="submit" button inside the form, whose onSubmit is form.handleSubmit(onSubmit). A username shorter than 2 characters never reaches that function.

Why is the username default an empty string?

defaultValues sets username to "", so the input is controlled from the first render and the placeholder shows. The schema still rejects that empty string on submit.