XDSField@xds/core · Field
Preview coming soon

Usage

Field wraps any input control with a label, description, and validation status. Use it to build accessible forms with consistent labeling, optional/required indicators, and inline error, warning, or success feedback.

Best practices

GuidancePractices
DoAlways provide a label for accessibility, even if visually hidden with isLabelHidden.
DoUse the status prop with clear messages to provide inline validation feedback.
DoAdd a description when the label alone does not explain what the field expects, like format hints or constraints.
Don'tSet both isOptional and isRequired on the same field.
Don'tUse the detached status variant on bordered inputs — reserve it for checkboxes, switches, and sliders.
Don'tHide the label without providing an alternative way for the user to understand the field purpose.

Anatomy

ElementDescription
LabelrequiredText identifying the field. Always rendered for accessibility, optionally hidden visually.
DescriptionHelper text between the label and input explaining what to enter.
Input slotrequiredThe input control wrapped by the field — TextInput, Select, DateInput, etc.
Status messageInline validation feedback showing error, warning, or success with a message.
Optional/Required indicatorBadge next to the label showing whether the field is optional or required.
Label tooltipInfo icon at the end of the label with a tooltip explaining the field.

Import

ts
import {XDSField} from '@xds/core/Field'

Props

PropTypeDescription
labelrequired
stringLabel text for the field (always rendered for accessibility).
inputIDrequired
stringID for the input element (used for the label htmlFor attribute).
childrenrequired
ReactNodeThe input or control to render.
isLabelHidden
boolean (default: false)Visually hide the label (still accessible to screen readers).
isDisabled
boolean (default: false)Whether the associated input is disabled. Propagates disabled styling to the label.
description
stringDescription text displayed between the label and input.
descriptionID
stringID for the description element (use for aria-describedby on the input).
isOptional
boolean (default: false)Whether the field is optional (mutually exclusive with isRequired).
isRequired
boolean (default: false)Whether the field is required (mutually exclusive with isOptional).
labelIcon
XDSIconTypeIcon to display before the label text. See `npx xds docs icons` for valid semantic names.
labelTooltip
stringTooltip text to display in an info icon at the end of the label.
status
XDSFieldStatusStatus indicator with type and optional message. When message is set, displays a colored status box.
statusVariant
'attached' | 'detached' (default: 'attached')How the status message renders relative to the input. Attached overlaps the input border; detached floats below.
ref
React.Ref<HTMLDivElement>Ref forwarded to the root element.
xstyle
StyleXStylesStyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value — not an inline style object like style={{}}.
className
stringCSS class name(s) appended to the root element. Prefer xstyle for StyleX deduplication.
style
React.CSSPropertiesInline styles applied to the root element. Takes priority over StyleX inline styles.

Sub-components

Field is a compound component with 3 sub-components.

XDSField

Form field wrapper that provides label, description, and optional/required indicators.
PropTypeDescription
labelrequired
stringLabel text for the field (always rendered for accessibility).
inputIDrequired
stringID for the input element (used for the label htmlFor attribute).
childrenrequired
ReactNodeThe input or control to render.
isLabelHidden
boolean (default: false)Visually hide the label (still accessible to screen readers).
isDisabled
boolean (default: false)Whether the associated input is disabled. Propagates disabled styling to the label.
description
stringDescription text displayed between the label and input.
descriptionID
stringID for the description element (use for aria-describedby on the input).
isOptional
boolean (default: false)Whether the field is optional (mutually exclusive with isRequired).
isRequired
boolean (default: false)Whether the field is required (mutually exclusive with isOptional).
labelIcon
XDSIconTypeIcon to display before the label text. See `npx xds docs icons` for valid semantic names.
labelTooltip
stringTooltip text to display in an info icon at the end of the label.
status
XDSFieldStatusStatus indicator with type and optional message. When message is set, displays a colored status box.
statusVariant
'attached' | 'detached' (default: 'attached')How the status message renders relative to the input. Attached overlaps the input border; detached floats below.
ref
React.Ref<HTMLDivElement>Ref forwarded to the root element.
xstyle
StyleXStylesStyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value — not an inline style object like style={{}}.
className
stringCSS class name(s) appended to the root element. Prefer xstyle for StyleX deduplication.
style
React.CSSPropertiesInline styles applied to the root element. Takes priority over StyleX inline styles.

XDSFieldLabel

Standalone label component with optional/required indicators and tooltip support.
PropTypeDescription
labelrequired
stringLabel text.
inputIDrequired
stringID of the input this label is for.
isLabelHidden
boolean (default: false)Visually hide the label.
isDisabled
boolean (default: false)Whether the associated input is disabled.
isOptional
boolean (default: false)Show "Optional" indicator.
isRequired
boolean (default: false)Show "Required" indicator.
labelIcon
XDSIconTypeIcon before the label text. See `npx xds docs icons` for valid semantic names.
labelTooltip
stringTooltip text for info icon at end of label.

XDSFieldStatus

Status message component for form field validation feedback.
PropTypeDescription
typerequired
'error' | 'warning' | 'success'Status type.
messagerequired
stringStatus message text.
id
stringID for aria-describedby association.
variant
'attached' | 'detached' (default: 'attached')Visual variant — attached overlaps the input, detached floats below.

Examples

Common configurations, variations, and states.
Field — DescriptionFields with helper text below the label. Use descriptions to explain format requirements, constraints, or what happens with the data — like
tsx
'use client';
import {useState} from 'react';
import {XDSTextInput} from '@xds/core/TextInput';
import {XDSVStack} from '@xds/core/Layout';
import {XDSCenter} from '@xds/core/Center';
export default function FieldWithDescription() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<XDSCenter>
<XDSVStack gap={4}>
<XDSTextInput
label="Email"
description="We'll send a confirmation link to this address"
value={email}
onChange={setEmail}
placeholder="you@example.com"
/>
<XDSTextInput
label="Password"
description="At least 8 characters with one uppercase letter"
value={password}
onChange={setPassword}
placeholder="Create a password"
/>
</XDSVStack>
</XDSCenter>
);
}
Field — Required & OptionalRequired and optional field indicators side by side. Use isRequired on fields the user must fill in, and isOptional to clarify which fields can be skipped.
tsx
'use client';
import {useState} from 'react';
import {XDSTextInput} from '@xds/core/TextInput';
import {XDSVStack} from '@xds/core/Layout';
import {XDSCenter} from '@xds/core/Center';
export default function FieldRequired() {
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
return (
<XDSCenter>
<XDSVStack gap={4}>
<XDSTextInput
label="Username"
isRequired
value={username}
onChange={setUsername}
placeholder="Enter your username"
/>
<XDSTextInput
label="Backup email"
isOptional
value={email}
onChange={setEmail}
placeholder="you@example.com"
/>
</XDSVStack>
</XDSCenter>
);
}
Field — Validation StatesAll three validation states: error, warning, and success. Use error for invalid input, warning for potential issues like reserved names, and success to confirm valid entries like API keys.
tsx
'use client';
import {useState} from 'react';
import {XDSTextInput} from '@xds/core/TextInput';
import {XDSVStack} from '@xds/core/Layout';
import {XDSCenter} from '@xds/core/Center';
export default function FieldStatusVariants() {
const [email, setEmail] = useState('bad-email');
const [username, setUsername] = useState('admin');
const [apiKey, setApiKey] = useState('sk-live-abc123');
return (
<XDSCenter>
<XDSVStack gap={4}>
<XDSTextInput
label="Email"
description="Enter your work email"
value={email}
onChange={setEmail}
status={{
type: 'error',
message: 'Please enter a valid email address',
}}
/>
<XDSTextInput
label="Username"
description="Choose a unique username"
value={username}
onChange={setUsername}
status={{
type: 'warning',
message: 'This username is reserved for administrators',
}}
/>
<XDSTextInput
label="API Key"
description="Paste your API key"
value={apiKey}
onChange={setApiKey}
status={{type: 'success', message: 'API key is valid and active'}}
/>
</XDSVStack>
</XDSCenter>
);
}

Showcase source

tsx
'use client';
import {useState} from 'react';
import {XDSField} from '@xds/core/Field';
import {XDSTextInput} from '@xds/core/TextInput';
import {XDSStack} from '@xds/core/Layout';
import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
root: {
width: 320,
},
});
export default function FieldShowcase() {
const [email, setEmail] = useState('');
const status =
email.length > 0 && !email.includes('@')
? {type: 'error' as const, message: 'Enter a valid email address.'}
: undefined;
return (
<XDSStack direction="vertical" gap={3} xstyle={styles.root}>
<XDSField
label="Email"
inputID="field-email"
description="We will never share your email."
isRequired
status={status}>
<XDSTextInput
label="Email"
isLabelHidden
value={email}
onChange={setEmail}
placeholder="you@example.com"
/>
</XDSField>
</XDSStack>
);
}