Field

Lays out a control with its label, description and error.

View as Markdown
Payment Method

All transactions are secure and encrypted

Enter your 16-digit card number

Billing Address

The billing address associated with your payment method

<form>  <FieldGroup>    <FieldSet>      <FieldLegend>Payment Method</FieldLegend>      <FieldSetDescription>        All transactions are secure and encrypted      </FieldSetDescription>      <FieldGroup>        <Field>          <FieldLabel>Name on Card</FieldLabel>          <Input placeholder="Jordan Kim" required />        </Field>        <Field>          <FieldLabel>Card Number</FieldLabel>          <Input placeholder="1234 5678 9012 3456" required />          <FieldDescription>Enter your 16-digit card number</FieldDescription>        </Field>      </FieldGroup>    </FieldSet>    <FieldSeparator />    <FieldSet>      <FieldLegend>Billing Address</FieldLegend>      <Field orientation="horizontal">        <Checkbox defaultChecked />        <FieldLabel>Same as shipping address</FieldLabel>      </Field>    </FieldSet>    <Field orientation="horizontal">      <Button type="submit" variant="primary">        Submit      </Button>      <Button type="button" variant="outline">        Cancel      </Button>    </Field>  </FieldGroup></form>

Installation

$ npx shadcn@latest add @constella/field

Usage

import {  Field,  FieldContent,  FieldDescription,  FieldError,  FieldGroup,  FieldLabel,  FieldLegend,  FieldSeparator,  FieldSet,  FieldSetDescription,  FieldTitle,} from "@/components/primitives/field";
<Field>  <FieldLabel>Label</FieldLabel>  {/* control */}  <FieldDescription>Helper text.</FieldDescription></Field>

The label, description and error link to the control inside the Field on their own, so no id or htmlFor is needed.

Composition

FieldSet├── FieldLegend├── FieldSetDescription└── FieldGroup    ├── Field    │   ├── FieldLabel    │   ├── FieldContent    │   │   ├── FieldTitle    │   │   └── FieldDescription    │   └── FieldError    └── FieldSeparator

Orientation

Use orientation="horizontal" to put the control beside its label, as for a checkbox. Wrap the label and description in FieldContent to stack them.

By clicking this checkbox, you agree to the terms.

<Field orientation="horizontal">  <Checkbox />  <FieldContent>    <FieldLabel>Accept terms and conditions</FieldLabel>    <FieldDescription>      By clicking this checkbox, you agree to the terms.    </FieldDescription>  </FieldContent></Field>

Fieldset

Group related fields in a FieldSet with a FieldLegend. Use variant="label" for a legend the size of a label, and FieldSetDescription for its helper text.

Show these items on the desktop

Select the items you want to show on the desktop.

<FieldSet>  <FieldLegend variant="label">Show these items on the desktop</FieldLegend>  <FieldSetDescription>    Select the items you want to show on the desktop.  </FieldSetDescription>  <FieldGroup>    <Field orientation="horizontal">      <Checkbox defaultChecked />      <FieldLabel>Hard disks</FieldLabel>    </Field>    <Field orientation="horizontal">      <Checkbox />      <FieldLabel>Connected servers</FieldLabel>    </Field>  </FieldGroup></FieldSet>

Field Group

Stack fieldsets in a FieldGroup, with a FieldSeparator between them. Pass it text to label the break.

Responses

Get notified when ChatGPT responds to requests that take time.

Tasks

Get notified when tasks you've created have updates.

<FieldGroup>  <FieldSet>    <FieldLegend variant="label">Responses</FieldLegend>    <Field orientation="horizontal">      <Checkbox defaultChecked disabled />      <FieldLabel>Push notifications</FieldLabel>    </Field>  </FieldSet>  <FieldSeparator />  <FieldSet>    <FieldLegend variant="label">Tasks</FieldLegend>    <Field orientation="horizontal">      <Checkbox />      <FieldLabel>Email notifications</FieldLabel>    </Field>  </FieldSet></FieldGroup>

Choice Card

Put the control and a FieldContent inside the FieldLabel to turn the whole label into a card that toggles it. Use FieldTitle for its heading.

<Field>  <FieldLabel>    <Checkbox defaultChecked />    <FieldContent>      <FieldTitle>Enable notifications</FieldTitle>      <FieldDescription>        You can enable or disable notifications at any time.      </FieldDescription>    </FieldContent>  </FieldLabel></Field>

Card

Put the cards in a FieldGroup directly inside a flush Card to list them as rows of one card, split by hairlines. A settings page lists its switches this way.

<Card size="flush">  <FieldGroup>    <Field>      <FieldLabel>        <FieldContent>          <FieldTitle>Mentions</FieldTitle>          <FieldDescription>When someone @mentions you.</FieldDescription>        </FieldContent>        <Switch defaultChecked />      </FieldLabel>    </Field>  </FieldGroup></Card>

Error

Use the invalid prop to mark the field, and FieldError for the message. match shows it always; leave it out to show it only when Base UI's validation fails. With a form library, pass its errors to errors instead: each message shows once, several as a list, and nothing renders when there are none.

<FieldError errors={field.state.meta.errors} />
You must accept the terms to continue.
<Field invalid orientation="horizontal">  <Checkbox />  <FieldContent>    <FieldLabel>Accept terms and conditions</FieldLabel>    <FieldError match>You must accept the terms to continue.</FieldError>  </FieldContent></Field>

Disabled

Use the disabled prop on Field to disable its control and dim its label.

<Field disabled orientation="horizontal">  <Checkbox />  <FieldLabel>Enable notifications</FieldLabel></Field>

Input

Choose a unique username for your account.

Must be at least 8 characters long.

<Field>  <FieldLabel>Username</FieldLabel>  <Input placeholder="Sam Lee" />  <FieldDescription>    Choose a unique username for your account.  </FieldDescription></Field>

Textarea

Share your thoughts about our service.

<Field>  <FieldLabel>Feedback</FieldLabel>  <Textarea placeholder="Your feedback helps us improve..." rows={4} />  <FieldDescription>Share your thoughts about our service.</FieldDescription></Field>

Select

Select your department or area of work.

<Field>  <FieldLabel>Department</FieldLabel>  <Select items={departments}>    <SelectTrigger>      <SelectValue />    </SelectTrigger>    <SelectContent>      <SelectItem value="engineering">Engineering</SelectItem>    </SelectContent>  </Select>  <FieldDescription>Select your department or area of work.</FieldDescription></Field>

Slider

Use FieldTitle for a control that isn't labelled by a <label>.

Price Range

Set your budget range ($200 - 800).

<Field>  <FieldTitle>Price Range</FieldTitle>  <FieldDescription>    Set your budget range (${range[0]} - {range[1]}).  </FieldDescription>  <Slider    aria-label="Price Range"    max={1000}    onValueChange={setRange}    value={range}  /></Field>

Radio Group

Subscription Plan

Yearly and lifetime plans offer significant savings.

<FieldSet>  <FieldLegend variant="label">Subscription Plan</FieldLegend>  <RadioGroup defaultValue="monthly">    <Field orientation="horizontal">      <RadioGroupItem value="monthly" />      <FieldLabel>Monthly ($9.99/month)</FieldLabel>    </Field>  </RadioGroup></FieldSet>

Switch

<Field orientation="horizontal">  <FieldLabel>Multi-factor authentication</FieldLabel>  <Switch /></Field>

API Reference

Field adds orientation ("vertical", the default, or "horizontal") FieldLegend adds variant ("legend", the default, or "label") and FieldError adds errors (an array of { message }, in place of match). FieldTitle takes render. FieldGroup, FieldContent and FieldSetDescription are plain elements. FieldSeparator draws a line, broken by its children when it has any. Every part takes sx, applied last. For the rest, see Base UI Field and Fieldset.