---
title: Textarea
description: A multi-line text field with autogrow and platform-adaptive styling.
---
import Source from './_generated/textarea.mdx';

A multi-line text field — the multi-line sibling of [Input](/docs/components/input). It shares the input's chrome: a Material 3 notched outline with a floating label, and an iOS grouped-list surface with an inline label. It grows with its content between a minimum and maximum number of rows.

<DemoFrame component="textarea" height={520} />

## Installation

```bash
npx touchcn add textarea
```

## Usage

<CodeGroup>

```html Angular
<tcn-textarea label="Bio" placeholder="Tell us about yourself" [(value)]="bio" />
```

```tsx React
import { TcnTextarea } from '@/components/ui/textarea';

<TcnTextarea label="Bio" placeholder="Tell us about yourself" onValueChange={setBio} />
```

```vue Vue
<script setup lang="ts">
import { TcnTextarea } from '@/components/ui/textarea';
</script>

<template>
  <TcnTextarea v-model="bio" label="Bio" placeholder="Tell us about yourself" />
</template>
```

</CodeGroup>

## Autogrow

The field grows with its content between `minRows` and `maxRows`, then scrolls. This uses the modern CSS [`field-sizing: content`](https://developer.mozilla.org/en-US/docs/Web/CSS/field-sizing) property, clamped by `min-height` / `max-height` derived from the row counts.

`field-sizing` reached [Baseline](https://web-platform-dx.github.io/web-features-explorer/features/field-sizing/) in 2026 (Chrome 123, Safari 26.2, Firefox 152). **No JavaScript is used** — so on browsers older than that Baseline the field falls back to the `rows` attribute (set to `minRows`), rendering a correctly-sized, internally-scrolling multi-line field. Autogrow is a progressive enhancement on top of that solid baseline; there is no measurement/observer plumbing, keeping the copied component free of engine behavior.

<CodeGroup>

```html Angular
<tcn-textarea label="Notes" [minRows]="3" [maxRows]="8" />
```

```tsx React
<TcnTextarea label="Notes" minRows={3} maxRows={8} />
```

```vue Vue
<TcnTextarea label="Notes" :min-rows="3" :max-rows="8" />
```

</CodeGroup>

## Props

| Prop            | Type                      | Default | Description                                        |
| --------------- | ------------------------- | ------- | -------------------------------------------------- |
| `label`         | `string`                  | —       | Floating (MD) / inline (iOS) field label.          |
| `value`         | `string` (model, Angular) | `''`    | Two-way bound value.                               |
| `placeholder`   | `string`                  | —       | Placeholder text.                                  |
| `minRows`       | `number`                  | `2`     | Minimum visible rows; the field never shrinks below this. |
| `maxRows`       | `number`                  | `6`     | Maximum rows before the field stops growing and scrolls. |
| `error`         | `boolean`                 | `false` | Tint the outline / border destructive.             |
| `disabled`      | `boolean`                 | `false` | Disable the field.                                 |
| `onValueChange` | `(value: string) => void` | —       | Convenience callback with the raw value (React).   |

<Source />
