> ## Documentation Index
> Fetch the complete documentation index at: https://docs.awaitio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Input Textarea

> Asks for longer text over several lines.

`io.input.textarea()` requests a string value that can span several lines. Provided by the `@awaitio/input-textarea` package.

<Frame>
  <img src="https://mintcdn.com/awaitio/MjbT5AW66vMXbVck/images/io-input-textarea.png?fit=max&auto=format&n=MjbT5AW66vMXbVck&q=85&s=cd58b775e7181f39ef5c28b2383131da" alt="A Why refund pay_1042? text area with a filled-in reason and help text under it" width="1004" height="332" data-path="images/io-input-textarea.png" />
</Frame>

## Install

```bash theme={null}
npm install @awaitio/input-textarea
```

## Setup

Register it under the key you want in `io`, see [Input components](/core/components):

```ts app.ts {5} theme={null}
import { inputTextarea } from '@awaitio/input-textarea';

export const app = new AwaitIO({
  // name, actionsDirectory, theme, secret, users…
  components: { input: { textarea: inputTextarea } },
});
```

## Usage

```ts theme={null}
const reason = await io.input.textarea('Why refund this payment?', {
  lines: 4,
  minLength: 10,
  helpText: 'Goes to the customer with the refund',
});
```

## Props

| Prop | Type | Required | Description |
| - | - | - | - |
| `placeholder` | `string` | Optional | Text shown in the empty field. |
| `helpText` | `string` | Optional | Secondary text under the field. |
| `defaultValue` | `string` | Optional | The value the field starts with. Defaults to an empty string. |
| `lines` | `number` | Optional | Visible height in lines. A whole number, 1 or more. Defaults to `4`. The person can still resize the field. |
| `minLength` | `number` | Optional | Minimum number of characters. A whole number, 0 or more. |
| `maxLength` | `number` | Optional | Maximum number of characters. A whole number, 1 or more. |
| `disabled` | `boolean` | Optional | Shows the starting value without letting it change; the handler gets that value whatever the browser sends. |

## Optional

The field is required. Chain `.optional()` to let it stay empty; the handler then gets `string | undefined`, see [Optional fields](/core/components#optional-fields).

```ts theme={null}
const note = await io.input.textarea('Note for the team').optional();
```

## Returns

`string` with the line breaks the person typed (`\n`).

## Built-in validation

The field is always required. Checked on the server:

| When | Message |
| - | - |
| The value is empty or only whitespace | `<label> is required.` |
| Shorter than `minLength` | `<label> must be at least <minLength> characters long.` |
| Longer than `maxLength` | `<label> must be at most <maxLength> characters long.` |

## Custom validation

Chain `.validate()` for a check of your own. It runs on the server after the checks above, gets the value the handler would get and returns a message to show under the field, or nothing when the value is fine; see [Custom validation](/core/components#custom-validation).

```ts theme={null}
const reason = await io.input.textarea('Reason for the refund').validate((reason) => {
  return reason.trim().split(/\s+/).length >= 3 ? undefined : 'Write at least three words.';
});
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.