ComponentsPrimitives
Textarea
Multi-line text input for longer form content
The Textarea component is a multi-line text input for capturing longer form content such as comments, descriptions, and messages. It supports validation variants, multiple sizes, and optional resize behavior.
Import
import { Textarea } from '@nim-ui/components';Variants
Textarea comes in three variants to communicate validation state.
Code
<Textarea variant="default" placeholder="Default textarea" />
<Textarea variant="error" placeholder="Error textarea" />
<Textarea variant="success" placeholder="Success textarea" />Sizes
Three size options are available: small, medium (default), and large.
Code
<Textarea size="sm" placeholder="Small textarea" />
<Textarea size="md" placeholder="Medium textarea" />
<Textarea size="lg" placeholder="Large textarea" />States
Disabled
Code
<Textarea disabled placeholder="Disabled textarea" />Non-Resizable
Code
<Textarea resize={false} placeholder="This textarea cannot be resized" />Custom Rows
Code
<Textarea rows={2} placeholder="2 rows" />
<Textarea rows={6} placeholder="6 rows" />
<Textarea rows={10} placeholder="10 rows" />Props
| Name | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'error' | 'success' | 'default' | Visual style variant indicating validation state |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the textarea (affects padding and font size) |
resize | boolean | true | Whether the textarea can be resized by the user |
rows | number | 4 | Number of visible text rows |
placeholder | string | - | Placeholder text displayed when the textarea is empty |
disabled | boolean | false | Whether the textarea is disabled |
className | string | - | Additional CSS classes to apply |
The Textarea component also accepts all standard HTML textarea attributes (excluding the native size attribute, which is replaced by the component's size prop).
Usage Examples
Comment Form
function CommentForm() {
const [comment, setComment] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
submitComment(comment);
setComment('');
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="comment" className="block text-sm font-medium mb-1">
Your Comment
</label>
<Textarea
id="comment"
rows={4}
placeholder="Write your comment..."
value={comment}
onChange={(e) => setComment(e.target.value)}
/>
</div>
<Button type="submit">Post Comment</Button>
</form>
);
}With Character Count
function DescriptionField() {
const [value, setValue] = useState('');
const maxLength = 500;
return (
<div>
<label htmlFor="description" className="block text-sm font-medium mb-1">
Description
</label>
<Textarea
id="description"
rows={6}
placeholder="Describe your project..."
value={value}
onChange={(e) => setValue(e.target.value)}
variant={value.length > maxLength ? 'error' : 'default'}
/>
<p className={`mt-1 text-sm ${value.length > maxLength ? 'text-red-500' : 'text-gray-500'}`}>
{value.length}/{maxLength} characters
</p>
</div>
);
}Feedback Form
function FeedbackForm() {
const [feedback, setFeedback] = useState('');
const [submitted, setSubmitted] = useState(false);
return (
<form onSubmit={handleSubmit} className="space-y-4">
<Textarea
placeholder="Tell us what you think..."
rows={5}
resize={false}
value={feedback}
onChange={(e) => setFeedback(e.target.value)}
variant={submitted ? 'success' : 'default'}
/>
<Button type="submit" disabled={!feedback.trim()}>
Send Feedback
</Button>
</form>
);
}Accessibility
The Textarea component follows WAI-ARIA best practices:
- Uses semantic
<textarea>element - Supports all native textarea attributes including
aria-labelandaria-describedby - Visual variants communicate state but should be paired with text for screen readers
- Focus visible states for keyboard users
- Disabled state properly disables interaction and announces to assistive technology
Keyboard Support
| Key | Action |
|---|---|
| Tab | Moves focus to the textarea |
| Shift + Tab | Moves focus to previous focusable element |
Best Practices
- Always pair textareas with visible
<label>elements oraria-label - Use appropriate
rowsvalues to hint at expected content length - Provide character count when there is a maximum length
- Use the
errorvariant alongside visible error messages