BridgeHandbookDraft
For agents
Menu
ExperimentalatomInputs

Textarea

A text field for more than one line: notes, bios, messages.

import { … } from "@brdgapp/ui/components/textarea"

Usage

Textarea is a text field for more than one line: a note, a bio, an intro message. It starts 3 lines tall, grows as people type up to 10 lines, then scrolls inside. Give it a maxLength and it counts the characters under the box. Put it in a Field, like Input. The usual mistake is a fixed little box that hides most of what someone wrote, or a count each screen builds its own way.

When to use

  • Any typed value that can run past one line: notes on a contact, a bio, the message in an intro request, feedback.
  • With maxLength wherever the server has a limit, so people see it coming instead of being cut off.

When not to use

  • For a name, email, link or anything that fits on one line. Use Input instead.
  • For a list of short entries, like target roles. Use TagInput instead.

The look comes from props

A component's appearance comes only from its own options (variant, size, color). className on a package component is for layout (mt-4, shrink-0, w-full), never for font size, color, padding, radius or hover. If the look needs a className, the component or the chosen option is wrong: fix that instead.

Anatomy

223 of 280 characters left

  1. Box. The same box as Input: white --surface-primary, --border-default line, 8px corners, 14px side padding. 3 lines (82px) tall when empty.

  2. Text. 14px --text-primary on a 20px line; 16px on phones, so iPhones don't zoom in when it's tapped. The placeholder is --text-muted.

  3. Count. Only with maxLength. 12px, under the box on the right: “120/500”. Turns red in the last 10% (at most the last 50 characters).

Examples

A note on a contact

Type more than 3 lines and the box grows. The count under it shows how much is left.

500 of 500 characters left

Only you can see notes.

Grows with the text

Already-written text shows in full, up to 10 lines, then the box scrolls.

Near the limit

In the last 10% the count turns red, and screen readers hear how many characters are left.

179 of 280 characters left

16 of 280 characters left

16 characters left

An error

Under the field, with an icon, saying what to write.

Write a line about why you'd like the intro

States

RestHoverFocusDisabled
Empty
Filled
Invalid
StateWhat happens
RestGrey line.
HoverThe line darkens to --border-hover.
FocusBlue line and a soft blue ring.
InvalidRed line (and a soft red ring on focus). The error text sits under it, in the Field.
Near the limitThe count turns red; screen readers hear how many characters are left.
Disabled50% opacity; can't be typed in.

Behavior

  • Grows with the text, a line at a time, from rows (3) to maxRows (10), then scrolls inside. Set maxRows equal to rows for a fixed height.
  • No drag handle in the corner: the box sizes itself.
  • maxLength stops typing at the limit and shows the count.
  • Built on Base UI's field control. Inside a Field, its label, help text and error are linked to it automatically.
  • className is for layout only (max-w-md). Never a height: use rows.

Do and don't

Do

Let it grow, and set maxLength to the server's limit.

Don't

Fix it at 2 lines with a hidden scrollbar, so people can't see what they wrote.

Do

Put it in a Field with a visible label: “Note”.

Don't

Use the placeholder as the label: “Write a note…”.

Content

  • Placeholder: a short example of the kind of thing to write, like “Met at the Saltmarsh dinner. Interested in climate deals.” Never the label.
  • Help text says who sees it: “Only you can see notes.”

Accessibility

  • Always has a name: a FieldLabel (preferred) or aria-label.
  • The count is read with the field, as “380 of 500 characters left”. Near the limit, screen readers are told how many are left; they aren't told the count on every key.
  • The red count uses --danger-text, 5.5:1 in light and 5.8:1 in dark.
KeysAction
EnterStarts a new line. It never sends: the form's button does.
TabMoves to the next field.

API reference

Textarea

The multi-line field. Extends Native textarea props (value, defaultValue, onChange, onBlur, placeholder, disabled, name…).

PropTypeDefaultDescription
rowsnumber3Lines tall when empty.
maxRowsnumber10Lines it grows to before scrolling. Equal to rows for a fixed height.
maxLengthnumber—The character limit. Shows the count under the box.
aria-invalidboolean—Only outside a Field. Inside one, set invalid on the Field.
classNamestring—Layout only: max-w-md.

Lineage

What it's built from and where it's used, read from the code. When you change it, check these too.

Built from
Nothing else in the package
Used by components
None
Used in patterns
Forms and validation
Used in templates
None