Textarea
A multi-line text field.
Playground
<Textarea
variant="outlined"
/>01 Examples
Auto-resizing notes field
autoResize measures the text after every keystroke and after a value you assign yourself. maxRows is where the growing stops and the field starts scrolling. minRows is a floor it never shrinks below, and the size brings a floor of its own that a small minRows disappears under.<Textarea
label="Notes"
placeholder="Start typing and the field will grow..."
autoResize
minRows={2}
maxRows={10}
/>Character-limited composer
showCounter needs a maxlength to count against and then reads count/limit. It switches to the warning colour at 90 percent of the limit, which counterWarningThreshold moves, and typing stops at the limit itself.<Textarea
label="Tweet"
placeholder="What's happening?"
maxlength={280}
showCounter
autoResize
minRows={2}
/>In a form
<textarea> sits underneath, so name submits the text and required, readonly or an oninput handler all reach it. error is yours to set from whatever the submit finds out, and it takes the helper text's place while it is there.<form
class="border-border-subtle bg-surface-elevated w-full space-y-4 rounded-2xl border p-5"
onsubmit={handleFeedback}
>
<Textarea
name="feedback"
label="Your feedback"
placeholder="What could we improve?"
helper="Anything from a typo to a missing feature"
error={feedbackError}
maxlength={500}
showCounter
autoResize
minRows={3}
maxRows={8}
bind:value={feedback}
/>
<Button type="submit" size="sm">Send feedback</Button>
{#if sent}
<p class="text-success text-xs">Thanks, that went through.</p>
{/if}
</form>02 Customization
A quieter field
underline variant, so it costs no classes at all. What is left for slotClasses is the counter row underneath, addressed by the footer and counter slots.<Textarea
variant="underline"
label="Release note"
autoResize
minRows={4}
maxlength={200}
showCounter
placeholder="What changed in this version?"
bind:value={bio}
slotClasses={{
footer: 'justify-start',
counter: 'tabular-nums tracking-wide'
}}
/>A field that should read as the text it sits in is the bare variant, not a stack of reset classes: no frame,
no fill, no padding, no fixed height, and size keeps
only its type step. It needs context that says it is a field — a placeholder, a rule under the
line, a label before it — and it keeps the one thing such a reset usually loses, a focus
outline, whose colour is the --blocks-focus-ring-color custom property. Worked through on the Input page.
A treatment the whole form shares belongs on a BlocksProvider, as a defaults entry for Textarea next to the same entry for Input and Select. See Customization for class, slotClasses, unstyled, preset and provider-level overrides.
03 Accessibility
Labels and messages
The label prop renders a <label> linked through for/id, and
the id is generated unless you pass one. Helper and error text reach the field through aria-describedby, and an error sets aria-invalid.
Character counter
The counter is aria-live="polite", so a screen reader
speaks the new count once the user pauses instead of cutting in on every keystroke.
Keyboard
The focus ring shows for keyboard users only.
04 API Reference
23 propsProp | Type | Default | Description | |
|---|---|---|---|---|
autoResize | boolean | false | Automatically grow the textarea height to fit content. Disables manual resize handle. | |
class | string | — | Extra classes merged onto the root wrapper element. | |
counterWarningThreshold | number | 0.9 | Character threshold (percentage of maxlength) at which the counter turns warning color. | |
disabled | boolean | false | disabled property | |
error | string | — | Error message below the textarea. Overrides helper and forces danger border styling. | |
helper | string | — | Helper text below the textarea. Hidden when error is set. | |
intent variant | dangerdefaultsuccesswarning | default | Controls the color theme and semantic meaning of the Textarea. Affects the overall appearance and user perception. Available options: danger, default, success, warning. | |
label | string | — | Label text displayed above the textarea, auto-linked via for/id. | |
maxRows | number | — | Maximum number of visible text rows when autoResize is enabled. | |
messageType variant | errorhelper | helper | Controls the messageType behavior and appearance of the Textarea component. Available options: error, helper. | |
minRows | number | 3 | Minimum number of visible text rows. | |
mint | MintProp | 'none' | Micro-interaction preset applied to the textarea element. Only applies while not disabled. | |
preset | string | — | Apply a named preset registered via <BlocksProvider presets={{ Textarea: {...} }}>.
Prefer this over class overrides when the requested look falls outside the
semantic intent palette — presets keep hover/active/dark-mode logic coherent
and make the custom look reusable across the project. | |
readonly | boolean | false | readonly property | |
required | boolean | false | Adds a required asterisk to the label and sets the native required attribute. | |
showCounter | boolean | — | Show a live character counter. Requires maxlength; shows the current count against the limit (e.g. 42/280). | |
size variant | lgmdsmxl +1 more | md | Controls the dimensions, padding, and text size of the Textarea. Affects the component's physical footprint. Available options: lg, md, sm, and 2 more. | |
slotClasses | Partial<Record<TextareaSlots, string>> | — | Per-slot class overrides merged with tv() styles. Slots: wrapper (root —
what class also targets) | base (the <textarea> element) | label |
requiredMark | footer | message | counter. | |
tier variant | commitmodify | modify | Selects the semantic radius tier of the Textarea — the shape family it belongs to (--radius-commit/-modify/-contain/-bridge). Shape is retuned per family in your theme, so this picks the family rather than a pixel value. Available options: commit, modify. | |
unstyled | boolean | — | Remove all default tv() classes. Only user-provided classes apply. | |
variant | TextareaVariants['variant'] | 'outlined' | Visual style.
- outlined (default) — visible border, surface-base background
- filled — surface-interactive fill, no border
- ghost — transparent until hover/focus
- underline — bottom-line only, no border-box (editorial style)
- bare — no frame, no fill, no padding, no fixed height: the field reads as
the text it sits in. size keeps only the type step, and focus is an
outline in --blocks-focus-ring-color | |
...HTMLTextareaAttributes inherited | HTMLAttributes | — | HTML attributes (excluding: 'size' | 'class' | 'children') | |
...TextareaVariants variant | VariantProps | — | Styling variants from TextareaVariants |
05 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
TextareaProps | interface | props | 0 | — | |
TextareaVariants | type | variant | 0 | — | |
TextareaSlots | type | variant | 0 | Slot names derived from the tv() config above — single source of truth for slotClasses. | |
MintProp | type | helper | 1 | — | |
MintName | type | helper | 0 | A mint name: a built-in (autocompleted), 'none' to disable, or any
consumer-registered name. (string & {}) keeps the registry open — a
custom name still type-checks, it just isn't suggested. A typo therefore
also still compiles (it resolves like an unregistered custom name and
warns at runtime); the union buys completion and docs, not validation. | |
MintConfig | interface | helper | 0 | — | |
BuiltinMintName | type | helper | 0 | Built-in mint names as a literal union, so the mint prop autocompletes
across every component — the single list the hand-curated playground knobs
and docs used to drift away from. |
06 Installation
Import
import { Textarea } from '@urbicon-ui/blocks';