Textarea
ComponentsMulti-line inputs.
Live Functional Playground Interactive Hooks • useState
Type to validate
0 chars
Motion Physics & Animation Showcase Framer Motion ✨
Motion Physics
✨
Hover to trigger spring elevation lift
Format:
Required Animation Library: framer-motion & lucide-react
Install this package in your project before importing the animated component.
npm i framer-motion lucide-react <textarea class="flex min-h-[80px] w-full max-w-sm rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50" placeholder="Type your message here."></textarea> <textarea className="flex min-h-[80px] w-full max-w-sm rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50" placeholder="Type your message here."></textarea> "use client";
import React, { useState } from "react";
interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
label?: string;
maxLength?: number;
}
export default function Textarea({
label = "Project Description",
maxLength = 250,
className = "",
...props
}: TextareaProps) {
const [value, setValue] = useState("");
const remaining = maxLength - value.length;
return (
<div className="w-full max-w-sm space-y-1.5">
<div className="flex items-center justify-between text-xs font-semibold text-foreground">
<span>{label}</span>
<span className={`text-[10px] font-mono ${remaining < 20 ? "text-amber-500 font-bold" : "text-muted-foreground"}`}>
{remaining} left
</span>
</div>
<textarea
{...props}
value={value}
maxLength={maxLength}
onChange={(e) => setValue(e.target.value)}
rows={4}
className={`w-full px-3.5 py-2.5 text-xs rounded-xl border border-input bg-background text-foreground transition-all focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-hidden resize-none ${className}`}
placeholder="Provide brief details about your use-case..."
/>
</div>
);
} "use client";
import React, { useState } from "react";
import { motion } from "framer-motion";
export default function AnimatedTextarea() {
const [text, setText] = useState("");
const [isFocused, setIsFocused] = useState(false);
return (
<div className="w-full max-w-sm space-y-2">
<div className="flex justify-between items-center text-xs font-semibold">
<span className="text-foreground">Feedback & Comments</span>
<motion.span
animate={{ scale: text.length > 0 ? [1, 1.15, 1] : 1 }}
transition={{ duration: 0.2 }}
className="text-[10px] font-mono text-purple-400 font-bold"
>
{text.length} characters
</motion.span>
</div>
<motion.div
animate={{
boxShadow: isFocused ? "0 0 0 3px rgba(168, 85, 247, 0.25)" : "none",
}}
className="rounded-xl overflow-hidden border border-input bg-background"
>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
rows={4}
className="w-full px-3.5 py-2.5 text-xs text-foreground bg-transparent focus:outline-hidden resize-none"
placeholder="Share your thoughts or feedback..."
/>
</motion.div>
</div>
);
}