# Textarea

> Textareas let people enter text that can run over several lines, like a description or a message.

Source: https://contributors.home-assistant.io/design/components/textarea/

Live demo of `ha-textarea`.

```html
<ha-textarea label="Description" value="Turns on the hallway lights when someone comes home after sunset." resize="auto"></ha-textarea>
```

## Overview

A textarea lets people enter free text that can be longer than a single line: the description of an automation, a label, or a calendar event, or a message to send to a voice assistant.

## When to use

Use a textarea for:

- Free text that can run over several lines, like a description, notes, or a message

Don't use a textarea for:

- A short, single line value, like a name. Use a [text input](https://contributors.home-assistant.io/design/components/input/).
- Code or YAML. The frontend has a dedicated code editor for that.

## Anatomy

1. **Container**: the filled field, with a line at the bottom
2. **Label**: names the text. It sits inside the field, and moves up when the field has focus or a value.
3. **Text**: the native textarea where people type
4. **Hint**: optional help text below the field, replaced by the validation message when the text is invalid

## Variants

### Growing with the content

Most textareas in the frontend grow with their content: the field starts small, grows while people type, and starts scrolling when it reaches its maximum height (200 pixels by default). That keeps a short text compact, without hiding a long one.

Live demo of `ha-textarea`.

```html
<ha-textarea label="Notes" resize="auto"></ha-textarea>
```

### Fixed height

A textarea that does not grow has a fixed height, in rows of text (4 by default). Use that when you know roughly how much text to expect, and want the space to be there from the start.

Live demo of `ha-textarea`.

```html
<ha-textarea label="Message" rows="6"></ha-textarea>
```

### With a hint

Use the hint for anything that helps people write the text, like whether formatting is supported.

Live demo of `ha-textarea`.

```html
<ha-textarea label="Description" hint="Supports Markdown." resize="auto"></ha-textarea>
```

## Behavior

- **Empty**: the label sits inside the field, at the size of the text.
- **Hover**: the field changes to the hover background.
- **Focus**: the line at the bottom gets thicker and turns the primary color, and so does the label.
- **Filled**: once the field has a value or focus, the label moves up and gets smaller. With a placeholder, the label is always up. The label has the background of the field, so text that scrolls stays readable under it.
- **Required**: the label gets a `*` marker. The field must have text for the form to be valid.
- **Disabled**: the field gets the disabled background and is dimmed to half its opacity, and the text can't be changed or focused.
- **Read-only**: shows text that people can read and copy, but not change.
- **Invalid**: the label and the line at the bottom turn to the danger color, and the validation message takes the place of the hint. A field becomes invalid when the code marks it invalid, when a form check finds the text invalid, or, for a field that checks itself, when it loses focus. It turns valid again as soon as people type valid text.

Live demo of `ha-textarea`.

```html
<ha-textarea label="Description" required resize="auto"></ha-textarea>
<ha-textarea label="Disabled" value="Can't change this." disabled resize="auto"></ha-textarea>
<ha-textarea label="Message" invalid validation-message="Enter a message to send." resize="auto"></ha-textarea>
```

## Specs

### Size

| Property | Value | Token |
| --- | --- | --- |
| Minimum height | 56px | None |
| Maximum height when growing | 200px | `--ha-textarea-max-height` |
| Rows at a fixed height | 4 | None |
| Space above the text | 24px, 12px without a label | `--ha-space-6`, `--ha-space-3` |
| Space below the text | 8px | `--ha-space-2` |
| Padding left and right of the text | 16px | `--ha-space-4` |
| Corner radius | 4px at the top, 0 at the bottom | `--ha-border-radius-sm`, `--ha-border-radius-square` |
| Line at the bottom | 1px, 2px with focus | None |

### Type

| Part | Size | Token |
| --- | --- | --- |
| Text | 14px | `--ha-font-size-m` |
| Label, inside the field | 14px | `--ha-font-size-m` |
| Label, moved up | 10px | `--ha-font-size-xs` |
| Space above the label | 16px, 8px when moved up | `--ha-space-4`, `--ha-space-2` |
| Label padding left and right | 12px | `--ha-space-3` |
| Hint and validation message | 12px | `--ha-font-size-s` |

The text uses `--ha-font-family-body`. Changes in color, line, and label position take 150ms.

### Color

| Part | State | Token |
| --- | --- | --- |
| Background and label background | Resting | `--ha-color-form-background` |
| Background and label background | Hover | `--ha-color-form-background-hover` |
| Background and label background | Disabled | `--ha-color-form-background-disabled` |
| Line at the bottom | Resting | `--ha-color-border-neutral-loud` |
| Line at the bottom | Focus | `--primary-color` |
| Line at the bottom | Invalid | `--ha-color-border-danger-normal` |
| Label | Resting | `--secondary-text-color` |
| Label | Focus | `--primary-color` |
| Label | Invalid | `--ha-color-fill-danger-loud-resting` |
| Hint | All | `--ha-color-text-secondary` |
| Validation message | Invalid | `--ha-color-on-danger-quiet` |

## Guidelines

Do and don't, as live demos.

**Do:** Always give a textarea a short label.

```html
<ha-textarea label="Description" resize="auto"></ha-textarea>
```

**Don't:** Use a placeholder as the label. It disappears once people start typing.

```html
<ha-textarea placeholder="Description" resize="auto"></ha-textarea>
```

Do and don't, as live demos.

**Do:** Say what is wrong, and how to fix it.

```html
<ha-textarea label="Message" invalid validation-message="Enter a message to send." resize="auto"></ha-textarea>
```

**Don't:** Only say that the text is wrong.

```html
<ha-textarea label="Message" invalid validation-message="Invalid value." resize="auto"></ha-textarea>
```

- Keep labels short: **Description**, **Notes**, **Message**.

## Accessibility

### Keyboard

| Key | Action |
| --- | --- |
| <kbd>Tab</kbd> | Moves focus to the textarea, and away from it. A disabled textarea is skipped. |
| <kbd>Enter</kbd> | Starts a new line. |

Key presses in the textarea don't trigger keyboard shortcuts around it.

### Focus

Focus shows as the primary color on the line at the bottom and on the label, instead of a separate focus ring.

### Target size

The field is at least 56px high, and as wide as its container.

### Screen readers

A screen reader announces the textarea with its label, and reads the hint as its description. When the field turns invalid, the validation message is announced. Required, disabled, and read only are announced as well. Without a label, only the placeholder describes it, so always give it a label.

### In the code

- Focus goes to the native textarea inside the component.
- The component stops `keydown` events from leaving it.

- The label is a native `<label>` connected to the textarea, so it is the accessible name.
- Without a label, the `<label>` is empty and hidden from assistive technology. The placeholder is then the only text that describes the textarea.
- The hint and the validation message are connected to the textarea with `aria-describedby`, so screen readers read them as the description.
- The validation message is in a live region, and gets the role `alert` while the field is invalid, so screen readers announce it when it appears.
- Required, disabled, and read-only are set on the native textarea, so assistive technology gets them as is.

## Related

- [Text input](https://contributors.home-assistant.io/design/components/input/): a single line of text
- [Form](https://contributors.home-assistant.io/design/components/form/): builds fields from a schema
- [Selector](https://contributors.home-assistant.io/design/components/selector/): the text selector with `multiline` shows a textarea
- [UI text](https://contributors.home-assistant.io/design/ui-text/): how to write labels, hints, and errors

## In code

The element is `<ha-textarea>`. It is based on the [Web Awesome textarea](https://webawesome.com/docs/components/textarea/).

```html
<ha-textarea label="Description" resize="auto"></ha-textarea>
<ha-textarea label="Message" rows="6"></ha-textarea>
<ha-textarea label="Notes" hint="Supports Markdown." required></ha-textarea>
```

### Attributes

- `label`: the label.
- `value`: the current value.
- `hint`: help text below the textarea.
- `placeholder`: text shown while the textarea is empty.
- `rows`: the number of visible lines. Defaults to `4`.
- `resize`: `none` (default), `vertical`, `horizontal`, `both`, or `auto`. With `auto`, the textarea grows with its content, up to `--ha-textarea-max-height`.
- `required`: makes the field required, and adds a marker after the label.
- `disabled`: disables the textarea.
- `readonly`: makes the textarea read-only.
- `invalid`: marks the textarea as invalid.
- `validation-message`: the message shown when the textarea is invalid. Without it, the browser's own message is shown.
- `auto-validate`: validates the textarea when it loses focus, instead of waiting for the form to be submitted.
- `minlength` and `maxlength`: the minimum and maximum length of the value.
- `name`, `autocomplete`, `autocapitalize`, `autofocus`, `spellcheck`, `inputmode`, and `enterkeyhint`: passed to the native textarea, and work the same as on a regular `<textarea>`.

The maximum height for `resize="auto"` only applies when `resize` is set as an attribute. The property does not reflect, so setting only `.resize` from code gives you a textarea that grows without limit.

### Slots

- `label`: a label with markup. Content in this slot replaces the text of the `label` attribute, including the required marker.
- `hint`: a hint with markup, like a link. Only used when the `hint` attribute is not set.

### Events

- `input`: fires on every change to the value, while people type.
- `change`: fires when the value is committed, like when the textarea loses focus.

Read the new value from `value` on the element. Key presses do not bubble out of the textarea: it stops `keydown` events, so typing, or pressing Enter for a new line, does not trigger keyboard handlers around it.

### Styling

- `--ha-textarea-max-height`: the maximum height with `resize="auto"`. Defaults to `200px`.
- `--ha-textarea-padding-bottom`: the space below the textarea.
- `--ha-textarea-required-marker`: the marker after the label of a required field. Defaults to `"*"`.

Source: [`src/components/ha-textarea.ts`](https://github.com/home-assistant/frontend/blob/dev/src/components/ha-textarea.ts)
