TextArea
Multi-line text that grows as you type. Labels, descriptions, and errors belong to Field. For a single line, use Input.
Installation
bun add @harmo-ui/css @harmo-ui/reactnpm install @harmo-ui/css @harmo-ui/reactpnpm add @harmo-ui/css @harmo-ui/reactyarn add @harmo-ui/css @harmo-ui/reactbunx harmo-ui add textareanpx harmo-ui add textareapnpm dlx harmo-ui add textareayarn dlx harmo-ui add textareaUsage
import { Field, TextArea } from "@harmo-ui/react";
<Field label="Message">
<TextArea name="message" maxLength={500} placeholder="Hello, your order has shipped…" />
</Field>Examples
With a counter
It starts one line tall and grows as you type, up to 150px, then scrolls. The counter under it, connected with aria-describedby, counts toward maxlength.
0/500
<Field label="Message">
<TextArea
name="message"
maxLength={500}
placeholder="Hello, your order has shipped…"
/>
</Field>Long text
Already tall with its text. Dragging the corner handle can make it taller, up to 400px or half the window, whichever is less.
<Field label="Saved reply">
<TextArea
name="reply"
defaultValue="Thanks for reaching out! Your order left our warehouse this morning and should arrive within three working days. You can follow it with the tracking link in your confirmation email, and reply here if anything looks off."
/>
</Field><div class="hfield">
<label class="hlabel" for="reply">Saved reply</label>
<textarea class="htextarea" id="reply" name="reply">Thanks for reaching out! Your order left our warehouse this morning and should arrive within three working days. You can follow it with the tracking link in your confirmation email, and reply here if anything looks off.</textarea>
</div>Custom maximum height
--htextarea-max-height sets how tall dragging the corner can make it; here 200px instead of 400px or half the window.
<Field label="Email footer">
<TextArea
name="footer-text"
style={{ "--htextarea-max-height": "200px" } as CSSProperties}
defaultValue="Acme Support · Mon–Fri, 9:00–18:00"
/>
</Field><div class="hfield">
<label class="hlabel" for="footer-text">Email footer</label>
<textarea class="htextarea" id="footer-text" name="footer-text" style="--htextarea-max-height: 200px">Acme Support · Mon–Fri, 9:00–18:00</textarea>
</div>Invalid
aria-invalid="true" turns the border red, as for an Input.
Remove card numbers from notes.
<Field
label="Internal note"
optional="Optional"
error="Remove card numbers from notes."
>
<TextArea
name="internal-note"
defaultValue="Customer paid with card 4242 4242 4242 4242."
/>
</Field>Read-only and disabled
As for an Input: both get a gray background, and only the read-only one can be focused and copied from.
<div class="hfield">
<label class="hlabel" for="original-message">Original message</label>
<textarea class="htextarea" id="original-message" name="original-message" readonly>Where is my order?</textarea>
</div>
<div class="hfield">
<label class="hlabel" for="signature">Signature</label>
<textarea class="htextarea" id="signature" name="signature" disabled>The Acme team</textarea>
</div>API reference
React
<TextArea> renders the <textarea>, and with maxLength the counter, connected through aria-describedby and kept current as you type and after a form reset. In a Field, it takes the field's id and descriptions. Its props are the textarea's attributes, with value or defaultValue.
HTML
A <textarea class="htextarea">, with an optional .htextarea-counter right after it, named by a <label for>. Load textarea.css; field.css for its label and messages.
| Hook | Effect |
|---|---|
aria-invalid="true", readonly, disabled, placeholder | As for Input |
.htextarea-counter | A character count under the box |
--htextarea-max-height | How tall dragging can make it; default min(400px, 50dvh) |
A script is only needed for the counter's text. See TextArea's full contract.
Accessibility
Name it with a <label for> in a Field. Connect the counter with aria-describedby, so screen readers read it on focus.