Skip to main contentSkip to docs navigation

Multi-line text input component with custom styles, read-only and plain-text display, and native browser resizing.

Overview

Textarea is a styled, accessible replacement for a native multi-line <textarea>. It's built on React Aria's useTextField hook, which wires aria-describedby / aria-labelledby to the ids generated for an associated label, help text, and validation feedback — the same wiring Text Input uses.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return <Textarea placeholder="Example textarea" aria-label="Example textarea" />
}

As a form field

Pass label / help / invalid / invalidFeedback / valid / validFeedback directly to Textarea to render it together with an associated FormLabel, FormHelp, and FormFeedback, already wired up — see Form Field instead when a control needs to be grouped with companion content under one label.

A short description, shown on your public profile
JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return <Textarea label="Bio" help="A short description, shown on your public profile" />
}

Sizing

Set the size prop to "lg" or "sm" to change the control's padding, typography, and border radius.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Textarea size="lg" placeholder="Large textarea" aria-label="Large textarea example" />
      <Textarea placeholder="Default textarea" aria-label="Default textarea example" />
      <Textarea size="sm" placeholder="Small textarea" aria-label="Small textarea example" />
    </>
  )
}

Rows

Set the native rows attribute to control how many lines show before the control scrolls — independent of size, which changes padding and typography rather than height.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Textarea rows={1} placeholder="1 row" aria-label="Textarea with one row" />
      <Textarea rows={4} placeholder="4 rows" aria-label="Textarea with four rows" />
    </>
  )
}

Regardless of rows, the control never renders shorter than a single-line TextInput — the underlying .form-input class applies the same minimum height floor to both.

Disabled

Add the disabled boolean attribute to give the control a muted color. Browsers also remove disabled controls from the tab order and from form submission automatically.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Textarea
        placeholder="Disabled textarea placeholder"
        aria-label="Disabled textarea placeholder example"
        disabled
      />
      <Textarea
        defaultValue="Disabled textarea value"
        aria-label="Disabled textarea value example"
        disabled
      />
    </>
  )
}

Readonly

Add the readOnly boolean attribute to prevent the value from being edited. Unlike disabled, a read-only control stays focusable and is still included in form submission — only typing into it is blocked — and it keeps the same appearance as an editable control.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return (
    <>
      <Textarea value="Readonly textarea" aria-label="readonly textarea example" readOnly />
      <Textarea
        defaultValue="Readonly disabled textarea"
        aria-label="readonly disabled textarea example"
        readOnly
        disabled
      />
    </>
  )
}

Plain text

Pair the plainText prop with readOnly to render the value as plain text instead of an editable-looking field — useful for read-only values that should still line up with the editable fields around them.

JSX
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  return (
    <Textarea
      defaultValue="Shipping address confirmed by the customer."
      readOnly
      plainText
      aria-label="Shipping address"
    />
  )
}

Controlled value

Pass value and onChange to control the value from external state. onChange receives the new string value directly rather than a change event, so it can be passed straight to a state setter. Omit them (optionally passing defaultValue instead) to let the component manage its own value.

0 characters
JSX
import { useState } from 'react'
import { Textarea } from '@chassis-ui/react'

export const Example = () => {
  const [value, setValue] = useState('')
  return (
    <Textarea
      label="Comment"
      help={`${value.length} characters`}
      value={value}
      onChange={setValue}
      placeholder="Leave a comment"
      aria-label="comment example"
    />
  )
}

API

Textarea

PropTypeDefault
className?string—
A string of all className you want applied to the component.
defaultValue?string—
The value of the textarea, uncontrolled.
disabled?boolean—
Toggle the disabled state for the component.
help?ReactNode—
A description for the field, rendered below the textarea.
invalid?boolean—
Set component validation state to invalid. Left unset, the component shows as invalid by itself from a submit it held back (an empty required one, say) until it no longer would, or its form is reset. Set it, to false too, and it alone decides.
invalidFeedback?ReactNode—
An error message for the field, rendered below the textarea when invalid is set, and after a submit the field held back, until it no longer would.
label?ReactNode—
The field's caption, rendered as a FormLabel associated with this textarea.
onChange?((value: string) => void)—
Handler that is called when the value changes.
plainText?boolean—
Render the component styled as plain text. Removes the default form field styling and preserve the correct margin and padding. Recommend to use only along side readonly.
readOnly?boolean—
Toggle the readonly state for the component.
rows?number—
The number of visible text lines for the control.
size?"sm" | "lg"—
Size the component sm or lg.
valid?boolean—
Set component validation state to valid.
validFeedback?ReactNode—
A success message for the field, rendered below the textarea when valid is set.
value?string—
The value of the textarea, controlled.