Summit
ComponentsFields

Field

A Field pairs one control with the label, the description, and the error message that tell users what to enter.

When to Use

  • for each control of a form: an Input, a Textarea, a Select, or a Slider
  • as a horizontal Field, to place a Checkbox, a radio, or a Switch next to its label
  • as a field set, to place several Fields under one legend, such as the lines of a billing address
  • as a choice card, when each option of a Radio Group needs a title and a description

When Not to Use

  • for a control whose name isn’t shown, such as the search box above a Table (set aria-label on the control)
  • for one control with a name and nothing else, such as the only Input of a Dialog (use a Label)

Anatomy

The parts in field.tsx build a Field, a field set, and a choice card.

Field

Invoices go to this address.

ElementUsage
LabelRequired
ControlRequired
DescriptionOptional
ErrorInvalid state only

Field stacks its children and stretches them to its own width.

Field Set and Field Group

Billing address

Shown on every invoice.

ElementUsage
LegendRequired
DescriptionOptional
FieldRequired
Field groupOptional

FieldSet renders a fieldset, and FieldLegend names it. FieldGroup stacks Fields, and it’s the container that a responsive Field is measured against.

Choice Card

ElementUsage
TitleRequired
ControlRequired
DescriptionOptional
CardRequired

A choice card is a Field whose FieldLabel wraps a FieldContent and the control, so users can click anywhere on the card to change the control. Use FieldTitle for the title because the card itself is the label. The control can be a radio, a Checkbox, or a Switch.

States

A choice card shows the focus outline on its own edge, not on the control inside it.

Invalid

A Field is invalid when invalid is set, when its control fails validation, or when Base UI’s Form has an error for the control’s name. The control then has aria-invalid. Add a FieldError after the control, as color alone doesn’t tell users what is wrong.

DoAdd a FieldError that says what to enter.
Don’tWhen a Field is marked invalid by color alone, users can see that something is wrong but not what to enter.

Disabled

If disabled is set on Field, the control is disabled, and the label can’t be clicked.

Required

Field has no required prop and adds no mark to the label. Set required on the control. A native input then reports the state to assistive technology, and the browser prevents the form from being submitted while the input is empty.

Behavior

orientation on Field sets whether the label is above the control or next to it.

OrientationLayout
verticalA column, in which the parts fill the Field’s width
horizontalA row, in the order of the markup: a Checkbox before its label, a Switch after it
responsiveA column until the FieldGroup around it is 448px wide, then a row

In a row, FieldContent contains the label and the description in one column and fills the width that remains next to the control.

Responsive

A responsive Field responds to the width of its FieldGroup, not of the screen, so the same form is stacked in a 384px Sheet and laid out in rows in a 576px Dialog. If there is no FieldGroup, the Field stays a column. See Layout for the rule.

Separator

FieldSeparator renders a Separator between two Fields of a FieldGroup. Its children are displayed as text centered on the line.

Content

StringRuleExampleCounterexample
LabelName the value in sentence case, with no colon“Billing email”“Billing Email:”
DescriptionSay what the value is used for or what format it has“Invoices and receipts go to this address.”“Enter your billing email.”
ErrorSay what to enter“Enter a valid email address.”“Invalid input.”
LegendName what the fields have in common“Billing address”“Details”

Allow a label and an error to wrap. See Typography for the rule on truncation.

Accessibility

Field is Base UI’s Field with role="group". The FieldLabel names the control, and the FieldDescription and the FieldError are the control’s accessible description, which screen readers read together with the control. The error has role="alert", so screen readers announce the message when it appears. A Field can’t receive focus, and the control inside keeps its own keys.

A Field connects any registry control that holds a value. A Toggle Group and a Segmented Control are groups of buttons, and a Field connects nothing to them.

A Field takes one control. For several controls under one label, such as a first and a last name, use a FieldSet with a Field for each control. Two controls in one Field take the same label and the same form name.

A control with an error needs aria-invalid so that assistive technology can identify it, as WCAG 2.2 SC 3.3.1 Error Identification requires. An invalid Field sets it. A FieldError with a message of your own doesn’t make the Field invalid: set invalid with it.

Outside a Field, a FieldLabel, a FieldDescription, and a FieldError render plain elements and connect to no control.

Installation

npx shadcn@latest add @summit/field

The CLI also adds @summit/label and @summit/separator.

Usage

Field lays out, colors, and connects its parts. You provide invalid and the error text.

import { Field, FieldDescription, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';

<Field>
    <FieldLabel>Billing email</FieldLabel>
    <Input type="email" />
    <FieldDescription>Invoices and receipts go to this address.</FieldDescription>
</Field>;

Show an Error

To show an error that your own code holds, set invalid on Field and place the message in a FieldError. A FieldError with no content shows nothing while the Field is valid, so the same markup covers both states.

Show an Error
<Field invalid={Boolean(error)}>
    <FieldLabel>Billing email</FieldLabel>
    <Input type="email" />
    <FieldError>{error}</FieldError>
</Field>

Word a Validation Message

A Field validates its control when users press Enter in it. A FieldError with no content then shows the browser’s message. To word the message yourself, set match on a FieldError. To add a rule, pass a function to validate on Field.

Word a Validation Message
<FieldError match="valueMissing">Enter your billing email.</FieldError>
<FieldError match="typeMismatch">Enter a valid email address.</FieldError>

Base UI also has a Form that holds the errors of a server by field name. See the Base UI Form documentation.

Show Several Errors

To show several errors, pass a list of objects with a message to errors. FieldError removes repeated messages, renders one message as text and several as a list, and renders nothing if the list is empty.

Show Several Errors
<FieldError errors={[{ message: 'Enter a valid email address.' }, { message: 'Use an address at your company.' }]} />

Beside a Checkbox or a Switch

To place the label next to a Checkbox or a Switch, set orientation="horizontal", and wrap the label and the description in FieldContent.

Beside a Checkbox or a Switch
import { Checkbox } from '@/components/ui/checkbox';

<Field orientation="horizontal">
    <Checkbox defaultChecked />
    <FieldContent>
        <FieldLabel>Attach a PDF copy</FieldLabel>
        <FieldDescription>Every invoice email carries the invoice as a PDF file.</FieldDescription>
    </FieldContent>
</Field>;

Name a Group of Options

To name a Radio Group, pass it to render on FieldSet, and set variant="label" on FieldLegend. The legend then names the Radio Group and has the size of a label. A Field in that FieldSet is one option, with its own label. A FieldDescription and a FieldError in the outer Field describe the whole group.

Name a Group of Options
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';

<Field invalid={Boolean(error)}>
    <FieldSet render={<RadioGroup defaultValue="net-30" />}>
        <FieldLegend variant="label">Payment terms</FieldLegend>
        <Field orientation="horizontal">
            <RadioGroupItem value="net-15" />
            <FieldLabel>Net 15</FieldLabel>
        </Field>
        <Field orientation="horizontal">
            <RadioGroupItem value="net-30" />
            <FieldLabel>Net 30</FieldLabel>
        </Field>
    </FieldSet>
    <FieldError>{error}</FieldError>
</Field>;

For a group of Checkboxes, keep the FieldSet as a fieldset, and place the Fields in a FieldGroup with data-slot="checkbox-group".

Build a Choice Card

To build a choice card, wrap a FieldContent and the control in the FieldLabel of an option.

Build a Choice Card
<Field>
    <FieldLabel>
        <FieldContent>
            <FieldTitle>Hourly</FieldTitle>
            <FieldDescription>Bill the time you track at an hourly rate.</FieldDescription>
        </FieldContent>
        <RadioGroupItem value="hourly" />
    </FieldLabel>
</Field>

API Reference

Field accepts the props of Base UI’s Field.Root, and FieldSet and FieldLegend accept the props of its Fieldset.Root and Fieldset.Legend. See the Base UI Field documentation for name, validate, and validationMode, and the Base UI Fieldset documentation. The other parts accept the props of their elements, and FieldLabel accepts the props of a Label.

Field

PropTypeDefaultDescription
orientation'vertical' | 'horizontal' | 'responsive''vertical'The direction of the label and the control
invalidbooleanfalseMarks the control as invalid and colors the label
disabledbooleanfalseDisables the control and dims the label

FieldSet

PropTypeDefaultDescription
renderAn element or a function that returns oneNoneThe element to render in place of the fieldset, such as a RadioGroup

FieldLegend

PropTypeDefaultDescription
variant'legend' | 'label''legend'The text size of a legend or of a label

FieldError

PropTypeDefaultDescription
errorsArray<{ message?: string } | undefined>NoneThe messages to display when the part has no children
matchboolean | keyof ValidityStateNoneThe validation failure that the message is for. true always shows the message, and is the default when the part has content

On this page