XDSField@xds/core · Field
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
| Guidance | Practices |
|---|---|
| Do | Always provide a label for accessibility, even if visually hidden with isLabelHidden. |
| Do | Use the status prop with clear messages to provide inline validation feedback. |
| Do | Add a description when the label alone does not explain what the field expects, like format hints or constraints. |
| Don't | Set both isOptional and isRequired on the same field. |
| Don't | Use the detached status variant on bordered inputs — reserve it for checkboxes, switches, and sliders. |
| Don't | Hide the label without providing an alternative way for the user to understand the field purpose. |
Anatomy
| Element | Description | |
|---|---|---|
| Label | required | Text identifying the field. Always rendered for accessibility, optionally hidden visually. |
| Description | Helper text between the label and input explaining what to enter. | |
| Input slot | required | The input control wrapped by the field — TextInput, Select, DateInput, etc. |
| Status message | Inline validation feedback showing error, warning, or success with a message. | |
| Optional/Required indicator | Badge next to the label showing whether the field is optional or required. | |
| Label tooltip | Info icon at the end of the label with a tooltip explaining the field. |
Import
tsimport {XDSField} from '@xds/core/Field'
Props
| Prop | Type | Description |
|---|---|---|
labelrequired | string | Label text for the field (always rendered for accessibility). |
inputIDrequired | string | ID for the input element (used for the label htmlFor attribute). |
childrenrequired | ReactNode | The 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 | string | Description text displayed between the label and input. |
descriptionID | string | ID 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 | XDSIconType | Icon to display before the label text. See `npx xds docs icons` for valid semantic names. |
labelTooltip | string | Tooltip text to display in an info icon at the end of the label. |
status | XDSFieldStatus | Status 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 | StyleXStyles | StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value — not an inline style object like style={{}}. |
className | string | CSS class name(s) appended to the root element. Prefer xstyle for StyleX deduplication. |
style | React.CSSProperties | Inline 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.| Prop | Type | Description |
|---|---|---|
labelrequired | string | Label text for the field (always rendered for accessibility). |
inputIDrequired | string | ID for the input element (used for the label htmlFor attribute). |
childrenrequired | ReactNode | The 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 | string | Description text displayed between the label and input. |
descriptionID | string | ID 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 | XDSIconType | Icon to display before the label text. See `npx xds docs icons` for valid semantic names. |
labelTooltip | string | Tooltip text to display in an info icon at the end of the label. |
status | XDSFieldStatus | Status 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 | StyleXStyles | StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value — not an inline style object like style={{}}. |
className | string | CSS class name(s) appended to the root element. Prefer xstyle for StyleX deduplication. |
style | React.CSSProperties | Inline styles applied to the root element. Takes priority over StyleX inline styles. |
XDSFieldLabel
Standalone label component with optional/required indicators and tooltip support.| Prop | Type | Description |
|---|---|---|
labelrequired | string | Label text. |
inputIDrequired | string | ID 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 | XDSIconType | Icon before the label text. See `npx xds docs icons` for valid semantic names. |
labelTooltip | string | Tooltip text for info icon at end of label. |
XDSFieldStatus
Status message component for form field validation feedback.| Prop | Type | Description |
|---|---|---|
typerequired | 'error' | 'warning' | 'success' | Status type. |
messagerequired | string | Status message text. |
id | string | ID 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}><XDSTextInputlabel="Email"description="We'll send a confirmation link to this address"value={email}onChange={setEmail}placeholder="you@example.com"/><XDSTextInputlabel="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}><XDSTextInputlabel="Username"isRequiredvalue={username}onChange={setUsername}placeholder="Enter your username"/><XDSTextInputlabel="Backup email"isOptionalvalue={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}><XDSTextInputlabel="Email"description="Enter your work email"value={email}onChange={setEmail}status={{type: 'error',message: 'Please enter a valid email address',}}/><XDSTextInputlabel="Username"description="Choose a unique username"value={username}onChange={setUsername}status={{type: 'warning',message: 'This username is reserved for administrators',}}/><XDSTextInputlabel="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}><XDSFieldlabel="Email"inputID="field-email"description="We will never share your email."isRequiredstatus={status}><XDSTextInputlabel="Email"isLabelHiddenvalue={email}onChange={setEmail}placeholder="you@example.com"/></XDSField></XDSStack>);}