# Textarea

> A multi-line text field for forms, at least three lines high, with an optional character counter.

Source: https://raft-design.botiverse.build/components/textarea. Generated from the current release; where it differs from what you remember, this page is right.

A textarea takes several lines of text in a form: a description, a note, instructions for an agent. It has the same ink border and states as an [Input](https://raft-design.botiverse.build/components/input.md), is at least three lines of field text high (96px on a phone, 90px on a desktop), and people can drag it taller.

```tsx
import { Field, FieldDescription, FieldError, FieldLabel, Textarea } from "@botiverse/raft-ui";

export function TextareaWithFieldContent() {
  return (
    <div className="grid w-80 gap-6">
      <Field>
        <FieldLabel htmlFor="textarea-project-summary">Project summary</FieldLabel>
        <Textarea id="textarea-project-summary" rows={4} defaultValue="Weekly launch update" />
        <FieldDescription>Keep the summary under 120 characters.</FieldDescription>
      </Field>

      <Field invalid>
        <FieldLabel htmlFor="textarea-invalid-message">Message</FieldLabel>
        <Textarea id="textarea-invalid-message" rows={4} data-invalid defaultValue="" />
        <FieldError match>Message is required.</FieldError>
      </Field>
    </div>
  );
}
```

## When to use

| Situation                                        | Use                                 |
| ------------------------------------------------ | ----------------------------------- |
| Several lines of text that are saved with a form | Textarea                            |
| One line of text                                 | [Input](https://raft-design.botiverse.build/components/input.md)          |
| A message that is sent                           | [Composer](https://raft-design.botiverse.build/components/composer.md) |

## Anatomy

- `Textarea`: the field. Required.
- `TextareaGroup`: holds the textarea and its counter. Needed only with a counter.
- `TextareaCounter`: the count and the limit, below the field at its end (72/280).

## States

- **Invalid:** `data-invalid` gives the textarea a `danger-strong` border; the message goes in the field ([Field](https://raft-design.botiverse.build/components/field.md)).
- **Over the limit:** the counter turns bold `danger-strong` once the count passes the limit.
- **Disabled:** the shared disabled look ([States](https://raft-design.botiverse.build/foundations/states.md)), and it can no longer be resized. Disabled wins over invalid.

## Behavior

- Let people drag the textarea taller. It never gets shorter than three lines of field text.
- To make it grow with its content, use `field-sizing-content` together with a maximum height, so a long draft scrolls inside the field instead of pushing the page down.
- Add a counter when the value has a limit. Pass the current value and the limit to `TextareaCounter`.
- Leave out the native `maxLength` when the counter shows the limit: `maxLength` stops typing at the limit, so the counter could never show that the text is over it.

## Accessibility

Textarea renders a native `<textarea>`; it is not a Base UI control.

- Name it with a `FieldLabel` whose `htmlFor` matches the textarea's `id` ([Field](https://raft-design.botiverse.build/components/field.md)).
- `data-invalid` also sets `aria-invalid`.
- Reference the counter from `aria-describedby` when the limit matters, so it is read with the field.

## API

### Textarea

Also takes the attributes of its element.

### TextareaCounter

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `count` | `number` |  |  |
| `getLength` | `(value: string) => number` |  |  |
| `limit` (required) | `number` |  |  |
| `value` | `string` |  |  |

Also takes the attributes of its element.

### TextareaGroup

Also takes the attributes of its element.

## Changes

- 0.10.0 (Breaking Changes): Field frames (`Input`, `Textarea`, `InputGroup`, `Select`, `Combobox`, `ComboboxSelect`, `Composer`, option `Card`, `SearchTrigger`) are drawn at 1px in `line-field` instead of 1.5px, on the phone too.
- 0.4.0 (Breaking Changes): **Invalid-state styling now keys off `data-invalid` instead of `aria-invalid`.** `Input`, `Textarea`, and form controls style the error visual from `data-invalid` and mirror it to `aria-invalid`; passing `aria-invalid` alone no longer shows the error style. Update callers to pass `data-invalid`. ([b3786da](https://github.com/botiverse/rui/commit/b3786da))
