|Kit

Textarea

The multi-line sibling of Input — a native textarea in the shared input shell, with bordered or filled box, focus ring, and invalid / disabled states, plus a built-in label, description, and error.

Textarea is the multi-line counterpart to Input. It renders a native <textarea> inside the same shell the whole form family uses — the bordered (or filled) box, the focus-within ring, and the invalid / disabled / readOnly states. Like the rest of the family it carries its own label, description, error, and required — no external wrapper needed — and passing error flips it to the invalid (red) state. Omit them and it still composes cleanly inside a Field.

import { Textarea } from '@42/ui-react/textarea';

<Textarea rows={4} placeholder="How did the defense go?" />

Native <textarea> props (value, onChange, name, rows, maxLength, ref, …) forward straight through; className styles the shell root and classNames overrides individual parts. The control is vertically resizable, and rows sets the initial height.

Playground

Component

Loading preview

Props

Code

<Component  label="Peer feedback"  size="md"  placeholder="How did the defense go?"  rows={3}/>

Variants

Three shells. default is bordered, filled is a soft neutral surface, unstyled strips the chrome but keeps the layout.

Code

<Textarea variant="default" placeholder="Default" /><Textarea variant="filled" placeholder="Filled" /><Textarea variant="unstyled" placeholder="Unstyled" />

Sizes

Five steps — xs through xl. The control font and padding scale to match Input, so a Textarea and an Input at the same size line up.

Code

<Textarea size="xs" placeholder="xs" /><Textarea size="sm" placeholder="sm" /><Textarea size="md" placeholder="md" /><Textarea size="lg" placeholder="lg" /><Textarea size="xl" placeholder="xl" />

Rows

rows sets the initial visible height (default 3). The textarea stays resizable, so a user can drag it taller.

Code

<Textarea rows={2} placeholder="Two rows" /><Textarea rows={6} placeholder="Six rows" />

States

invalid swaps the border and focus ring to red regardless of color (and sets aria-invalid). disabled dims the shell and blocks input; readOnly keeps full contrast and stays focusable but rejects edits.

Code

<Textarea invalid defaultValue="Too short." /><Textarea disabled defaultValue="Locked content" /><Textarea readOnly defaultValue="Read-only content" />

With label, description & error

label, description (helper text), and error are built in via Field — no external wrapper needed. Passing error flips the shell to the invalid (red) state; required adds the semantic flag and a red asterisk on the label.

A short blurb for your profile.
Bio is required

Code

<Textarea label="Bio" description="A short blurb for your profile." placeholder="Tell us about yourself…" /><Textarea label="Bio" required placeholder="Tell us about yourself…" /><Textarea label="Bio" error="Bio is required" placeholder="Tell us about yourself…" />

If you omit these props, Textarea still composes cleanly inside a Field, which propagates disabled / invalid / readOnly / required to the control automatically — exactly like Input.

import { Field } from '@42/ui-react/field';
import { Textarea } from '@42/ui-react/textarea';

<Field label="Peer feedback" description="What went well, what didn't?">
  <Textarea rows={4} placeholder="How did the defense go?" />
</Field>

API

Prop

Type

Textarea forwards every other prop to the underlying <textarea> (value, defaultValue, onChange, name, maxLength, ref, …). className styles the shell root.

Accessibility

  • Pass label / description / error to wire the accessible name and aria-* relationships via the built-in Field. Omit them and it composes inside an outer Field (or your own <label htmlFor>) instead.
  • invalid sets aria-invalid on the textarea so assistive tech announces the error state.
  • The focus ring is focus-within, so it appears whenever the nested textarea is focused.
  • RTL: the shell is a plain flex layout, so padding flips automatically under dir="rtl".

On this page