Skip to main content
Graphite UI

Text area

A multi-line field for an answer that needs a few sentences: feedback, a description, a note. For anything that fits on one line, use Text input, which is quicker to scan in a form.

Contract 3.0.0Kit · 4 sets · 20 variantsOpen in Figma

Live preview

Rendered by the component itself from the same generated tokens as the rest of the site.

Steps to reproduce help us most.

Installation

Install it with the shadcn CLI, along with everything it uses. New project? Set it up first, as Quick start shows.

npx shadcn@latest add https://www.graphite-ui.com/r/text-area.json
import { TextArea } from '@/components/ui/text-area'
import type { FieldSize, FieldState } from '@/components/ui/text-input'

Anatomy

A label, the value and supporting text, inherited from Text input. Text area has no leading or trailing slot: the code offers neither.

Supporting text
  1. ValueRequiredNone beyond the value itself. (from Text input)
  2. Leading iconOptional (from Text input)
  3. Trailing iconOptional (from Text input)
  4. LabelRequiredBuilt into the control, not supplied by a wrapper. The kit ships no standalone label component and no field wrapper; it makes label text a property of the control itself. (from Text input)
  5. Supporting textOptionalHelp text, or error text. The kit calls this Helper / Error text and builds it into the control the same way. (from Text input)

Variants

One height, as the kit draws it: 142 at least, the value in Body/3. Layout gives the kit’s two sets, Default and Fluid. Resize decides whether the reader can drag it taller; it can never be dragged wider. The count shows whenever maxLength is set.

Layout: Fixed (default)
Layout: Fluid
Fluid with an error
Error message
Resize: None

States

Focus is forced here with the declarations :focus-visible carries; it is never a prop. There is no Hover row because the field has no hover style. Error and Warning come from errorText and warningText and draw the kit’s status icon in the top-right corner; Invalid is the error ring without a message. Read-only is the native attribute.

Enabled
Helper text
Focus
Helper text
Disabled
Helper text
Error
Error message
Warning
Warning message
Read-only
Helper text
Invalid
Helper text

API reference

Generated from the contract, versioned with it, and checked by drift-check. This table cannot describe props the component does not have.

Text area props
PropTypeDefaultNotes
label——Required, as on Text input.
state'default' | 'focus' | 'disabled' | 'error' | 'invalid' | 'warning'—
layout'fixed' | 'fluid'—The kit's Text area - Default and Text area - Fluid. The kit draws no Inline Text area, so it has none.
helpText——Suppressed while errorText or warningText is present.
errorText——Resolves the error state, as on Text input.
warningText——Resolves the warning state, outranked by an error.
showCount——The kit's Show count, on by default in the kit, so on by default here; the count shows whenever maxLength is set.
resize'vertical' | 'none'—Never horizontal, which breaks layout containers.

Design tokens

Every swatch is live. Change the source color in the header and this table repaints, because it reads the same roles the component does.

  • elevationThe field's fill, elevation-01, the kit's Field/field-01. Select's hover rung, elevation-02, comes through the same inheritance. (from Text input)
  • outlineThe bottom rule at rest, through its strong step (outline-strong), which is also the placeholder colour; read-only quietens it to the subtle step. A rule on the bottom only, never a box. (from Text input)
  • primaryThe focus ring, through the family's focus step: 2px inside all four sides. (from Text input)
  • dangerThe error ring, 2px inside, the error text, and the error status icon's triangle. (from Text input)
  • warningThe warning status icon's triangle. (from Text input)
  • on-warningThe "!" on the warning status icon. (from Text input)
  • backgroundThe "!" on the error status icon, which the kit cuts out of the triangle to show what is behind it. (from Text input)
  • on-surfaceValue text. (from Text input)
  • textThe value at Body/3 at every size; size changes the height, never the type. (from Text input)
  • spacingField padding and height steps. (from Text input)
  • radiusField corner. Inherited by Select and Text area. (from Text input)
  • on-surface-variantLabel and helper text, which the kit binds to onSurfaceVariant rather than onSurface. (from Text input)

Usage

The contract's prohibitions, written as the choices you will actually face.

Do

  • Set rows when the answer you expect is longer than the kit’s 142px field. It only ever grows taller.
  • Leave resize on vertical unless the layout below the field cannot move.
  • Say in the helper text what a good answer includes, like steps to reproduce, rather than repeating the label.
  • Pass errorText to show an error, so the message and the red ring arrive together.

Don’t

  • Allow horizontal or both-way resize. The prop does not offer it, because a wider field breaks its container.
  • Let the field grow without limit. It stops at a fixed height and scrolls, and a style override that removes that limit breaks the contract.
  • Use the placeholder as the label. It disappears as soon as someone types.
  • Use a text area for a one-line answer like a name. The height suggests more is expected.

Accessibility

What the component does for you, and what it leaves to you.

Labels
The label is a real label element tied to the textarea by id, generated when you do not pass one.
Supporting text
Help, warning or error text is linked through aria-describedby. Error text carries role="alert", so it is announced when it appears. The status icon and the count are decorative.
Validity
Error and Invalid both set aria-invalid. The required asterisk is hidden; the native required attribute is what gets read.
Focus
The kit’s 2px ring inside the field on :focus-visible, drawn by the browser’s real focus rather than a prop.
Overflow
Past its maximum height the field scrolls, so long text stays reachable by keyboard and by scroll without moving the page.

Figma parity

The kit's Text area page ships 20 variants across 4 sets. The code exposes 8 props. This table is where those two facts are reconciled instead of quietly diverging.

Kit axes and how they map to code
Kit axisValuesCodeHow it maps
StateEnabled · Focus · Error · Warning · Disabled · Read-only · SkeletonstateError and Warning follow errorText and warningText and draw the kit’s status icon. Disabled maps to the prop; Read-only is the native readOnly. Focus is :focus-visible, per governance rule 7. Skeleton has no counterpart.
Show countBoolean, on by defaultshowCountOn by default, as the kit has it, and shown whenever maxLength is set.
Text filledFalse · True—Runtime state: whether the field has a value.
Fluid (set)Enabled → Read-onlylayout="fluid"The kit’s second public set: the label row inside the box, and the message inside too, under a divider.
Size——None. The kit draws one height, 142 at least, with the value in Body/3; the size prop went in 3.0.0.
Resize handlePrivate build blockresizeThe kit draws the handle; the code turns it on or off. Vertical is the only direction either one offers.