---
title: "Components — Field"
canonical: https://sky-ui.cf.sky.com/components/field
apiPackages: [{"name":"@sky-uk/ui-core","representedVersion":"13.2.0"}]
---

# Components — Field

The Field component is used to decorate TextInput and Select components with a label, message and validation.

```js
import { Field } from '@sky-uk/ui-core';
```

---

The `Field` component is used to decorate [Text Input](/components/text-input/react/), [Textarea](/components/textarea/react/) and [Select](/components/select/react/) components with a label, message and validation.

---

## Sub-components

- `Field.Label` – label of the input element
- `Field.Control` – input element
- `Field.Validation` – error message of the input element
- `Field.Message` – inline message of the input element

---

### Control

Either a [Text Input](/components/text-input/react/), [Textarea](/components/textarea/react/) or [Select](/components/select/react/) needs to be passed to the `as` prop of the `Field.Control`.

---

#### TextInput

```tsx
<Field>
    <Field.Label htmlFor="my-input">Label</Field.Label>
    <Field.Control as={TextInput} value="My Value" id="my-input" aria-describedby="message" />
    <Field.Message id="message">Inline message providing addition context on the input field.</Field.Message>
</Field>
```

---

#### Textarea

```tsx
<Field>
    <Field.Label htmlFor="my-input">Label</Field.Label>
    <Field.Control as={Textarea} value="My Value" id="my-input" aria-describedby="message" />
    <Field.Message id="message">Inline message providing addition context on the input field.</Field.Message>
</Field>
```

---

#### Select

```tsx
<Field>
    <Field.Label htmlFor="my-input">Label</Field.Label>

    <Field.Control as={Select} id="my-input" aria-describedby="message">
        <Select.Option defaultValue>Please select an option...</Select.Option>
        <Select.Option>Option 1</Select.Option>
        <Select.Option>Option 2</Select.Option>
        <Select.Option>Option 3</Select.Option>
    </Field.Control>

    <Field.Message id="message">Inline message providing addition context on the input field.</Field.Message>
</Field>
```

**Note:** Using a `disabled`, `defaultValue` on an uncontrolled `Select` input is not possbile with React. Once `disabled` is applied, React then considered the option no longer selectable by default and this option will only appear once a user has interacted with the `Select`.

    Using a controlled field allows the `Select` to have a selected, but `disabled` option.

```tsx
function Example () {
  const [value, setValue] = React.useState('unselectable')

  const handleChange = (e) => {
    setValue(e.target.value)
  }

  return (
    <Field>
        <Field.Label htmlFor="my-input">Label</Field.Label>

        <Field.Control as={Select} value={value} id="my-input" aria-describedby="message" onChange={handleChange}>
            <Select.Option value="unselectable" disabled>Please select an option...</Select.Option>
            <Select.Option>Option 1</Select.Option>
            <Select.Option>Option 2</Select.Option>
            <Select.Option>Option 3</Select.Option>
        </Field.Control>

        <Field.Message id="message">Inline message providing addition context on the input field.</Field.Message>
    </Field>
  )
}
```

---

## State and Validation

`state` can be `confirmed` or `error`.

The `Field` component will ensure the `Validation` and `Label` have the same state as the input component.

**Note:** It is best practice to validate input fields only upon form submission.

```tsx
<Field state="error">
    <Field.Label htmlFor="my-input">Label</Field.Label>

    <Field.Control as={Select} id="my-input" aria-describedby="validation message">
        <Select.Option defaultValue>Please select an option...</Select.Option>
        <Select.Option>Option 1</Select.Option>
        <Select.Option>Option 2</Select.Option>
        <Select.Option>Option 3</Select.Option>
    </Field.Control>
    <Field.Message id="message">Your inline message goes here.</Field.Message>
    <Field.Validation id="validation">Something is not quite right.</Field.Validation>
</Field>
```

---

### Inline Message

`Field.Message` could be used to display inline message related to the field. These will always be displayed as the bottom most element on the input field.

```tsx
<Field state="confirmed">
    <Field.Label htmlFor="my-input">Label</Field.Label>
    <Field.Control as={TextInput} value="My Value" id="my-input" aria-describedby="validation message" />
    <Field.Validation id="validation">Input is validated!</Field.Validation>
    <Field.Message id="message">Your inline message goes here.</Field.Message>
</Field>
```

---

## Required Fields

Adding `required` attribute on the `Field.Control` will render an asterisk to signify that a field is required. The asterisk color will also change based on the input status.

```tsx
<Field>
    <Field.Label htmlFor="my-input">Label</Field.Label>
    <Field.Control as={TextInput} required id="my-input" aria-describedby="message"/>
    <Field.Message id="message">* required field</Field.Message>
</Field>
```

---

## Disabled and Read-only

You can provide `disabled` or `readOnly` properties to make text input or textarea non-interactive. Select component only has `disabled` property.

```tsx
<Field>
    <Field.Label htmlFor="my-input">Label</Field.Label>
    <Field.Control as={TextInput} disabled value="my value" id="my-input" aria-describedby="message" />
    <Field.Message id="message">Your message goes here!</Field.Message>
</Field>
```

---

## Accessibility

Please refer to the [W3C Forms Concepts](https://www.w3.org/WAI/tutorials/forms/) guide when working with forms.
