Textarea with motion: it glides taller with each new line and back down when cleared, and shakes when it turns invalid while its error grows in.
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-textarea.jsonInstallation
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-textarea.jsonAdds components/dashral/motion/textarea.tsx, the Textarea it builds on (in components/dashral/), motion and the motion files every motion component shares. With the registry in your components.json:
$ pnpm dlx shadcn@latest add @dashral/motion-textareaUsage
The same as Textarea, imported from components/dashral/motion/: swap the import and it moves.
import { Textarea } from "@/components/dashral/motion/textarea"
<Textarea label="Message" value={text} onChange={(e) => setText(e.target.value)} error={error} />Examples
A comment box
It glides taller as you write, the count rolls and turns red past the limit; Post drops your comment into the thread and the box glides back down.
Compared with Default
Grows with what's typed, a line at a time, in jumps. The error fades in under it.
Motion
Glides to each new line's height, and back down when the text is cleared; shakes when it turns invalid, its error growing in under it.
How the two editions differ in general, and which to use where: Motion.
API reference
Every prop of Textarea, and every attribute of the element it renders. The Motion edition adds no props of its own.
Textarea
Also takes every prop of <textarea>(opens in a new tab).
| Prop | Type | Default |
|---|---|---|
label | ReactNodeShown above, linked to the control. | — |
description | ReactNodeA hint under the control. | — |
error | boolean | ReactNodetrue shows the error style; a message also shows under the control. | — |
labelAction | ReactNodeAt the end of the label's row, e.g. a “Forgot password?” link or the current value. | — |
withAsterisk | booleanMarks the label with an asterisk, e.g. alongside required. | false |
classNames | { root, label, description, error, textarea }Classes for each part. | — |
className | stringExtra classes, merged with cn() so yours win. | — |
It sizes itself on a glide, so the browser's resize handle is off.
Motion
- Each new line glides the box to its new height (--duration-considered, no overshoot) instead of jumping; cleared from outside (a message sent), it glides back down.
- A new width rewraps the text and the height follows at once, so nothing wobbles while the page resizes.
- When it turns invalid, and again at every try to submit its form while it's still invalid, it shakes sideways a few pixels and settles; the error grows in under it and folds away when it clears.
- With reduced motion it resizes at once, nothing shakes, and messages only appear and disappear.