# Textarea

> A multi-line input with an optional character limit.

## Examples

### With a limit

```vue
<script setup lang="ts">
const bio = ref("Building the web for humans.");
</script>

<template>
  <div class="demo-field">
    <UiTextarea v-model="bio" label="Bio" :max-length="80" :rows="3" />
  </div>
</template>
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | — | Visible label, linked to the control. |
| `hint` | `string` | — | Help text under the control, announced as its description. |
| `error` | `string \| boolean` | — | `true` marks the control invalid; a string also shows it as the message, replacing the hint. |
| `maxLength` | `number` | — | Character limit. Shows a live counter and flags values already over it. |
| `optional` | `boolean` | `false` | Appends the `optional` translation to the label. |
| `disabled` | `boolean` | `false` | Disables the control. |
| `rows` | `number` | `4` | Visible text lines. |
| `id` | `string` | — | Id for the control; generated with `useId()` when omitted. |
| `modelValue` | `string` | — | The value. |

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `[value: string \| undefined]` | `v-model:modelValue` update. |

## Styling

- Parts (`[data-part="…"]`): `field`, `field-label`, `field-optional`, `textarea`, `field-footer`, `field-count`, `field-message`
- State attributes: `data-field-error`, `data-field-count-exceeded`, `data-field-tone`

## Accessibility

- Values over the limit are flagged, not truncated.
