Textarea
import { Textarea } from '@absoluteui/components/textarea';import '@absoluteui/components/textarea/style.css';Using Angular? See Textarea for Angular.
What it does
Section titled “What it does”Multi-line text entry. Textarea renders a native <textarea> with the same field chrome and constraint set as Text Input: label, required indicator, help text, validation message, and optional character counter. Validation runs in the shared validation engine, so messages are localized and identical in every browser. resize: 'auto' grows the control with its content.
When to use
Section titled “When to use”- Free text that may span several lines: comments, descriptions, messages, addresses.
- Long-form values with a length limit that users should see while typing.
- Fields that need consistent, localized validation messages across browsers.
When not to use
Section titled “When not to use”- Single-line values such as names or email addresses: use Text Input.
- Formatted rich text: use Rich Text Editor.
- Numbers: use Number Input.
Examples
Section titled “Examples”Required comments with a character counter
Section titled “Required comments with a character counter”import { Textarea } from '@absoluteui/components/textarea';
const host = document.createElement('div');document.body.append(host);const comments = Textarea.create(host, { label: 'Comments', name: 'comments', required: true, maxLength: 500, showCounter: true });host.addEventListener('aui-change', () => { host.dataset.valid = String(comments.validity.valid);});Grow with content between 2 and 8 rows
Section titled “Grow with content between 2 and 8 rows”import { Textarea } from '@absoluteui/components/textarea';
const host = document.createElement('div');document.body.append(host);Textarea.create(host, { label: 'Message', rows: 2, resize: 'auto', maxRows: 8 });Custom validation
Section titled “Custom validation”import { Textarea } from '@absoluteui/components/textarea';
const host = document.createElement('div');document.body.append(host);Textarea.create(host, { label: 'Bio', minLength: 20, validate: (value) => (/https?:\/\//.test(value) ? 'Links are not allowed in the bio.' : null),});Show messages on first input (Mode B)
Section titled “Show messages on first input (Mode B)”import { configureAbsoluteUI } from '@absoluteui/core';
configureAbsoluteUI({ components: { textarea: { validationTiming: 'input' } } });import { Textarea } from '@absoluteui/components/textarea';import '@absoluteui/components/textarea/style.css';
const host = document.querySelector<HTMLElement>('#feedback');if (host) { const feedback = Textarea.create(host, { label: 'Feedback', name: 'feedback', required: true, maxLength: 1000, showCounter: true, resize: 'auto', maxRows: 10 }); host.addEventListener('aui-change', () => { if (!feedback.validity.valid) feedback.reportValidity(); });}More usage
Section titled “More usage”import { Textarea } from '@absoluteui/components/textarea';
const host = document.createElement('div');document.body.append(host);Textarea.create(host, { label: 'Message', rows: 2, resize: 'auto', maxRows: 8, maxLength: 500, showCounter: true });Anatomy
Section titled “Anatomy”<div class="aui-field aui-textarea" data-aui-control> (consumer host) <label class="aui-field__label" for=textarea>Label<span class="aui-field__required" aria-hidden="true">*</span></label> <textarea class="aui-textarea__input" rows> <div class="aui-field__description"> (optional) <div class="aui-field__counter"> (showCounter) <div class="aui-field__error aui-validation-message"> (when shown)</div>API reference
Section titled “API reference”Factory
Section titled “Factory”Textarea.create(host: HTMLElement, options: TextareaOptions): TextareaGlobal configuration key: textarea (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Visible label and accessible name. Required. | |
hideLabel |
boolean |
false |
Visually hide the label; it remains the accessible name. |
value |
string |
"" |
Initial value; also the value restored by reset(). |
name |
string |
Form field name. | |
placeholder |
string |
Supplementary hint; never replaces the label. | |
description |
string |
Help text referenced by aria-describedby. | |
required |
boolean |
false |
Empty value is invalid; shows the required indicator. |
disabled |
boolean |
false |
Disables the textarea. |
readOnly |
boolean |
false |
Value is focusable and submitted but not editable. |
minLength |
number |
Minimum length in code points. | |
maxLength |
number |
Maximum length in code points (validated, not truncated). | |
showCounter |
boolean |
false |
Show remaining/over characters; requires maxLength. |
rows |
number |
3 |
Visible text rows, integer 1..100; the minimum height for resize ‘auto’. |
resize |
'none' | 'vertical' | 'auto' |
"vertical" |
Native vertical resize handle, fixed height, or grow with content. |
maxRows |
number |
Upper bound in rows for resize ‘auto’ (integer >= rows); content scrolls beyond it. | |
autocomplete |
string |
Native autocomplete token. | |
spellcheck |
boolean |
true |
Native spellcheck. |
validate |
(value: string) => string | null |
Consumer validation; return a message to mark the value invalid. | |
icons |
Partial<{ error: IconRef }> |
Icon slot overrides. | |
validationTiming |
'blur' | 'input' | 'submit' |
"blur" |
When validation messages first appear; afterwards they update live. Globally configurable. |
locale |
string |
"en-US" |
Message and number-formatting locale. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
Consumer host; its children are owned by the component. |
textarea |
HTMLTextAreaElement |
The native textarea. |
value |
string |
Current value. |
name |
string | null |
Form field name. |
label |
string |
Label text. |
disabled |
boolean |
Disabled state. |
validity |
FieldValidity |
{ valid, error, message }; computed on every change. |
dirty |
boolean |
Value differs from the initial value. |
touched |
boolean |
Focus has left the control at least once. |
options |
Readonly<TextareaOptions> |
Current instance options. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
setValue(value: string): void |
Programmatic value (no events); clears an external custom error. |
update(options: Partial<TextareaOptions>): void |
Merge and apply options. |
reportValidity(): boolean |
Show messages now and return validity. |
setCustomError(message: string | null): void |
External error (server, cross-field rule); cleared when the user edits. |
getFormValue(): string |
Value for form serialization. |
focus(): void |
Focus the textarea. |
reset(): void |
Restore the initial value and clear dirty/touched/submitted state. |
destroy(): void |
Remove rendering, listeners, registration, and subscriptions. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-input |
{ value: string; validity: FieldValidity } |
Yes | No | User edited the value. |
aui-change |
{ value: string; validity: FieldValidity } |
Yes | No | User committed the value (native change, on blur). |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-field aui-textarea |
Host. |
aui-textarea--invalid | --disabled |
State modifiers on the host. |
aui-textarea--resize-none | --auto | --auto-native |
Sizing modifiers on the host (–auto-native: field-sizing: content is used). |
aui-field__label | __required | __description | __counter | __error |
Shared field chrome. |
aui-textarea__input |
Native textarea; also the control boundary. |
Icon slots
Section titled “Icon slots”| Slot | Default icon |
|---|---|
error |
alert-circle |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-disabled-bg | --aui-color-error-fg | --aui-color-focus-ring | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-disabled | --aui-color-text-muted | --aui-control-height-md | --aui-control-padding-x | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-weight-medium | --aui-icon-size-sm | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-space-1 | --aui-space-2
TypeScript definitions
Section titled “TypeScript definitions”type TextareaResize = 'none' | 'vertical' | 'auto';type ValidationTiming = 'blur' | 'input' | 'submit';interface FieldValidity { readonly valid: boolean; readonly error: ValidationErrorCode | null; readonly message: string }interface TextareaValueDetail { value: string; validity: FieldValidity }Accessibility
Section titled “Accessibility”Pattern: Native <textarea> with a <label for> association (HTML).
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| Tab / Shift+Tab | Any | Moves focus to and from the textarea. |
| Enter | Textarea focused | Inserts a line break (native). |
| All editing keys | Textarea focused | Native text editing. |
| Element | Role |
|---|---|
| textarea | textbox (native, multi-line) |
| icons | none (aria-hidden=true) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-describedby |
textarea | Help text, counter, and visible error message ids |
aria-invalid |
textarea | “true” only while an error message is shown |
The textarea shows the focus indicator (focus-ring-width outline in color-focus-ring, border color, and a 1px ring).
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The required asterisk is aria-hidden; required state is conveyed by the native required attribute.
- Errors appear after the first blur by default so users are not interrupted while typing.
- The character count is announced through a polite live region only near or over the limit, 750 ms after typing stops.
- Auto-grow keeps the whole value visible up to maxRows, which helps users review what they wrote.
- Screen-reader announcement of the counter has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Behavior
Section titled “Behavior”States
Section titled “States”default, focus-visible, filled, disabled, read-only, required, invalid (message shown), over limit, auto-grow.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| pristine | user types | dirty; message shown only with validationTiming: 'input' |
| any | focus leaves the host | touched; messages shown (blur timing), after the pointer is released if focus left by a click |
| any | reportValidity() (for example on form submit) |
submitted; messages shown for every timing |
| invalid (custom error) | user edits | custom error cleared, validity recomputed |
| auto-grow | user types or the value is set | height follows content between rows and maxRows |
| any | reset() |
initial value; pristine, untouched |
Accessibility notes
Section titled “Accessibility notes”- The required asterisk is
aria-hidden; the nativerequiredattribute conveys the state. - Errors appear after the first blur by default, then update live.
- The counter is announced through a polite live region only near or over the limit, 750 ms after typing stops.
- Auto-grow keeps the whole value visible up to
maxRows, so users can review what they wrote without scrolling. - Manual screen-reader verification is pending (see Known limitations).
Responsive behavior
Section titled “Responsive behavior”Full width of its container. Height follows rows. With resize: 'vertical' users can drag the height; with 'auto' the control grows between rows and maxRows and then scrolls. Density tokens change font size and padding; the row bounds use lh units so they follow them.
Right-to-left
Section titled “Right-to-left”Logical properties throughout. The native resize handle follows the writing direction.
Theming
Section titled “Theming”Colors come from role tokens only (light, dark, and high-contrast themes). In forced-colors mode, focus draws a Highlight outline.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { textarea: { validationTiming: 'input' } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
icons.error (default alert-circle).
Security
Section titled “Security”All text uses textContent. Validation messages never include the entered value. Auto-grow sizing is written through the CSSOM (style.setProperty), never through a style attribute. CSP-safe (no inline styles or HTML sinks).
Data handling
Section titled “Data handling”No persistence, network access, or telemetry. The native textarea carries the value for form submission when name is set.
Performance
Section titled “Performance”Three listeners per instance (input, change, focusout) and one configuration subscription. With native field-sizing there is no layout work in script; the fallback performs one layout read (scrollHeight) per input event. Budget: under 1 ms average per Textarea.create across 1,000 instances.
Supported data scale
Section titled “Supported data scale”1,000 textareas per page is the performance target. Values of any length; counters count code points.
Edge cases
Section titled “Edge cases”- Pasting text longer than
maxLengthkeeps the text and shows the over-limit count and message. - A line break counts as one character.
maxRowswithoutresize: 'auto', or smaller thanrows, throwsTEXTAREA_OPTIONS.- Auto-grow on a textarea that is not connected (or is hidden) is measured on the next input event.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
TEXTAREA_OPTIONS |
configuration | Missing label; invalid lengths, rows, resize, or maxRows; or showCounter without maxLength. |
Validation (validity.error) |
validation | value-missing, too-short, too-long, custom. |
A failed construction leaves no rendering, listeners, or subscriptions behind.
Known limitations
Section titled “Known limitations”maxLengthis validated, not truncated.- Grapheme clusters such as flag emoji count as more than one character.
- Without native
field-sizingsupport, a container resize that rewraps text is applied on the next edit. - Only vertical resizing is offered.
- Screen-reader behavior of the counter has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Unsupported scenarios
Section titled “Unsupported scenarios”- HTML in the label, help text, or messages.
- Rich text, mentions, or syntax highlighting.
- Native
maxlengthtruncation.