Field
Combine labels, controls, and help text to compose accessible form fields.
import * as stylex from '@stylexjs/stylex';
import {
Field,
FieldDescription,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { container } from '@/lib/constants.stylex';
export default function FieldDemo() {
return (
<FieldSet style={styles.root}>
<FieldLegend>Profile</FieldLegend>
<FieldGroup>
<Field>
<FieldLabel htmlFor="field-name">Name</FieldLabel>
<Input id="field-name" placeholder="Evil Rabbit" />
<FieldDescription>Shown on your public profile.</FieldDescription>
</Field>
<FieldSeparator>Contact</FieldSeparator>
<Field>
<FieldLabel htmlFor="field-email">Email</FieldLabel>
<Input id="field-email" type="email" placeholder="you@example.com" />
</Field>
</FieldGroup>
</FieldSet>
);
}
const styles = stylex.create({
root: {
width: container.sm,
},
});
Install
npx shadcn@latest add @madeui/field
Usage
import {
Field,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from '@/components/ui/field';
Composition
<FieldSet>
<FieldLegend />
<FieldGroup>
<Field>
<FieldLabel />
<Input />
<FieldDescription />
<FieldError />
</Field>
<FieldSeparator />
</FieldGroup>
</FieldSet>
Validation
Give the field a name and place a Base UI control inside — the control
joins the field automatically (label association, aria-describedby,
aria-invalid, red label on error). Combine with Form
to validate on submit, or set validationMode="onChange" per field. Custom
rules go in validate:
<Field
name="username"
validate={(value) => (String(value).length < 2 ? 'Too short.' : null)}
>
<FieldLabel>Username</FieldLabel>
<Input required />
<FieldError />
</Field>
Using react-hook-form or TanStack Form instead? See the
Form page — Field takes invalid and FieldError
takes errors for externally controlled state.
API reference
Built on Base UI Field and Fieldset: Field renders Field.Root (all validation props forwarded: name, validate, validationMode, invalid, disabled, …), FieldLabel/FieldDescription/FieldError render the matching parts, FieldSet/FieldLegend render Fieldset parts. FieldGroup, FieldContent, FieldTitle, and FieldSeparator are layout markup.
Field
| Prop | Type | Default | Description |
|---|---|---|---|
orientation |
'vertical' | 'horizontal' |
'vertical' |
|
name |
string |
— | Identifies the field in form values and server errors. |
validate |
(value, formValues) => string | string[] | null |
— | Custom validation; return message(s) or null. |
invalid |
boolean |
— | Force the invalid state — for external form libraries. |
FieldError
| Prop | Type | Default | Description |
|---|---|---|---|
errors |
Array<{ message?: string }> |
— | External errors rendered directly (de-duplicated; one message as text, several as a list; nothing when empty). Without it, the surrounding field’s own validation message renders. |
match |
boolean | keyof ValidityState |
— | When to show children (Base UI). true always shows — for external control. |
FieldLegend accepts variant: 'legend' (base size) or 'label' (sm). FieldSeparator accepts children rendered centered over the line. All parts accept a style prop (StyleXStyles, merged last).