Field

A low-level component that associates an accessible label and description with a single form control element.

To label a group of multiple form control elements, use the Fieldset component instead.

Simply wrapping a control with this component does not guarantee accessible labeling. See examples for how to associate the label in different cases.

import { Field } from '@wordpress/ui';

View on Storybook

View source on GitHub

PropsPermalink to this section

NameDefaultDescription
name

string

Identifies the field when a form is submitted. Takes precedence over the name prop on the <Field.Control> component.

render( props: React.ComponentProps< typeof Stack > ) => ( <Stack { ...props } direction="column" gap="sm" /> )

ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

style

CSSProperties

CSS style to apply to the element.

className

string

CSS class name to apply to the element.

actionsRef

RefObject<FieldRootActions | null>

A ref to imperative actions.

  • validate: Validates the field when called.
children

ReactNode

disabledfalse

boolean

Whether the field is disabled.

ExamplesPermalink to this section

DefaultPermalink to this section

If your control component forwards refs, as well as the aria-labelledby and aria-describedby props to the actual underlying HTML element to be labeled, you can simply place your control in the render prop of Field.Control.

const Default = () => <Field.Root>{[
        <Field.Label key="label">Label</Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,

        <Field.Description key="description">
            The accessible description.
        </Field.Description>,
    ]}</Field.Root>;

Using htmlForPermalink to this section

If your control component does not forward refs, but does forward the id prop to the actual underlying HTML element to be labeled, use the htmlFor prop of the Field.Label component to associate the label with the control.

This is preferred over aria-labelledby because it allows users to click the label to focus the control.

const UsingHtmlFor = () => {
    const controlId = useId();
    const descriptionId = useId();

    return (
        <Field.Root>
            <Field.Label htmlFor={ controlId }>Label</Field.Label>
            <MyNonRefForwardingControl
                placeholder="Placeholder"
                id={ controlId }
                aria-describedby={ descriptionId } />
            <Field.Description id={ descriptionId }>The accessible description.
                                </Field.Description>
        </Field.Root>
    );
};

Using aria-labelledbyPermalink to this section

If your control component does not forward refs nor the id prop, but does forward the aria-labelledby prop to the actual underlying HTML element to be labeled, use the id prop of the Field.Label component to associate the label with the control.

const UsingAriaLabelledby = () => {
    const labelId = useId();
    const descriptionId = useId();

    return (
        <Field.Root>
            <Field.Label id={ labelId }>Label</Field.Label>
            <MyNonRefForwardingControl
                placeholder="Placeholder"
                aria-labelledby={ labelId }
                aria-describedby={ descriptionId } />
            <Field.Description id={ descriptionId }>The accessible description.
                                </Field.Description>{ ' ' }
        </Field.Root>
    );
};

Hidden LabelPermalink to this section

When hideFromVision is set on Field.Label, the label is visually hidden but remains accessible to screen readers.

const HiddenLabel = () => <Field.Root>{[
        <Field.Label hideFromVision key="label">
            Label
        </Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,
    ]}</Field.Root>;

With DetailsPermalink to this section

To add rich content (such as links) to the description, use Field.Details.

Although this content is not associated with the field using direct semantics, it is made discoverable to screen reader users via a visually hidden description, alerting them to the presence of additional information below.

If the content only includes plain text, use Field.Description instead, so the readout is not unnecessarily verbose for screen reader users.

const WithDetails = () => <Field.Root>{[
        <Field.Label key="label">Label</Field.Label>,
        <Field.Control
            render={ <input type="text" placeholder="Placeholder" /> }
            key="control"
        />,

        <Field.Details key="details">{ DETAILS_EXAMPLE }</Field.Details>,
    ]}</Field.Root>;

With Visual LabelPermalink to this section

Field.VisualLabel renders a purely visual label with the same styling as Field.Label. It can be used outside Field.Root when the control is already accessibly labeled, but a visual label is still needed for layout consistency.

const WithVisualLabel = () => (
    <Stack direction="column" gap="sm" align="flex-start">
        <Field.VisualLabel>Author</Field.VisualLabel>
        <Button variant="outline">Select an author</Button>
    </Stack>
);