Field
Lays out a form control with its label, help text and error.
Use the name on the contract.
Installation
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- A form control needs a label, and maybe help text or an error. It does what a Lightning input's label, help text and error do, for any control.
- Several fields make up a form, or related fields need a legend, like an address.
- A checkbox, radio or switch needs its label beside it.
- It works with any form library.
Don't use it
- A control needs only a label, outside a form. Label is enough.
- You show a record's values read-only. Use Output field, or Record detail for a record's whole Details tab.
- The message is about the whole form, not one field. Use Alert above the form.
Usage
A field holds one control with its label and text:
Field
├── FieldLabel
├── control, like Input
├── FieldDescription
└── FieldErrorRelated fields share a legend:
FieldSet
├── FieldLegend
├── FieldDescription
└── FieldGroup
├── Field
└── Fieldimport { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"<Field>
<FieldLabel htmlFor="phone">Phone</FieldLabel>
<Input id="phone" type="tel" aria-describedby="phone-help" />
<FieldDescription id="phone-help">Include the country code.</FieldDescription>
</Field>For a text field with its label in a column beside it, as a record's edit form lays them out, give Field layout="horizontal". From a 48rem screen the label takes the first third, less a gap, and the control and help text start after it; below that the field stacks. layout="auto" follows Salesforce's display density: stacked, and horizontal when the page is compact (data-density="compact" on <html>, see Theming).
For help that opens from an info button beside the label, as Salesforce's field-level help does, put a TooltipTrigger after the FieldLabel with the help in its TooltipContent, as the Label with help example shows. Name the button "Help for" and the label, and point its aria-describedby at a hidden copy of the help inside it. In Base UI projects the tooltip doesn't describe its trigger, and in Radix projects it does only while open.
For a checkbox, radio or switch, give Field orientation="horizontal" so the label sits beside the control. When it also has a description, wrap the label and description in FieldContent, as the Checkbox group example shows.
For a form library's errors, mark the Field with data-invalid, set aria-invalid on the control and pass the list to FieldError. One message shows as text, several as a list, each once:
<Field data-invalid={invalid}>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" aria-invalid={invalid} aria-describedby="email-error" />
<FieldError id="email-error" errors={errors} />
</Field>Examples
Fieldset
A billing address in a `FieldSet` under a `FieldLegend` and a description, then a labelled `FieldSeparator` before an optional field.
Checkbox group
Three checkboxes in `orientation="horizontal"` fields under `FieldLegend variant="label"`, stacked tight as SLDS does, one with a description.
Label beside the field
A contact's fields with `layout="horizontal"`: each label in a column, help text under its input. Below a 48rem screen they stack.
Include the country code for numbers outside the US.
Label with help
An info button after the `FieldLabel` that shows the field's help in a `Tooltip` and describes itself with it, through `aria-describedby`.
API reference
| Part | Built on |
|---|---|
FieldSet | <fieldset> (opens in a new tab) |
FieldLegend | <legend> (opens in a new tab) |
FieldGroup | <div> (opens in a new tab) |
Field | <div> (opens in a new tab) |
FieldContent | <div> (opens in a new tab) |
FieldLabel | Label |
FieldTitle | <div> (opens in a new tab) |
FieldDescription | <p> (opens in a new tab) |
FieldSeparator | <div> (opens in a new tab) |
FieldError | <div> (opens in a new tab) |
FieldLegend
| Prop | Type | Default |
|---|---|---|
variant | "legend" | "label" | "legend" |
Field
| Prop | Type | Default |
|---|---|---|
orientation | "vertical" | "horizontal" | "responsive" | "vertical" |
layout | "stacked" | "horizontal" | "auto" | "stacked" |
FieldError
| Prop | Type | Default |
|---|---|---|
errors | Array<{ message?: string } | undefined> |
SLDS mapping
Fieldisslds-form-element;FieldGroupstacks fields asslds-form-element_stackeddoes.layout="horizontal"isslds-form-element_horizontal.FieldLabelisslds-form-element__label, through Label. Beside a checkbox or radio it's regular weight, as SLDS's are.FieldDescriptionisslds-form-element__help.FieldErroris the help text of anslds-has-errorform element; the control draws its own error style fromaria-invalid.FieldSetis afieldset.slds-form-element,FieldLegendisslds-form-element__legend.
Known gaps:
FieldSeparator, and the selectable card aFieldLabelbecomes when it wraps aField, have no SLDS counterpart.- Read-only and inline-edit form elements are Output field's, not Field's.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
orientation | vertical | slds-form-element slds-form-element_stacked | The label above the control. |
orientation | horizontal | slds-checkbox, slds-radio | The control beside its label, as SLDS lays out checkboxes and radios. For a label beside a text control, use layout="horizontal". |
orientation | responsive | none | Vertical, then horizontal when the field group is at least 28rem wide. |
layout | stacked (added) | slds-form-element_stacked | The label above the control. The default; shadcn's own layout. |
layout | horizontal (added) | slds-form-element_horizontal | A text field with its label in a column, from a 48rem viewport. Applies to a vertical field. |
layout | auto (added) | slds-form-element_stacked, or slds-form-element_horizontal in compact density | Stacked, and horizontal when the page is compact (data-density="compact"), as Lightning's display density lays out record fields. |
FieldLegend variant | legend | slds-form-element__legend | |
FieldLegend variant | label | slds-form-element__legend slds-form-element__label |
Accessibility
- Link each label to its control with
htmlForandid, and help text and errors witharia-describedby.Fielddoesn't do it for you. - Set
aria-invalidon the invalid control.FieldErrorhasrole="alert", so its message is announced when it appears. - Mark a required field with
requiredon the control and an asterisk in the label, as the Account details example shows. - In Cosmos dark, text in an invalid input is about 4.3:1 against its background, below AA. Salesforce's own stylesheet fails the same way; the error text below the field passes.
Responsive behavior
orientation="responsive"turns horizontal once the surroundingFieldGroupis at least 28rem wide. It reads the group's width, so outside aFieldGroupit stays vertical.
Rules
- One
Fieldper control, with oneFieldLabel. - Use
orientation="horizontal"only for checkboxes, radios and switches. For a text field with its label beside it, uselayout="horizontal", orlayout="auto"to follow the page's density; both need the default vertical orientation. - Don't add spacing classes between fields.
FieldGroupspaces them. - A group of checkboxes takes
FieldLegend variant="label"anddata-slot="checkbox-group"on itsFieldGroup, as the Checkbox group example shows. Without the slot, the boxes sit as far apart as text fields. - Don't color the label of an invalid field. Only the error text and the control turn red.