Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Form examples · Layouts

Spacious Form with Sections for React

A spacious form split into Personal Information and Address sections, each with its own heading and description.

Framework
UI library

Longer forms read better in sections. This one has two FieldSets, Personal Information and Address, each with a FieldLegend, a FieldDescription and its own FieldGroup of fields, and generous gaps between everything. Each Field has its FieldLabel, Input, an optional FieldDescription and its FieldError, wired to React Hook Form with a Controller and checked by one Zod schema. Use it for registration, account settings and onboarding.

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

Where does the extra space come from?

The outer FieldGroup is gap-8, so the two sections and Save Changes sit well apart. Inside each section, the fields' FieldGroup is gap-6. The form is max-w-2xl.

How are the two sections labeled?

Each section is a FieldSet with a FieldLegend, Personal Information or Address, and a FieldDescription under it: Tell us about yourself. and Where are you located? The legend names the group for screen readers too.

What does the schema check?

firstName, lastName, street and city are z.string().min(2) and email is z.email(). There are no custom messages, so FieldError shows Zod's defaults.

Which fields have helper text?

First name says Your legal first name., last name says Your legal last name. and email says Your primary email address. Street and city have no FieldDescription.

How is email different from the other inputs?

It sets type="email" and the placeholder john@example.com. The other four are text inputs with John, Doe, 123 Main St and New York as placeholders.

What does Save Changes submit?

The button is type="submit". defaultValues starts all five fields as empty strings, and onSubmit logs them once the resolver passes.