Textarea
Multi-line text input with auto-resize, character counter, validation, and semantic variants.
Playground
<Textarea
variant="outlined"
/>01 Examples
Auto-resizing notes field
autoResize with minRows/maxRows to grow the field as the user writes and cap the height before it dominates the layout.<Textarea
label="Notes"
placeholder="Start typing — the field will grow..."
autoResize
minRows={2}
maxRows={10}
/>Character-limited composer
maxlength, showCounter, and autoResize for tweet/comment-style inputs. The counter announces remaining characters via aria-live.<Textarea
label="Tweet"
placeholder="What's happening?"
maxlength={280}
showCounter
autoResize
minRows={2}
/>Helper & error
error overrides helper when both are set and toggles aria-invalid.<Textarea
label="Bio"
helper="Write a short bio for your profile page"
placeholder="I'm a..."
/>
<Textarea
label="Required field"
error="This field is required"
placeholder="Cannot be empty"
/>Feedback Form
No feedback yet
<div class="border-border-subtle bg-surface-elevated w-full space-y-4 rounded-2xl border p-5">
<Textarea
label="Your Feedback"
placeholder="What could we improve?"
maxlength={500}
showCounter
autoResize
minRows={3}
maxRows={8}
bind:value={feedback}
/>
<p class="text-text-tertiary text-xs">
{feedback.length > 0 ? `${feedback.length} characters entered` : 'No feedback yet'}
</p>
</div>02 Customization
Code Input
<Textarea
label="JSON Config"
placeholder={'{"key": "value"}'}
slotClasses={{ base: 'font-mono text-sm' }}
minRows={5}
/>Fully Custom (unstyled)
<Textarea
unstyled
autoResize
maxlength={200}
showCounter
placeholder="Minimal textarea..."
bind:value={bio}
slotClasses={{
wrapper: 'flex flex-col gap-1',
base: 'bg-transparent border-b-2 border-text-tertiary px-0 py-2 text-text-primary placeholder:text-text-quaternary focus-visible:outline-none focus-visible:border-primary resize-none transition-colors',
footer: 'flex justify-end',
counter: 'text-xs text-text-tertiary tabular-nums'
}}
/>A field treatment shared with Input and Select belongs in a BlocksProvider preset (presets.Textarea) so the whole form speaks one
language — see Customization.
03 Accessibility
Labels & Descriptions
The label prop creates an associated <label> element linked via for/id. Helper
and error text are linked via aria-describedby, and errors set aria-invalid.
Character Counter
The character counter uses aria-live="polite" to announce remaining characters to
screen readers. Color changes at warning/over thresholds are paired with text for non-color-dependent
feedback.
Keyboard
Standard textarea keyboard behavior. Focus rings use focus-visible: for keyboard-only visibility. Auto-resize
does not interfere with keyboard interaction or scroll position.
Reduced Motion
Mint effects respect prefers-reduced-motion. The
auto-resize height adjustment is instantaneous and does not animate.
04 API Reference
Prop | 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 | Whether the Textarea is disabled and non-interactive | |
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 for the Textarea component | |
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 to display remaining count. | |
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 |
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) | |
...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';