Textarea
Overview
A multi-line text input for longer free-form content, supporting auto-resizing, character counting, and clearable functionality. Use it for descriptions, comments, messages, or any content that spans multiple lines. For single-line input use SInput.
Usage
Features
- 📏 6 sizes: xs, sm, md, lg, xl, 2xl
- 📐 Autosize with
minRows/maxRowsbounds and overflow switching - 🧹 Clearable mode with an i18n
aria-labelclear button - 🔢 Character counter (
count / maxlength) with and withoutmaxlength - 🔄
resizecontrol: none / vertical / horizontal (ignored while autosize is active) - 📋 Native form submission via a proxied hidden input when
nameis set - 🧩
clear/counter/footerslots for per-part customization - ♿ Full accessibility support —
aria-roledescription, clear button naming, axe-clean
Textarea component family
- STextarea - Base multi-line text area component
- STextareaClear - Clear button, shown on hover/focus when
clearable
Demos
Basic
Footer
API
Aria Layer
6Textarea
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<TextareaUi> | — | Per-slot class overrides for the component. |
resize | TextareaResize | — | The resize of the textarea
if autosize is true, the resize will be ignored |
textareaRef | ((el: HTMLTextAreaElement) => void) | — | The function to set the textarea element. |
clearable | boolean | false | Whether to show the clear trigger. |
showCounter | boolean | false | Whether to show the counter. |
controlProps | TextareaControlProps | — | Properties forwarded to the control element. |
clearProps | TextareaClearProps | — | Properties forwarded to the clear element. |
counterProps | TextareaCounterProps | — | Properties forwarded to the counter element. |
defaultValue | string | — | The default value of the textarea |
modelValue | string | — | The controlled value of the textarea |
autosize | boolean | TextareaAutosizeOptions | — | When `true` or an options object, enables auto-resizing based on content |
id | string | — | Id of the textarea element |
autofocus | boolean | — | When `true`, the textarea is auto-focused. |
disabled | boolean | — | When `true`, prevents the user from interacting with the textarea. |
maxlength | number | — | The maximum number of characters allowed in the textarea |
minlength | number | — | The minimum number of characters allowed in the textarea |
placeholder | string | — | The placeholder of the textarea |
readonly | boolean | — | When `true`, the textarea is read-only. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
clear | PointerEvent | Emitted when the clear button is clicked. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
clear | TextareaCompactSlotProps | Custom content for the clear slot. |
counter | TextareaCompactSlotProps | Custom content for the counter slot. |
footer | TextareaCompactSlotProps | Custom content for the footer slot. |
TextareaClear
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
clear | PointerEvent | Emitted when the clear button is clicked. |
TextareaCompact
Props
| Prop | Type | Default | Description |
|---|---|---|---|
textareaRef | ((el: HTMLTextAreaElement) => void) | — | The function to set the textarea element. |
clearable | boolean | false | Whether to show the clear trigger. |
showCounter | boolean | false | Whether to show the counter. |
controlProps | TextareaControlProps | — | Properties forwarded to the control element. |
clearProps | TextareaClearProps | — | Properties forwarded to the clear element. |
counterProps | TextareaCounterProps | — | Properties forwarded to the counter element. |
defaultValue | string | — | The default value of the textarea |
modelValue | string | — | The controlled value of the textarea |
autosize | boolean | TextareaAutosizeOptions | — | When `true` or an options object, enables auto-resizing based on content |
id | string | — | Id of the textarea element |
autofocus | boolean | — | When `true`, the textarea is auto-focused. |
disabled | boolean | — | When `true`, prevents the user from interacting with the textarea. |
maxlength | number | — | The maximum number of characters allowed in the textarea |
minlength | number | — | The minimum number of characters allowed in the textarea |
placeholder | string | — | The placeholder of the textarea |
readonly | boolean | — | When `true`, the textarea is read-only. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
clear | PointerEvent | Emitted when the clear button is clicked. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
clear | TextareaCompactSlotProps | Custom content for the clear slot. |
counter | TextareaCompactSlotProps | Custom content for the counter slot. |
footer | TextareaCompactSlotProps | Custom content for the footer slot. |
TextareaControl
TextareaCounter
TextareaRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | — | The default value of the textarea |
modelValue | string | — | The controlled value of the textarea |
autosize | boolean | TextareaAutosizeOptions | — | When `true` or an options object, enables auto-resizing based on content |
id | string | — | Id of the textarea element |
autofocus | boolean | — | When `true`, the textarea is auto-focused. |
disabled | boolean | — | When `true`, prevents the user from interacting with the textarea. |
maxlength | number | — | The maximum number of characters allowed in the textarea |
minlength | number | — | The minimum number of characters allowed in the textarea |
placeholder | string | — | The placeholder of the textarea |
readonly | boolean | — | When `true`, the textarea is read-only. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
Notes
Architecture and benchmark differences
VeanUI splits the textarea into an Aria layer (@vean/aria/textarea) that owns state, autosize measurement, and form proxying, and a styled layer (@vean/ui) that owns variants and UnoCSS classes. The Aria TextareaCompact composes TextareaRoot / TextareaControl / TextareaClear / TextareaCounter and exposes clear / counter / footer slots. This mirrors the headless/styled split of Radix and differs from single-package libraries such as Ant Design, Element Plus, and Mantine.
| Capability | VeanUI | Ant Design Input.TextArea | Element Plus Input | Mantine Textarea |
|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — |
| Controlled / uncontrolled | ✅ | ✅ | ✅ | ✅ |
| Autosize (min/max rows) | ✅ | ✅ | ✅ | ✅ |
| Clear button (hover reveal) | ✅ | — | ✅ | — |
Character counter count/max | ✅ | ✅ | ✅ | — |
resize control | ✅ | — | ✅ | ✅ |
| Native form proxying | ✅ | — | — | — |
footer slot | ✅ | — | — | — |
error state | — | — | ✅ | ✅ |
Cautions
- Autosize relies on real layout (
scrollHeight/getComputedStyle); behavior is verified through browser e2e tests, not happy-dom unit tests. error,loading,showCount, IME composition events, andchangeevents are not implemented; they are tracked as enhancement backlog.- The counter does not announce itself with
aria-live; add anaria-liveregion via thecounterslot if live announcements are required.
FAQ
How do I make the textarea grow with its content?
Pass autosize (boolean) or autosizeOptions with minRows / maxRows. The height adjusts on input and switches to overflow-y: auto at maxRows.
How do I show a character counter?
Pass showCounter with maxlength to show count / maxlength, or without maxlength to show the raw count. Customize the presentation via the counter slot.
How do I control resizing?
Use the resize prop (none / vertical / horizontal). When autosize is active, resize is ignored because height is managed automatically.
How does the textarea submit its value in a native form?
Pass name — the component renders a visually hidden proxy input carrying the current value, so native form submission works without extra wiring.