Forms and feedback

Build a semantic form

Compose a card, labels, inputs, and a submit button while keeping the native form contract visible and usable.

8 minute lesson

~~~

Let’s build a form before adding any validation library. This gives us a solid HTML foundation first.

Add the Button, Field, and Input components with the shadcn CLI. Then connect the label and input using htmlFor and id. The name attribute is what includes the value in FormData.

<form action={createProject}>
  <Field>
    <FieldLabel htmlFor='name'>Project name</FieldLabel>
    <Input id='name' name='name' />
  </Field>

  <Button type='submit'>Create project</Button>
</form>

Notice that shadcn/ui does not change how forms work. We still use a real form, a real input, and a submit button. The components give us a consistent design on top of those browser features.

The name is the server contract: an attractive input without one contributes nothing to FormData. Give fields useful autocomplete tokens and input types. Use fieldset and legend when several controls answer one question, and connect help text with aria-describedby. Placeholder text can show an example, but it disappears during typing and cannot replace a label.

Start with the native submission path before adding a form library. It exposes incorrect names, missing button types, accidental nested forms, and Enter-key surprises early. Browser autocomplete and keyboard submission are useful product features, not details to disable for visual consistency.

Add a labelled description field with an appropriate name and autocomplete decision. Submit it to an action that prints only the received key names. Test Enter, Tab order, browser autocomplete, and a directly constructed FormData object before adding client validation.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →