Multi-line text input for longer content like messages and descriptions
Tags: component form text-input
Textarea allows users to enter and edit multi-line text content.
Import
<script>
import { Textarea } from '@classic-homes/theme-svelte';
</script>Basic Usage
<Textarea placeholder="Enter your message..." />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
'' |
Textarea value (bindable) |
placeholder |
string |
- | Placeholder text |
disabled |
boolean |
false |
Disables the textarea |
readonly |
boolean |
false |
Makes the textarea read-only |
required |
boolean |
false |
Marks as required |
name |
string |
- | Textarea name for forms |
id |
string |
- | Textarea ID for label association |
rows |
number |
3 |
Number of visible text rows |
class |
string |
- | Additional CSS classes |
onValueChange |
(value: string) => void |
- | Callback when value changes |
Rows
Control the visible height with the rows prop:
<Textarea rows={2} placeholder="Short note" />
<Textarea rows={5} placeholder="Detailed description" />
<Textarea rows={10} placeholder="Long form content" />Two-Way Binding
Use Svelte's bind:value for two-way data binding:
<script>
let message = $state('');
</script>
<Textarea bind:value={message} placeholder="Your message" /><p>Character count: {message.length}</p>Value Change Callback
Use onValueChange for controlled input handling:
<script>
let value = $state('');
function handleChange(newValue: string) {
// Limit to 500 characters
value = newValue.slice(0, 500);
}
</script>
<Textarea {value} onValueChange={handleChange} /><p>{500 - value.length} characters remaining</p>States
Disabled
<Textarea disabled value="Cannot edit this content" />Read-only
<Textarea readonly value="This content is read-only" />Required
<Textarea required placeholder="Required field" />With Label
Always associate textareas with labels for accessibility:
<script>
import { Textarea, Label } from '@classic-homes/theme-svelte';
</script>
<div class="space-y-2">
<Label for="message">Message</Label>
<Textarea id="message" placeholder="Enter your message..." />
</div>Resizing
The textarea has resize-y applied by default, allowing vertical resizing. Override with CSS classes:
<!-- No resize -->
<Textarea class="resize-none" />
<!-- Both directions -->
<Textarea class="resize" />Accessibility
The Textarea component includes:
- Full keyboard navigation
- Visible focus ring with
focus-visible - Disabled state with
cursor-not-allowed - Works with
<label>associations viaid - Minimum height maintained for usability
Examples
Character Counter
<script>
import { Textarea, Label } from '@classic-homes/theme-svelte';
let bio = $state('');
const maxLength = 280;
</script>
<div class="space-y-2">
<Label for="bio">Bio</Label>
<Textarea id="bio" bind:value={bio} rows={4} placeholder="Tell us about yourself..." />
<p class="text-sm text-muted-foreground text-right">
{bio.length}/{maxLength}
</p>
</div>With Help Text
<div class="space-y-2">
<Label for="description">Description</Label>
<Textarea id="description" rows={4} placeholder="Describe your item..." />
<p class="text-sm text-muted-foreground">
Include key details to help buyers understand your item.
</p>
</div>Fixed Height
<Textarea class="resize-none h-32" placeholder="Fixed height textarea" />Full Width in Container
<div class="max-w-md">
<Textarea placeholder="Constrained to container width" />
</div>