Skip to content

Textarea

A multi-line text field that the user can resize. Three fills and every state: hover, focus, filled, read-only, disabled and error.

Version 0.4.1 ·

Textarea states

Installation

bunx --bun shadcn@latest add @dga/textarea

Installs Field too.

Usage

page.tsx
tsx
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Textarea } from "@/components/ui/textarea";

export function DetailsField() {
  return (
    <Field name="details">
      <FieldLabel required>Request details</FieldLabel>
      <Textarea required rows={4} />
      <FieldDescription>Give the plot number and the street name.</FieldDescription>
    </Field>
  );
}

Use Textarea for answers that need more than a line: descriptions, comments, reasons. Set rows for the starting height. Tell people the limit in the helper text, and do not cut text off silently.

Anatomy

  • Textarea (<textarea>): the border, fill, text and resize handle in one element.
  • The scroll bar is the browser's own; it appears when the text is taller than the box.

Examples

States

Default, filled, read-only, disabled and error, plus the darker fill without resizing.

States

Resizing

resize="vertical" (default) shows a handle at the end corner. Use resize="none" when the layout needs a fixed height. The field never resizes sideways.

page.tsx
tsx
<Textarea resize="none" rows={6} />

RTL

Text starts on the right and the resize handle sits in the bottom-left corner. Everything follows the page direction.

LTR (English)
RTL (Arabic)

Accessibility

KeyAction
TabMoves focus to the field.
EnterStarts a new line.
  • A native <textarea> linked to its Field label, helper text and error.
  • Same states as Input: the underline grows from the centre when pressed (half) and focused (full), and there is no outline. A wrapper <div> carries the border and underline because a <textarea> cannot draw one.
  • The resize handle can be dragged with a pointer. Keyboard users get the same space by typing; give rows enough height for the expected answer.
  • If you show a character limit, put it in the helper text and use maxLength so it is enforced.

API Reference

Textarea

A multi-line text field that grows in height (it is resizable by default). Label it with a Field. It is linked to the Field's label, helper text and error like any other control.

Textarea props
PropTypeDefault
"default" | "lighter" | "darker"

Fill: `default` (white), `lighter` or `darker`. All three keep a visible border.

"default"
"vertical" | "none"

`vertical` lets the user drag the corner to change the height. `none` fixes it.

"vertical"
string

Class names for the box around the field (border, fill and underline).

No default
string

Class names for the native `<textarea>`.

No default
number

Visible lines of text, which sets the starting height.

4
string

Initial value when uncontrolled.

No default
boolean

Disables the field.

No default
string

Hint shown while empty.

No default
boolean

The text can be read and copied but not changed.

No default
boolean

The form cannot be submitted while the field is empty.

No default
string

Controlled value.

No default

Also accepts every prop of the Base UI Field (opens in a new tab).

Deviations from DGA

  • Figma has one fixed-height variant. This one grows with rows and can be resized.
  • Lighter and darker have no border at rest, as on Input, including the known gap.
ChangeReason
Textarea: sizeA multi-line field has no single right height. Figma's Resize and Scroll Bar props map to resize and the native scroll bar.

View all 1 deviations for this component

Contrast

276 pairs checked · all pass WCAG 2.1 AAShow 46 states
Variant / stateLightDark
filled text18.09:1 AAA15.87:1 AAA
hovered text18.09:1 AAA15.87:1 AAA
focused text10.17:1 AAA12.04:1 AAA
pressed text9.24:1 AAA9.64:1 AAA
pressed placeholder6.69:1 AA5.06:1 AA
pressed prefix and suffix text9.24:1 AAA9.64:1 AAA
underline, focused and pressed18.74:1 3:116.80:1 3:1
placeholder4.77:1 AA6.32:1 AA
prefix and suffix text10.17:1 AAA12.04:1 AAA
icon4.77:1 3:19.38:1 3:1
border, default4.57:1 3:13.80:1 3:1
border, hovered9.73:1 3:112.04:1 3:1
border, focused and pressed17.93:1 3:116.80:1 3:1
underline, error4.62:1 3:14.65:1 3:1
border, error4.62:1 3:14.65:1 3:1
filled text (lighter)17.64:1 AAA14.42:1 AAA
hovered text (lighter)17.64:1 AAA14.42:1 AAA
focused text (lighter)10.17:1 AAA12.04:1 AAA
pressed text (lighter)9.24:1 AAA9.64:1 AAA
pressed placeholder (lighter)6.69:1 AA5.06:1 AA
pressed prefix and suffix text (lighter)9.24:1 AAA9.64:1 AAA
underline, focused and pressed (lighter)18.28:1 3:115.27:1 3:1
placeholder (lighter)4.65:1 AA5.75:1 AA
prefix and suffix text (lighter)9.92:1 AAA10.95:1 AAA
icon (lighter)4.65:1 3:18.52:1 3:1
border, hovered (lighter)9.73:1 3:112.04:1 3:1
border, focused and pressed (lighter)17.93:1 3:116.80:1 3:1
underline, error (lighter)4.62:1 3:14.65:1 3:1
border, error (lighter)4.62:1 3:14.65:1 3:1
filled text (darker)16.44:1 AAA17.04:1 AAA
hovered text (darker)16.44:1 AAA17.04:1 AAA
focused text (darker)10.17:1 AAA12.04:1 AAA
pressed text (darker)9.24:1 AAA9.64:1 AAA
pressed placeholder (darker)6.69:1 AA5.06:1 AA
pressed prefix and suffix text (darker)9.24:1 AAA9.64:1 AAA
underline, focused and pressed (darker)17.03:1 3:118.03:1 3:1
placeholder (darker)6.69:1 AA6.79:1 AA
prefix and suffix text (darker)9.24:1 AAA12.93:1 AAA
icon (darker)4.34:1 3:110.07:1 3:1
border, hovered (darker)9.73:1 3:112.04:1 3:1
border, focused and pressed (darker)17.93:1 3:116.80:1 3:1
underline, error (darker)4.62:1 3:14.65:1 3:1
border, error (darker)4.62:1 3:14.65:1 3:1
border, hover and focus (lighter and darker)4.57:1 3:13.80:1 3:1
read-only text18.09:1 AAA15.87:1 AAA
border, resize handle4.57:1 3:13.80:1 3:1

Text needs 4.5:1, icons and focus rings 3:1. Disabled states are exempt. Full contrast report