# Field

A field is a combination of a label and any form component, like an input, text area, or dropdown.

## Best practices

### Do

- Use one Field per input.
- Use a short sentence-case label with optional one-line help.
- Use required for mandatory fields.
- Put plain-language errors in validationMessage.
- Pick the right state: success, warning, or error.

### Don't

- Put multiple inputs in one Field, except checkbox or radio groups.
- Treat placeholder text as the label.
- Show errors before the user interacts.
- Use red for anything other than errors or required marks.
- Show success and error on the same Field.

## Behavior and states

- Validation states change the visual presentation of the field and can display a validation message.
- Use the required prop to display a red asterisk and announce the field as required to screen readers.
- When a field is disabled, only the form component appears disabled; its label remains enabled.
- Helper text and validation text that appeared before the field was disabled also remain enabled.
- Optionally, fields can also have info buttons, helper text, and validation states to give people clues about the information they need to enter.

## Forms

For selection controls, read the [Dropdown guidance](/coreai-design-system/components/Dropdown.md) before choosing
an inline label, external label, or placeholder. Keep labels and validation
accessible, and preserve keyboard behavior.

For a form inside a dialog, see [Forms in dialogs](/coreai-design-system/components/Dialog.md#forms-in-dialogs).

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-field--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { FieldProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = (props: Partial<FieldProps>): JSXElement => (<Field label="Example field" validationState="success" validationMessage="This is a success message." {...props}>
    <Input />
  </Field>);

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### Field API

```ts
interface FieldProps {
  as?: "div";

  /**
   * The Field's child can be a single form control, or a render function that takes the props that should be spread on
   * a form control.
   *
   * All form controls in this library can be used directly as children (such as `<Input>` or `<RadioGroup>`).
   *
   * For other controls, there are two options:
   * 1. The child of Field can be a render function that is given the props that should be spread on the control.
   *    `<Field>{(props) => <MyInput {...props} />}</Field>`
   * 2. The control itself can merge props from field with useFieldControlProps_unstable().
   *    `props = useFieldControlProps_unstable(props);`
   */
  children?: ReactNode | ((props: FieldControlProps) => ReactNode);

  className?: string;

  /**
   * Additional hint text below the field.
   */
  hint?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * The label associated with the field.
   */
  label?: WithSlotShorthandValue<Omit<ComponentProps<LabelSlots>, "required"> & { disabled?: boolean; required?: boolean | WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null | undefined; }, "children"> & { children?: any; }> | null | undefined; size?: "small" | "medium" | "large" | undefined; weight?: "regular" | "semibold" | undefined; } & RefAttributes<HTMLLabelElement>> | null | undefined;

  /**
   * The orientation of the label relative to the field component.
   * This only affects the label, and not the validationMessage or hint (which always appear below the field component).
   * @default vertical
   */
  orientation?: "horizontal" | "vertical";

  ref?: Ref<HTMLDivElement>;

  /**
   * Marks the Field as required. If `true`, an asterisk will be appended to the label, and `aria-required` will be set
   * on the Field's child.
   */
  required?: boolean;

  /**
   * The size of the Field's label.
   * @default medium
   */
  size?: "small" | "medium" | "large";

  style?: CSSProperties;

  /**
   * A message about the validation state. By default, this is an error message, but it can be a success, warning,
   * or custom message by setting `validationState`.
   */
  validationMessage?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * The icon associated with the `validationMessage`. This will only be displayed if `validationMessage` is set.
   *
   * The default depends on `validationState`:
   * * error: `<ErrorCircle12Filled />`
   * * warning: `<Warning12Filled />`
   * * success: `<CheckmarkCircle12Filled />`
   * * none: `null`
   */
  validationMessageIcon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * The `validationState` affects the display of the `validationMessage` and `validationMessageIcon`.
   *
   * * error: (default) The validation message has a red error icon and red text, with `role="alert"` so it is
   *     announced by screen readers. Additionally, the control inside the field has `aria-invalid` set, which adds a
   *     red border to some field components (such as `Input`).
   * * success: The validation message has a green checkmark icon and gray text.
   * * warning: The validation message has a yellow exclamation icon and gray text, with `role="alert"` so it is
   *     announced by screen readers.
   * * none: The validation message has no icon and gray text.
   * @default error when validationMessage is set; none otherwise.
   */
  validationState?: "none" | "success" | "warning" | "error";
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

Note: Storybook-only layout decorators are omitted. Examples use the documentation preview spacing instead.

## Component Examples

Source: Fluent, adapted for CoreAI.

Field can be used with any input components in this library. This story shows some examples.
        It can also be used to add a label or error text to components like ProgressBar.

[Download source](/coreai-design-system/source/examples/components-field--component-examples.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { Textarea } from "@coreai-ds/react-components";
import { Combobox } from "@coreai-ds/react-components";
import { Option } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";
import { Checkbox } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import { Switch } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import * as React from 'react';

const useStackClassName = makeResetStyles({
    display: 'flex',
    flexDirection: 'column',
    rowGap: tokens.spacingVerticalL,
});

export const ComponentExamples = (): JSXElement => (<div className={useStackClassName()}>
    <Field label="Input">
      <Input />
    </Field>
    <Field label="Textarea">
      <Textarea />
    </Field>
    <Field label="Combobox">
      <Combobox>
        <Option>Option 1</Option>
        <Option>Option 2</Option>
        <Option>Option 3</Option>
      </Combobox>
    </Field>
    <Field label="SpinButton">
      <SpinButton />
    </Field>
    <Field hint="Checkboxes use their own label instead of the Field label.">
      <Checkbox label="Checkbox"/>
    </Field>
    <Field label="Slider">
      <Slider defaultValue={25}/>
    </Field>
    <Field label="Switch">
      <Switch />
    </Field>
    <Field label="RadioGroup">
      <RadioGroup>
        <Radio label="Option 1"/>
        <Radio label="Option 2"/>
        <Radio label="Option 3"/>
      </RadioGroup>
    </Field>
  </div>);

export default ComponentExamples;
```

## Disabled control

Source: Fluent, adapted for CoreAI.

When the control inside the Field is disabled, the label should _not_ be marked disabled. This ensures the label remains readable to users.

[Download source](/coreai-design-system/source/examples/components-field--disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Disabled = (): JSXElement => (<Field label="Field with disabled control">
    <Input disabled/>
  </Field>);

export default Disabled;
```

## Hint

Source: Fluent, adapted for CoreAI.

The `hint` provides additional descriptive information about the field. Hint text should be used sparingly.

[Download source](/coreai-design-system/source/examples/components-field--hint.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Hint = (): JSXElement => (<Field label="Example with hint" hint="Sample hint text.">
    <Input />
  </Field>);

export default Hint;
```

## Horizontal Orientation

Source: Fluent, adapted for CoreAI.

Setting `orientation="horizontal"` places the label beside the input. The validationMessage and hint still appear below the input.<br />The label width is a fixed 33% of the width of the field. This makes it so horizontal fields are aligned when stacked together.

[Download source](/coreai-design-system/source/examples/components-field--horizontal.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Horizontal = (): JSXElement => (<Field label="Horizontal" orientation="horizontal" hint="Validation message and hint are below the input.">
    <Input />
  </Field>);

export default Horizontal;
```

## Info button

Source: Fluent, adapted for CoreAI.

Add an info button to the label by replacing the Field's label with an `InfoLabel`. This can be done using a [slot render function](https://react.fluentui.dev/?path=/docs/concepts-developer-customizing-components-with-slots--docs#replacing-the-entire-slot). See the code from this story for more details.

[Download source](/coreai-design-system/source/examples/components-field--info.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import type { LabelProps } from "@coreai-ds/react-components";
import { InfoLabel } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Info = (): JSXElement => (<Field label={{
        // Setting children to a render function allows you to replace the entire slot.
        // The first param is the component for the slot (Label), which we're ignoring to use InfoLabel instead.
        // The second param are the props for the slot, which need to be passed to the InfoLabel.
        children: (_: unknown, slotProps: LabelProps) => (<InfoLabel {...slotProps} info="Example info">
          Field with an info button
        </InfoLabel>),
    }}>
    <Input />
  </Field>);

export default Info;
```

## Third party controls a Field

Source: Fluent, adapted for CoreAI.

Field uses context to associate its label and message text with its child form control. All of the form controls in this library support FieldContext.<br/>To use a third party control that does not support FieldContext, the child of Field may be a function that takes props to pass to the control. See the code in this example for more details.

[Download source](/coreai-design-system/source/examples/components-field--render-function.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import * as React from 'react';
import { makeStyles } from "@coreai-ds/react-components";
import { AnimalCat24Regular } from "@fluentui/react-icons";

const useCatInputStyles = makeStyles({
    root: {
        display: 'flex',
        alignItems: 'center',
        columnGap: '4px',
    },
});

const CatInput: React.FC<React.InputHTMLAttributes<HTMLInputElement>> = props => {
    const styles = useCatInputStyles();
    return (<div className={styles.root}>
      <AnimalCat24Regular />
      <input {...props}/>
    </div>);
};

export const RenderFunction = (): JSXElement => (<Field label="Third party input" hint="Use a render function to properly associate the label with the control.">
    {fieldProps => <CatInput {...fieldProps}/>}
  </Field>);

export default RenderFunction;
```

## Required

Source: Fluent, adapted for CoreAI.

When a Field is marked as `required`, the label has a red asterisk, and the input gets the `aria-required` property for accessiblity tools.

[Download source](/coreai-design-system/source/examples/components-field--required.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

export const Required = (): JSXElement => (<Field label="Required field" required>
    <Input />
  </Field>);

export default Required;
```

## Size

Source: Fluent, adapted for CoreAI.

The `size` prop affects the size of the Field's label, as well as form controls that support a `size` prop.

[Download source](/coreai-design-system/source/examples/components-field--size.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import * as React from 'react';

const useStackClassName = makeResetStyles({
    display: 'flex',
    flexDirection: 'column',
    rowGap: tokens.spacingVerticalL,
});

export const Size = (): JSXElement => (<div className={useStackClassName()}>
    <Field label="Size small" size="small">
      <Input />
    </Field>
    <Field label="Size medium" size="medium">
      <Input />
    </Field>
    <Field label="Size large" size="large">
      <Input />
    </Field>
  </div>);

export default Size;
```

## Validation Message

Source: Fluent, adapted for CoreAI.

<p>The `validationMessage` is used to give the user feedback about the value entered. Field does not do validation itself, but can be used to report the result of form validation.</p><p>The `validationState` affects the behavior and appearance of the message: <ul>  <li>`error` - (default) The validation message has red text with a red error icon. It has `role="alert"`    so it is announced by accessibility tools. Additionally, the control inside the field has `aria-invalid`    set, which adds a red border to some field components (such as `Input`).</li>  <li>`success` - The validation message has gray text with a green checkmark icon.</li>  <li>`warning` - The validation message has gray text with a yellow exclamation icon.</li>  <li>`none` - The validation message has gray text with no icon.</li></ul></p><p>Optionally, `validationMessageIcon` can be used to override the default icon (or add an icon in the case of `validationState="none"`).</p>

[Download source](/coreai-design-system/source/examples/components-field--validation-message.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeResetStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { SparkleFilled } from "@fluentui/react-icons";
import * as React from 'react';

const useStackClassName = makeResetStyles({
    display: 'flex',
    flexDirection: 'column',
    rowGap: tokens.spacingVerticalL,
});

export const ValidationMessage = (): JSXElement => (<div className={useStackClassName()}>
    <Field label="Error state" validationMessage="This is an error message.">
      <Input />
    </Field>
    <Field label="Warning state" validationState="warning" validationMessage="This is a warning message.">
      <Input />
    </Field>
    <Field label="Success state" validationState="success" validationMessage="This is a success message.">
      <Input />
    </Field>
    <Field label="Custom state" validationState="none" validationMessageIcon={<SparkleFilled />} validationMessage="This is a custom message.">
      <Input />
    </Field>
  </div>);

export default ValidationMessage;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=32182-95336)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/field/usage)