Skip to content
shadcn.io
shadcn.io is not affiliated with official shadcn/ui

Forms

A guide to building forms with shadcn.io components.

Picking a form library

For detailed guides with examples, validation, and field-type-specific patterns, see the linked pages above.

Field Context

Form components automatically integrate with Field through context. When nested inside a Field, they inherit disabled, invalid, required, and readOnly states automatically.

Also htmlFor and id are automatically handled by the Field component. Never use them directly.

import { Field } from "@/registry/react/components/field"
import { NumberInput } from "@/registry/react/components/number-input"

const Demo = () => (
  <Field disabled>
    <NumberInput>
      <NumberInputGroup>
        <NumberInputInput />
        <NumberInputIncrement />
        <NumberInputDecrement />
      </NumberInputGroup>
    </NumberInput>
  </Field>
)

Input states

Invalid

Pass the invalid prop to the Field component.

The FieldError is only visible when the invalid prop is true.

import {
  Field,
  FieldLabel,
  FieldError,
} from "@/registry/react/components/field"
import { Input } from "@/registry/react/components/input"

const Demo = () => (
  <form>
    <Field invalid>
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="Enter your username" />
      <FieldError>Username is required.</FieldError>
    </Field>
  </form>
)

Required

Pass the required prop to the Field component.

Optionally, you can use the FieldRequiredIndicator to indicate that the field is required.

import {
  Field,
  FieldLabel,
  FieldRequiredIndicator,
  FieldError,
} from "@/registry/react/components/field"
import { Input } from "@/registry/react/components/input"

export const Demo = () => (
  <form>
    <Field required>
      <FieldLabel>
        Username
        <FieldRequiredIndicator />
      </FieldLabel>
      <Input placeholder="Enter your username" />
      <FieldError>Username is required.</FieldError>
    </Field>
  </form>
)