Textarea
NewA multi-line text field, for notes, messages and descriptions: anything longer than a line. It is the Input's frame, and it can grow with its text and count characters against a limit.
Playground
Change the props, then type a few lines. With autoGrow on, the field grows to eight rows and then scrolls.
<Textarea
aria-label="Order note"
placeholder="Only your team sees notes"
/>With a field
Put it in a Field for a label above and a hint below, as with an Input: the label points at the textarea, the hint becomes its description, and an error marks it invalid. Set rows to the length of answer you expect; three is the default.
Printed on a card in the parcel.
Sizes
sm, md (default) and lg take the Input's 13, 14 and 15px text. Lines run on a fixed rhythm, so one row is exactly as tall as an Input of the same size (30, 36 or 44px). A one-row field that grows sits on a line with its button, and stays lined up with it until the text wraps.
Auto-grow
autoGrow fits the field to its text, from minRows (or rows) up to maxRows, then scrolls. It is measured by a hidden copy of the text set in the same place, so the page never jumps as the field grows, and the resize handle goes. Type a few more lines into this note.
Character count
showCount puts a count in the frame's bottom corner: the characters typed, out of maxLength when there is one. It stays quiet until the last tenth of the limit, then takes the warning wash; the browser stops typing at the limit itself. A value set in code that runs over turns it red.
This description starts 5 short of its 160: delete a few words, or add some.
Shown under the page title in search results.
| Count | Looks | Screen readers |
|---|---|---|
| Up to 90% of the limit | Quiet slate digits | Read with the field: "12 characters left" |
| The last 10% | Digits on the warning wash | Announced politely as they change |
| Over the limit (set in code) | Digits on a red wash | Announced: "3 characters too many" |
States
The Input's states, many lines tall. Hover firms the hairline; focus turns it teal with the soft halo; an error in the Field swaps the teal for red. Read-only and disabled sink into the well: a read-only field can still be selected and copied.
Enter a reason, so the customer knows why
Left at checkout
Turn on Gift wrap to add a message
Errors
Check when the form is sent and clear the error as soon as the person starts fixing it. Press Start return with the field empty.
Long content
Past its most rows, a field that grows scrolls inside its frame, and the frame keeps its edge whole.
In both themes
A count in its warning wash, an error and a disabled field, light and dark side by side.
Enter a reason, so the customer knows why
Turn on Gift wrap to add a message
Enter a reason, so the customer knows why
Turn on Gift wrap to add a message
Guidelines
- Size the field to the answer you expect: two or three rows for a note, more for a description. Let it grow rather than making it huge.
- Show a count only when there is a limit that matters, such as a search description or an SMS. Say what the limit is for in the hint.
- A placeholder gives an example of a good answer; it never replaces the label.
- Long formatted copy (product descriptions, blog posts) belongs in the rich text editor, not here.
Accessibility
- A native textarea: everything the browser and assistive tech know about text fields works, including spellcheck and dictation.
- In a Field, the label names it and the hint or error describes it. An error also sets
aria-invalid. Outside a Field, give it anaria-label. - With a limit, the count is part of its description, so it is read with the field. In the last tenth it is announced politely as it changes, never on every key press before that.
- The visible digits are hidden from screen readers; they hear words instead, from countLabel.
- Clicking anywhere in the frame, the count included, puts the caret in the field.
- Focus shows as a teal edge with a soft halo round the whole frame.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | Text of 13, 14 or 15px; one row is 30, 36 or 44px tall, as an Input. |
rows | number | 3 | Height in rows. With autoGrow, the fewest rows unless minRows is set. |
autoGrow | boolean | false | Grow with the text, then scroll. Removes the resize handle. |
minRows | number | None | With autoGrow: the fewest rows. Defaults to rows, or 3. |
maxRows | number | None | With autoGrow: the most rows before it scrolls. No limit when left out. |
showCount | boolean | false | A character count in the bottom corner, out of maxLength when set. |
maxLength | number | None | The native limit. The count warns in its last tenth. |
countLabel | (length, maxLength) => string | None | Words screen readers hear for the count. Defaults to "12 characters left". |
invalid | boolean | None | Red edge and aria-invalid. In a Field, follows its error; aria-invalid works too. |
readOnly | boolean | None | Sinks into the well; still focusable and copyable. |
disabled | boolean | None | Sinks into the well and dims; skipped by Tab. |
Every other native textarea attribute, and the ref, go to the textarea. className and style go to the frame around it.