Back to Fluentui

TextField to Input Migration

apps/public-docsite-v9/src/Concepts/Migration/FromV8/Components/Input.mdx

4.40.2-hotfix210.0 KB
Original Source

import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Concepts/Migration/from v8/Components/TextField to Input Migration" />

TextField to Input Migration

Fluent UI v8 provides the TextField control for entering and editing text. In Fluent UI v9 TextField is replaced with Input for single line input. For multiline input, use Textarea.

While basic usage is largely the same, Input omits some features found in TextField, preferring to compose several components together for greater flexibility.

Examples

Basic Migration

Basic usage of TextField looks like

tsx
import * as React from 'react';
import { TextField } from '@fluentui/react/lib/TextField';}
import { Stack, IStackProps, IStackStyles } from '@fluentui/react/lib/Stack';

const columnProps: Partial<IStackProps> = {
  tokens: { childrenGap: 15 },
  styles: { root: { width: 300 } },
};

const TextFieldV8BasicExample = () => {
  return <Stack {...columnProps}>
    <TextField label="Standard" />
    <TextField label="Disabled" disabled defaultValue="I am disabled" />
    <TextField label="Read-only" readOnly defaultValue="I am read-only" />
    <TextField label="Required " required />
    <TextField ariaLabel="Required without visible label" required />
    <TextField label="With error message" errorMessage="Error message" />
  </Stack>
}

An equivalent Input usage is:

tsx
import * as React from 'react';
import { makeStyles, Text, Label, Input } from '@fluentui/react-components';
import { useId } from '@fluentui/react-utilities';

const useStackStyles = makeStyles({
  root: {
    maxWidth: '300px',
    display: 'flex',
    flexDirection: 'column',

    '> * + *': {
      marginTop: '20px',
    },

    '> div': {
      display: 'flex',
      flexDirection: 'column',
    },
  },
});

const InputV9BasicExample = () => {
  const stackStyles = useStackStyles();
  const standardId = useId('standard');
  const disabledId = useId('disabled');
  const readonlyId = useId('readonly');
  const requiredId = useId('required');
  const errorId = useId('error');
  const errorMessageId = useId('error-message');

  return (
    <div className={stackStyles.root}>
      <div>
        <Label htmlFor={standardId}>Standard</Label>
        <Input id={standardId} />
      </div>

      <div>
        <Label htmlFor={disabledId}>Disabled</Label>
        <Input id={disabledId} disabled defaultValue="I am disabled" />
      </div>

      <div>
        <Label htmlFor={readonlyId}>Read Only</Label>
        <Input id={readonlyId} readOnly defaultValue="I am read only" />
      </div>

      <div>
        <Label htmlFor={requiredId} required>
          Required
        </Label>
        <Input id={requiredId} required defaultValue="I am required" />
      </div>

      <div>
        <Input
          aria-label="Required without visible label"
          required
          defaultValue="I am required without a visible label"
        />
      </div>

      <div>
        <Label htmlFor={errorId}>With Error Message</Label>
        <Input id={errorId} aria-describedby={errorMessageId} />
        <Text id={errorMessageId}>Error message</Text>
      </div>
    </div>
  );
};

Prop Mapping

This table maps v8 TextField props to the v9 Input equivalent.

v8v9Notes
`componentRef``ref`v9 provides access to the underlyig DOM node, not ITextField
`elementRef``ref`
`multiline`n/aUse `Textarea`
`resizable`n/a
`autoAjustHeight`n/aSee `Textarea` docs
`underlined``appearance`
`borderless``appearance`
`label`Use `Label` componentBe sure to associate `Label` with `Input` via `htmlFor`
`onRenderLabel`n/aUse slots to customize `Input`
`description`n/aUse another element like `Text` and associate it with `Input` via `aria-describedby`
`onRenderDescription`n/a
`onRenderInput`n/aUse slots to customize `Input`
`prefix``contentBefore`This is a slot not a `string`
`suffix``contentAfter`This is a slot not a `string`
`onRenderPrefix`n/aUse slots to customize `Input`
`onRenderSuffix`n/aUse slots to customize `Input`
`iconProps`Use `contentBefore` or `contentAfter` slot
`defaultValue``defaultValue`Mutually exclusive with `value`
`value``value`Mutually exclusive with `defaultValue`
`disabled``disabled`
`readOnly``readOnly`In v9 this is the native HTML prop
`invalid`n/av9 `Input` does not handle validation states
`errorMessage`n/aUse another element like `Text` and associate it with `Input` via `aria-describedby`
`onChange``onChange`Typescript types have changed
`onNotifyValidationResult`n/av9 `Input` does not handle validation
`onGetErrorMessage`n/av9 `Input` does not handle error states
`deferredValidationTime`n/av9 `Input` does not handle validation
`className``className`
`inputClassName`Use `input` slot
`ariaLabel``aria-label`
`validateOnFocusIn`n/av9 `Input` does not handle validation
`validateOnFocusOut`n/av9 `Input` does not handle validation
`validateOnLoad`n/av9 `Input` does not handle validation
`theme`n/aUse `FluentProvider` to customize themes
`styles``className`
`autoComplete``autoComplete`In v9 this is the native HTML prop
`canRevealPassword`n/av9 `Input` does not provide built in password reveal behavior
`revealPasswordAriaLabel`n/av9 `Input` does not provide built in password reveal behavior