Textarea
Collect multi-line text in a field that grows with its content, then scrolls.
import { Textarea } from '@youj/react'
Installation & usage
npm i @youj/reactFor an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.
Use Textarea for comments, feedback, descriptions and other multi-line text. Use an Input for a single line. Wrap the textarea in an Input Group when you need a toolbar or send button inside its frame.
import { Field, FieldDescription, FieldLabel, Textarea } from '@youj/react'
export function ProjectDescription() {
return (
<Field>
<FieldLabel>Description</FieldLabel>
<Textarea name="description" placeholder="What does this project do?" />
<FieldDescription>Shown on the project page and in search.</FieldDescription>
</Field>
)
}It renders a real <textarea> through Base UI's field control, so inside a Field it's labeled, described, validated and made required exactly like an Input. rows, cols and wrap go to the element.
Description
A feedback form whose Textarea counts down to a 280-character limit and turns the count into an error once it is exceeded.
Count in the description line and turn the count into an error once it's exceeded, as the demo does. Announce only the last stretch: a live region that speaks on every keystroke drowns out what's being typed.
<span aria-live="polite" className="sr-only">
{left >= 0 && left <= 20 ? `${left} characters left` : ''}
</span>A textarea growing with its content, and its states.
It starts three lines tall and grows with its content up to 16rem, then scrolls. Growth is CSS field-sizing: content. In browsers without it, the box keeps its starting height and you can drag it taller. Border, hover, focus and invalid match Input.
A textarea that keeps a fixed height.
Pasted text, like a .env file or a certificate, is easier to check in a box that stays put. Add the field-sizing-fixed class and set rows to hold the height, and set wrap="off" so long lines scroll sideways instead of wrapping.
Code
textarea-demo.tsx, the Demo story. The component itself comes from the package.
Reference
Propsvalue, defaultValue (2)
Props
| Prop | Type | |
|---|---|---|
value | string | – |
defaultValue | string | – |
value and defaultValue take strings. Every other native textarea attribute passes through, including onChange, rows and maxLength.
MotionHover and focus · reduced motion
Motion
| Moment | Tokens | ||
|---|---|---|---|
| Hover and focusborder color, fill and the focus halo | duration.fastease.standard140ms · cubic-bezier(0.2, 0, 0, 1) | 140mscubic-bezier(0.2, 0, 0, 1) |
Reduced motion
There is nothing to reduce: growing with its content is instant, and colors change on the fast token.
Reduced motion
The textarea doesn't animate. It grows line by line as you type, with or without reduced motion.
AccessibilityKeyboard, ARIA, focus
Accessibility
- It's a native
<textarea>:Enteradds a new line andTabmoves focus on. - Label it through a Field, or with
aria-labelwhen the context names it. - If you use
maxLength, say so in the description. The browser stops accepting input silently, which reads as a broken keyboard. - Text is 16px on touch screens, so iOS doesn't zoom the page on focus.