YA Textarea
A multiline text input component for longer content
The YaTextarea is a multiline text input field in the YaVendio Design System. It supports vertical/horizontal orientations, character counter, validation states, and integrates seamlessly with external buttons.
Quick Start
pnpm dlx shadcn@latest add @yavendio/ya-textareanpx shadcn@latest add @yavendio/ya-textareayarn dlx shadcn@latest add @yavendio/ya-textareaimport { YaTextarea } from '@/components/ui/ya-textarea'
export default function Example() {
return <YaTextarea label="Message" placeholder="Type your message here..." />
}Orientations
YaTextarea supports two layout orientations for different use cases.
| Orientation | Description | Features |
|---|---|---|
vertical | Label above textarea | Help text below, counter right of label |
horizontal | Label beside textarea (85px width) | No help text, compact layout |
Vertical (Default)
Label appears above the textarea field.
Provide a detailed description
<YaTextarea
orientation="vertical"
label="Description"
placeholder="Enter a description..."
helpText="Provide a detailed description"
/>Horizontal
Label appears to the left of the textarea field.
<YaTextarea
orientation="horizontal"
label="Bio"
placeholder="Tell us about yourself..."
/>Orientation Comparison
This is help text
<div className="flex flex-col gap-6">
<YaTextarea
orientation="vertical"
label="Vertical Layout"
placeholder="Label above"
helpText="This is help text"
/>
<YaTextarea
orientation="horizontal"
label="Horizontal"
placeholder="Label on the left"
/>
</div>With Counter
Display a character counter next to the label.
Brief description about yourself
import { useState } from 'react'
import { YaTextarea } from '@/components/ui/ya-textarea'
export default function CounterExample() {
const [value, setValue] = useState('')
const maxLength = 500
return (
<YaTextarea
label="Bio"
placeholder="Tell us about yourself..."
value={value}
onChange={(e) => setValue(e.target.value.slice(0, maxLength))}
counter={{ current: value.length, max: maxLength }}
helpText="Brief description about yourself"
/>
)
}With External Button
Integrate with YaButton for combined textarea-action patterns.
Your feedback helps us improve
import { YaTextarea } from '@/components/ui/ya-textarea'
import { YaButton } from '@/components/ui/ya-button'
import { Send } from 'lucide-react'
<YaTextarea
label="Feedback"
placeholder="Share your thoughts..."
helpText="Your feedback helps us improve"
button={
<YaButton variant="primary" rightIcon={<Send />}>
Send
</YaButton>
}
/>States
All States
Please provide a valid message
Disabled
<YaTextarea label="Message" placeholder="This textarea is disabled" disabled />- Reduced opacity (50%)
pointer-events: none- Non-interactive
Destructive
Apply danger styling for validation errors.
Message is required
<YaTextarea
label="Message"
placeholder="Type your message here..."
destructive
errorText="Message is required"
/>Features:
- Red border
- Red label text
- Error message displayed below (vertical only)
Examples
Feedback Form
We appreciate your honest feedback
import { useState } from 'react'
import { YaTextarea } from '@/components/ui/ya-textarea'
import { YaButton } from '@/components/ui/ya-button'
import { Send } from 'lucide-react'
export default function FeedbackForm() {
const [feedback, setFeedback] = useState('')
const maxLength = 1000
return (
<YaTextarea
label="Your Feedback"
placeholder="Share your experience with us..."
value={feedback}
onChange={(e) => setFeedback(e.target.value.slice(0, maxLength))}
counter={{ current: feedback.length, max: maxLength }}
helpText="We appreciate your honest feedback"
button={
<YaButton variant="primary" rightIcon={<Send />}>
Submit
</YaButton>
}
/>
)
}Contact Form
import { YaInput } from '@/components/ui/ya-input'
import { YaTextarea } from '@/components/ui/ya-textarea'
import { YaButton } from '@/components/ui/ya-button'
<form className="flex flex-col gap-4">
<YaInput label="Name" placeholder="Your name" />
<YaInput label="Email" placeholder="your@email.com" />
<YaTextarea
label="Message"
placeholder="How can we help you?"
helpText="Please describe your inquiry in detail"
/>
<div className="flex gap-2 mt-4">
<YaButton type="submit" variant="primary">
Send Message
</YaButton>
<YaButton type="button" variant="secondary">
Cancel
</YaButton>
</div>
</form>With Validation
Minimum 10 characters required
import { useState } from 'react'
import { YaTextarea } from '@/components/ui/ya-textarea'
export default function ValidatedTextarea() {
const [value, setValue] = useState('')
const [error, setError] = useState('')
const minLength = 10
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const newValue = e.target.value
setValue(newValue)
if (newValue.length > 0 && newValue.length < minLength) {
setError(`Message must be at least ${minLength} characters`)
} else {
setError('')
}
}
return (
<YaTextarea
label="Message"
placeholder="Enter your message..."
value={value}
onChange={handleChange}
destructive={!!error}
errorText={error}
helpText={`Minimum ${minLength} characters required`}
/>
)
}Props
YaTextarea
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout orientation |
label | string | - | Label text |
helpText | string | - | Help text (vertical only) |
errorText | string | - | Error message (vertical only, when destructive) |
placeholder | string | - | Placeholder text |
counter | { current: number; max: number } | - | Character counter |
button | ReactNode | - | External button |
destructive | boolean | false | Applies error styling |
disabled | boolean | false | Disable the textarea |
className | string | - | Additional classes |
Additional Props
YaTextarea extends all standard HTML textarea attributes:
id,name,valuerows,cols,maxLengthonChange,onFocus,onBluraria-label,aria-describedby- And all other HTML textarea props
Accessibility
Best Practices
| Do | Don't |
|---|---|
| Use for multiline content | Use for single-line input |
| Always include a label | Skip labels for accessibility |
| Use help text to guide users | Leave users guessing |
| Display clear error messages | Vague error feedback |
Use destructive for validation | Red styling without prop |
| Use character counter for limits | Allow unlimited input when there's a max |
TypeScript
import { type VariantProps } from 'class-variance-authority'
import { yaTextareaWrapperVariants, yaTextareaFieldVariants } from '@/components/ui/ya-textarea'
type TextareaOrientation = VariantProps<typeof yaTextareaWrapperVariants>['orientation']