Default

Loading interactive example. Full source is available below.

View example source
Download source
// 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;

Resources

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 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.

API referenceGenerated CoreAI prop and type summaries

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

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.

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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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

Loading interactive example. Full source is available below.

Download source
// 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;