Use an Input when users only need to enter a short, single-line value. Use a Textarea when the expected content spans multiple lines.
When to use
Use a textarea when
- Users need to enter multiple lines of text such as a comment, review, or description
- The expected input length varies and may be long
- Free-form text entry is required without a predefined set of values
- Context makes the textarea purpose clear through a visible label
Do not use a textarea when
- The expected input is a short single-line value — use an Input instead
- Users must choose from a fixed set of options — use a Select or Radio
- The field value is meant to be read-only in the final UI — use plain text
- Rich formatting or markdown editing is required — consider a dedicated editor
Anatomy
| Part | Element | Description |
|---|---|---|
| 1 | Optional label | Secondary descriptive text displayed alongside the main label |
| 2 | Text | The value or placeholder text inside the control |
| 3 | Label icon | Optional icon displayed next to the label |
| 4 | Label | The primary field label rendered via the label slot |
| 5 | Leading icon | Optional icon displayed at the start of the input container |
| 6 | Container | The outer border and background wrapper of the textarea |
| 7 | Validation icon | Icon shown when validation-status is set (error, warning, success) |
| 8 | Helper text | Optional guidance or error text rendered via the helper-text slot |
| 9 | Character counter | Shown automatically when maxlength is set |
| 10 | Trailing icon | Optional icon displayed at the end of the input container |
Design guidelines
States
A textarea supports five interactive states: default, focused, disabled, read-only, and validation (error, warning, success). The focused state shows a colored ring. The disabled state dims the control and blocks all interaction. The read-only state displays the value but prevents editing.Always pair a textarea with a visible
label slot. An unlabeled textarea has no accessible name and is inaccessible by default.Resize behavior
By default, users can drag the bottom-right corner to resize the textarea vertically. Setdisable-resize to prevent resizing — useful when you want to maintain a consistent layout height. Alternatively, set auto-grow to let the textarea expand automatically as the user types, eliminating the need for manual resizing.
Character counter
Whenmaxlength is set to a value greater than zero, a character counter appears in the helper area below the textarea. It shows the current character count against the limit and helps users stay within bounds. The counter truncates input automatically when the limit is reached.
Validation
Setvalidation-status to error, warning, or success to communicate the state of the field. Pair each state with a descriptive helper-text message so users know what went wrong and how to fix it. Use error for critical blocking issues, warning for non-blocking concerns, and success to confirm valid input.
Usage
Default
Use the default textarea when you need a standard multi-line text input. Provide alabel slot for the field name and a helper-text slot for any additional guidance.
Initial value
Pre-populate your textarea with an initialvalue attribute to streamline user interactions and provide a helpful starting point.
Options
Disabled
Setdisabled when the field is not currently available for interaction. Use it to present non-editable content in a form context. Always communicate why the field is disabled through surrounding text or a tooltip.
Disable resize
Adddisable-resize to prevent users from resizing the textarea. This is useful when you need a stable layout with a consistent textarea height.
Max length
Setmaxlength to limit the number of characters users can enter. A character counter appears automatically below the textarea to show progress toward the limit. Input is truncated once the limit is reached.
Read only
Setreadonly to display the value without allowing edits. Unlike disabled, a read-only textarea is still focusable and its value is submitted with the form.
Validation
Setvalidation-status to error, warning, or success to communicate the state of the field. Always pair a validation status with a descriptive helper-text message so users understand the issue and how to resolve it.
Best practices
DoAlways provide a visible label via the
label slot. An unlabeled textarea has no accessible name and relies entirely on context, which screen readers cannot infer.Don’tUse placeholder text as a substitute for a label. Placeholder text disappears as soon as the user starts typing, leaving the field without any visible description.
DoWrite user-centric validation messages that explain what went wrong and how to fix it, not only that the input was invalid.
Don’tShow vague error messages like “Invalid input”. Users need actionable guidance to correct their input, not a generic error label.
DoUse
maxlength for inputs where length matters — tweet-like comments, SMS text, or short descriptions. The character counter gives users clear progress feedback.Don’tSet
maxlength on open-ended fields like detailed feedback forms or long descriptions where an arbitrary limit would frustrate users.DoUse a textarea only when the expected input is long or variable in length. This sets the right expectation for users about how much text they should provide.
Don’tUse a textarea when a short single-line response is expected. An oversized input creates confusion and wastes space — use an Input component instead.
Accessibility
bq-textarea renders a native <textarea> element inside its shadow DOM. The label slot renders as a <label> element that is linked to the <textarea> via an id/for relationship automatically, giving assistive technologies a correct accessible name.
Keyboard interaction
| Key | Action |
|---|---|
Tab | Moves focus to the textarea |
Shift + Tab | Moves focus away from the textarea |
| Arrow keys | Navigate the cursor through the text |
Enter | Inserts a new line in the text |
Developer responsibilities
- Always provide content in the
labelslot. The label is the primary source of the accessible name for the textarea. Do not rely onplaceholder— it disappears once the user starts typing. - When using
validation-status, pair it with ahelper-textmessage that explains the issue. Screen readers announce the helper text to users so they know what to correct. - When the textarea is
disabled, it is removed from the tab order and excluded from form submission. Communicate the reason for disabling through surrounding text. - A
readonlytextarea remains focusable and its value is included in form submissions. Use it when you want users to see but not edit a value. - The
bqChangeevent fires when the user changes the value and then blurs the field. ThebqInputevent fires on every keystroke. Usedebounce-timeto throttlebqInputfor performance-sensitive scenarios such as live search.
API reference
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
autocapitalize | autocapitalize | Controls how the textarea value is capitalized | 'off' | 'on' | 'sentences' | 'words' | 'characters' | 'off' |
autocomplete | autocomplete | Specifies whether autocomplete is enabled | string | 'off' |
autofocus | autofocus | If true, the textarea is focused on render | boolean | false |
autoGrow | auto-grow | If true, the textarea grows and shrinks to fit its contents | boolean | false |
debounceTime | debounce-time | Milliseconds to wait before emitting bqInput after a value change | number | 0 |
disabled | disabled | If true, the user cannot interact with the textarea | boolean | false |
disableResize | disable-resize | If true, the user cannot resize the textarea | boolean | false |
form | form | The ID of the form the textarea belongs to | string | — |
formValidationMessage | form-validation-message | Custom native form validation message | string | — |
maxlength | maxlength | Maximum number of characters (0 means no limit); enables the character counter | number | — |
name | name | Name of the form control; submitted with the form | string | required |
placeholder | placeholder | Placeholder text shown when the textarea has no value | string | required |
readonly | readonly | If true, the value cannot be modified but remains focusable and submitted | boolean | false |
required | required | If true, the textarea must have a value before the form can be submitted | boolean | false |
rows | rows | Number of visible text lines | number | 5 |
spellcheck | spellcheck | If true, the content may be checked for spelling errors | boolean | false |
validationStatus | validation-status | Validation state of the textarea | 'none' | 'error' | 'warning' | 'success' | 'none' |
value | value | The current value of the textarea | string | — |
wrap | wrap | How text is wrapped when the form is submitted | 'soft' | 'hard' | 'off' | 'soft' |
Events
| Event | Description | Type |
|---|---|---|
bqBlur | Emitted when the textarea loses focus | CustomEvent<HTMLBqTextareaElement> |
bqChange | Emitted when the value changes and the textarea loses focus | CustomEvent<{ value: string; el: HTMLBqTextareaElement }> |
bqClear | Emitted when the textarea value is cleared | CustomEvent<HTMLBqTextareaElement> |
bqFocus | Emitted when the textarea receives focus | CustomEvent<HTMLBqTextareaElement> |
bqInput | Emitted on every value change (keystroke or paste) | CustomEvent<{ value: string; el: HTMLBqTextareaElement }> |
Slots
| Slot | Description |
|---|---|
label | The textarea label displayed above the control |
helper-text | Optional helper text or icon shown below the control |
Shadow parts
| Part | Description |
|---|---|
base | The component’s base wrapper |
input | The native <textarea> element |
label | The <label> element |
helper-info | The helper info container below the textarea |
helper-text | The helper text element |
helper-counter | The character counter element |
CSS custom properties
Resources
Interactive playground
Explore textarea variants and states in Storybook
Source code
View the component source on GitHub