@neynar/ui
Version:
React UI component library built on shadcn/ui and Tailwind CSS
311 lines (272 loc) • 7.24 kB
Markdown
# Textarea
**Type**: component
Textarea - Multi-line text input control for extended content entry A styled textarea component built on the native HTML textarea element for entering longer pieces of text that span multiple lines, such as comments, descriptions, messages, or any content that requires multiple lines of input. Features automatic content-based resizing using CSS field-sizing when supported by the browser. Built following shadcn/ui design patterns with consistent styling and behavior across form elements. Inherits all native HTML textarea functionality while providing enhanced visual design and better accessibility patterns.
## JSX Usage
```jsx
import { Textarea } from '@neynar/ui';
<Textarea
className="value"
placeholder="value"
disabled={true}
readOnly={true}
rows={0}
cols={0}
maxLength={0}
minLength={0}
required={true}
form="value"
name="value"
id="value"
value="value"
defaultValue="value"
wrap={value}
autoFocus={true}
autoComplete="value"
autoCapitalize={value}
spellCheck={true}
onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
onKeyPress={handleKeyPress}
"aria-invalid"={value}
"aria-describedby"="value"
"aria-labelledby"="value"
"aria-label"="value"
tabIndex={0}
style={value}
/>
```
## Component Props
### className
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### placeholder
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### disabled
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### readOnly
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### rows
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### cols
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### maxLength
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### minLength
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### required
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### form
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### name
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### id
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### value
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### defaultValue
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### wrap
- **Type**: `"soft" | "hard" | "off"`
- **Required**: No
- **Description**: No description available
### autoFocus
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### autoComplete
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### autoCapitalize
- **Type**: `"none" | "sentences" | "words" | "characters"`
- **Required**: No
- **Description**: No description available
### spellCheck
- **Type**: `boolean`
- **Required**: No
- **Description**: No description available
### onChange
- **Type**: `(event: React.ChangeEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### onFocus
- **Type**: `(event: React.FocusEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### onBlur
- **Type**: `(event: React.FocusEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### onKeyDown
- **Type**: `(event: React.KeyboardEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### onKeyUp
- **Type**: `(event: React.KeyboardEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### onKeyPress
- **Type**: `(event: React.KeyboardEvent<HTMLTextAreaElement>) => void`
- **Required**: No
- **Description**: No description available
### "aria-invalid"
- **Type**: `boolean | "false" | "true" | "grammar" | "spelling"`
- **Required**: No
- **Description**: No description available
### "aria-describedby"
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### "aria-labelledby"
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### "aria-label"
- **Type**: `string`
- **Required**: No
- **Description**: No description available
### tabIndex
- **Type**: `number`
- **Required**: No
- **Description**: No description available
### style
- **Type**: `React.CSSProperties & {
resize?: "none" | "both" | "horizontal" | "vertical";
}`
- **Required**: No
- **Description**: No description available
## Examples
### Example 1
```tsx
// Basic usage
<Textarea placeholder="Type your message here..." />
```
### Example 2
```tsx
// With label and validation
<div className="space-y-2">
<Label htmlFor="description">Description</Label>
<Textarea
id="description"
placeholder="Enter a description..."
rows={4}
required
/>
</div>
```
### Example 3
```tsx
// Controlled with character limit and validation
const [bio, setBio] = useState("");
const [error, setError] = useState("");
const maxLength = 160;
<div className="space-y-2">
<Label htmlFor="bio">Bio</Label>
<Textarea
id="bio"
value={bio}
onChange={(e) => {
setBio(e.target.value);
if (e.target.value.length > maxLength) {
setError("Bio is too long");
} else {
setError("");
}
}}
placeholder="Tell us about yourself..."
maxLength={maxLength}
aria-invalid={!!error}
aria-describedby={error ? "bio-error" : "bio-count"}
/>
<div className="flex justify-between items-center">
<p id="bio-count" className="text-sm text-muted-foreground">
{bio.length}/{maxLength} characters
</p>
{error && (
<p id="bio-error" className="text-sm text-destructive">
{error}
</p>
)}
</div>
</div>
```
### Example 4
```tsx
// Auto-resizing with minimum height
<Textarea
placeholder="This textarea grows with content"
className="min-h-[100px] max-h-[300px]"
style={{ resize: "vertical" }}
/>
```
### Example 5
```tsx
// Form integration with validation
<form onSubmit={handleSubmit}>
<div className="space-y-2">
<Label htmlFor="feedback">Feedback</Label>
<Textarea
id="feedback"
name="feedback"
placeholder="Share your thoughts..."
required
minLength={10}
maxLength={500}
rows={3}
/>
</div>
<Button type="submit">Submit Feedback</Button>
</form>
```
### Example 6
```tsx
// Different wrap behaviors for code/text
<div className="space-y-4">
<div>
<Label>Code (no wrapping)</Label>
<Textarea
wrap="off"
placeholder="Enter code here..."
className="font-mono text-sm"
style={{ resize: "both" }}
/>
</div>
<div>
<Label>Text (soft wrapping)</Label>
<Textarea
wrap="soft"
placeholder="Enter text content..."
/>
</div>
</div>
```