Mosmox UI
Current version
GitHubnpmjs.com
Forms & Inputs

Textarea

Multiline text control with character limits and optional auto-growing rows

The Textarea component is a multiline text-entry control for notes, descriptions, comments, and other longer values. It follows the same field conventions as Input—labels, descriptions, errors, variants, disabled state, clear actions, controlled values, and character counters—but intentionally has one visual size instead of size variants.

Installation

import { Textarea } from '@mosmox/ui';

Basic usage

<Textarea label="Notes" placeholder="Write your notes" />

The component renders a native <textarea> and forwards native textarea attributes and events.

Value management

Use defaultValue for an uncontrolled textarea:

<Textarea label="Summary" defaultValue="Initial summary" />

Use value and onChange when the parent owns the value:

const [description, setDescription] = useState('');

<Textarea
  label="Description"
  value={description}
  onChange={(event) => setDescription(event.target.value)}
  placeholder="Describe the project"
/>

The component also forwards native properties such as name, id, required, placeholder, autoComplete, inputMode, form, and tabIndex.

Labels, descriptions, and errors

label creates an associated label. description provides supporting guidance, while error displays validation feedback and activates the error border and focus treatment.

<Textarea
  label="Release notes"
  description="Summarize the important changes."
  error="Release notes are required."
  required
/>

The component connects description and error IDs through aria-describedby and derives aria-invalid from the presence of error unless an explicit value is provided.

Rows and auto-growing behavior

minRows defines the initial number of visible text rows. It is also used as the native rows value. The textarea has one standard visual size; row count controls its vertical space.

<Textarea label="Comment" minRows={4} placeholder="Write a comment" />

Set autoResize to make the textarea grow as the user enters line breaks. maxRows caps the automatic height. Once the maximum is reached, the control scrolls internally instead of growing without limit.

<Textarea
  label="Expandable notes"
  autoResize
  minRows={2}
  maxRows={6}
  placeholder="Press Enter to add another line"
/>

maxRows is normalized so it cannot be smaller than minRows. When autoResize is false, the user can resize the textarea vertically using the native resize affordance.

Manual resize control

Use resize to control whether the user can manually change the textarea dimensions:

<Textarea label="Fixed" resize="none" />
<Textarea label="Vertical only" resize="vertical" />
<Textarea label="Both directions" resize="both" />
  • none disables manual resizing.
  • vertical allows height changes only and is the default.
  • both allows width and height changes.

When autoResize is enabled, automatic sizing takes precedence and manual resizing is disabled.

Character limits

Pass maxLength to enforce a native maximum character count. When present, the component displays current / maximum below the field on the right.

<Textarea
  label="Short description"
  maxLength={160}
  placeholder="Up to 160 characters"
/>

The counter works with both controlled and uncontrolled values, including an initial defaultValue. The browser prevents additional input after the limit is reached.

Variants

variant supports the same two surface treatments as Input:

<Textarea label="Outline" variant="outline" />
<Textarea label="Filled" variant="filled" />
  • outline is the default bordered surface.
  • filled uses the shared control-filled background token and removes the visible border.

Clear action

Set clearable to show a clear button when the textarea has editable content. onClear is called when the button is activated.

const [notes, setNotes] = useState('Draft notes');

<Textarea
  label="Notes"
  value={notes}
  onChange={(event) => setNotes(event.target.value)}
  clearable
  onClear={() => setNotes('')}
/>

The clear button is hidden for empty, disabled, or read-only values. For controlled usage, the parent must clear the value in onClear.

Disabled and read-only values

Use disabled when the textarea is unavailable. Use native readOnly when the value should remain selectable but not editable.

<Textarea label="Read-only notes" value="Approved content" readOnly />
<Textarea label="Unavailable notes" value="Locked content" disabled />

Full width

Use fullWidth to make the field fill its parent container.

<Textarea fullWidth label="Full-width description" minRows={4} />

Accessibility

  • label is associated with the native textarea through htmlFor and id;
  • description and error are referenced through aria-describedby;
  • error sets aria-invalid unless explicitly overridden;
  • required, readOnly, and disabled preserve native textarea semantics;
  • the character counter uses a polite live region;
  • native keyboard, selection, focus, form, and browser validation behavior is preserved.

Use a visible label instead of relying only on placeholder text.

Styling model

The component uses shared theme tokens for colors, typography, radius, and control surfaces. Textarea-specific layout, auto-resize behavior, and state rules remain in Textarea.css. The component does not expose the Input size variants; its height is controlled by minRows, maxRows, and autoResize.

API Reference

Textarea-specific properties

PropertyTypeDefaultDescription
labelstring—Associated field label.
descriptionstring—Supporting text below the label.
errorstring—Validation message and invalid visual state.
variantTextareaVariantoutlineoutline or filled.
minRowsnumber3Initial and minimum visible row count.
maxRowsnumber8Maximum automatic row count. Normalized to at least minRows.
autoResizebooleanfalseGrows with line breaks up to maxRows.
resizeTextareaResizeverticalManual resize mode: none, vertical, or both.
clearablebooleanfalseShows a clear action for editable, non-empty values.
onClear() => void—Called when the clear action is activated.
fullWidthbooleanfalseExpands the field to its container width.
classNamestring—Additional class name for the field wrapper.

Native textarea properties

Textarea accepts TextareaHTMLAttributes<HTMLTextAreaElement> except for native rows and size. Use minRows instead of rows; the component controls the native rows value.

PropertyTypeDefaultDescription
value`stringnumberreadonly string[]`
defaultValue`stringnumberreadonly string[]`
onChangeChangeEventHandler<HTMLTextAreaElement>—Called when the value changes.
maxLengthnumber—Maximum characters and counter limit.
readOnlybooleanfalsePrevents editing while preserving selection and focus.
disabledbooleanfalseDisables interaction.
requiredbooleanfalseEnables native required-field validation.
placeholderstring—Placeholder shown when empty.
namestring—Form submission name.
idstringgeneratedTextarea ID used by the label and messages.
aria-labelstring—Accessible name when no visible label is used.
aria-describedbystringgeneratedAdditional description IDs; component message IDs are appended.
aria-invalid`boolean'true''false'`

All other supported native textarea properties and event handlers are forwarded to the underlying <textarea> element.