Field
Layout primitives for labels, descriptions, errors, and grouped form regions.
This name appears on your profile and invoices.
Installation
The components are exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.
Composition
Use the following composition for form fields and grouped sections:
FieldGroup
├── FieldSet (optional)
│ ├── FieldLegend (optional)
│ ├── FieldDescription (optional)
│ └── FieldGroup (nested)
│ └── Field
│ ├── FieldLabel
│ ├── FieldContent (optional)
│ ├── (control: Input, Select, Checkbox, …)
│ ├── FieldDescription (optional)
│ └── FieldError (optional)
├── FieldSeparator (optional)
└── FieldTitle (optional, section heading style)Field sets role="group" and supports orientation for label/control layout. FieldError renders role="alert" when content is present.
Usage
import {
Field,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
} from '@by/experience-system';Field and its parts are client components ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" />
<FieldDescription>We will never share your email.</FieldDescription>
</Field>Examples
Overview
Label, control, and description in a vertical Field.
This name appears on your profile and invoices.
Checkout-style form
FieldSet, FieldLegend, nested FieldGroup, FieldSeparator, and horizontal Field rows.
Horizontal field
orientation="horizontal" for checkbox or compact label/control rows.
Invalid state
data-invalid on Field with FieldError and aria-invalid on the control.
API Reference
Subsection titles name the exports from @by/experience-system. These are layout and typography wrappers (not Radix primitives).
Field
| Prop | Type | Default |
|---|---|---|
orientation | vertical | horizontal | responsive | vertical |
| Data attribute | Values |
|---|---|
data-slot | field |
data-orientation | mirrors orientation |
Renders role="group". Also accepts standard div attributes.
FieldLabel
Forwards to the Experience System Label with field spacing and nested Field affordances.
| Data attribute | Values |
|---|---|
data-slot | field-label |
Also accepts Label props (for example htmlFor).
FieldTitle
Non-label title row inside a field group.
| Data attribute | Values |
|---|---|
data-slot | field-label |
Also accepts standard div attributes.
FieldDescription
Supporting copy; link styles apply to anchors inside.
| Data attribute | Values |
|---|---|
data-slot | field-description |
Also accepts standard p attributes.
FieldError
| Prop | Type | Default |
|---|---|---|
errors | Array<{ message?: string } | undefined> | — |
| Data attribute | Values |
|---|---|
data-slot | field-error |
Renders role="alert" when children or resolved errors produce content; otherwise returns null. Also accepts standard div attributes.
FieldGroup
| Data attribute | Values |
|---|---|
data-slot | field-group |
Also accepts standard div attributes.
FieldSet
| Data attribute | Values |
|---|---|
data-slot | field-set |
Also accepts standard fieldset attributes.
FieldLegend
| Prop | Type | Default |
|---|---|---|
variant | legend | label | legend |
| Data attribute | Values |
|---|---|
data-slot | field-legend |
data-variant | mirrors variant |
Also accepts standard legend attributes.
FieldSeparator
Optional inline label between groups; renders a Separator with optional centered text.
| Prop | Type | Default |
|---|---|---|
children | React.ReactNode | — |
| Data attribute | Values |
|---|---|
data-slot | field-separator |
data-content | true when children is present |
Also accepts standard div attributes.
FieldContent
Stacks helper text tightly around a control.
| Data attribute | Values |
|---|---|
data-slot | field-content |
Also accepts standard div attributes.
Accessibility
Associate FieldLabel with controls via htmlFor / id. Surface errors with FieldError and aria-invalid on inputs so the role="alert" message is read after the control name. Use FieldSet + FieldLegend for groups of related inputs. See MDN — Labels and your product form guidelines.
Source in the repo: packages/experience-system/src/components/Field/Field.tsx. Agent-oriented contracts: packages/experience-system/src/components/Field/Field.instructions.md.