Field
Lays out a control with its label, description and error.
<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/fieldUsage
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 └── FieldSeparatorOrientation
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.
<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.
<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} /><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>.
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
<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.