Accordion with motion: a section opens and closes on a spring, what's inside rises a little as it fades in, and the chevron turns with the panel as far as it has opened.
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-accordion.jsonInstallation
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-accordion.jsonAdds components/dashral/motion/accordion.tsx, the Accordion 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-accordionUsage
The same as Accordion, imported from components/dashral/motion/: swap the import and it moves.
import { Accordion } from "@/components/dashral/motion/accordion"
<Accordion
items={[
{ value: "trial", title: "Is there a free trial?", content: "Yes, 14 days." },
{ value: "refunds", title: "Can I get a refund?", content: "Within 30 days." },
]}
/>Examples
FAQ
Answer Was this helpful? and the open section glides to fit the thank you, or the form No opens.
Yes: 14 days of Team, no card needed. You keep your dashboards if you stay on Starter.
Within 30 days of paying, for any reason. Write to us from the account page and the money is back within five working days, on the card you paid with.
You pay for people who can sign in. Viewers on a shared link are free.
Start a return
variant="separated": start a return and the card glides open to fit its label and steps.
Compared with Default
Sections open and close on a keyframe of set length.
Motion
Sections open and close on a spring with no overshoot; what's inside rises as it fades in; the chevron turns with the panel itself and leans on hover the way it'll go.
How the two editions differ in general, and which to use where: Motion.
API reference
Every prop of Accordion, and every attribute of the element it renders. The Motion edition adds no props of its own.
Accordion
Also takes every prop of <div>(opens in a new tab).
| Prop | Type | Default |
|---|---|---|
items | { title, content, value?, disabled? }[]The sections. Required. | — |
multiple | booleanAny number open at once; otherwise opening one closes the other. | false |
value / defaultValue | string[]The open sections (their value, or index), controlled or initial. | — |
onValueChange | (value: string[]) => voidCalled with the new value. | — |
variant | "default" | "separated"Rows split by lines, or each a card of its own. | "default" |
classNames | { item, trigger, content }Classes for each part. | — |
className | stringExtra classes, merged with cn() so yours win. | — |
Motion
- A section's height glides open and closed on a spring with no overshoot, so the rows below move as one.
- What's inside rises 4px as it fades in, and fades a little faster on the way out.
- The chevron's turn is the panel's: 0° closed, 180° open and every angle between, so a section reversed halfway turns back from where it is. Hovered, it leans 2px the way the section will go.
- An open section keeps following what's inside: a line added or removed, an answer swapped for a thank you, and it glides to the new height.
- Closed sections stay mounted so closing can play out, but they're inert: the keyboard and screen readers skip them. With reduced motion sections open and close at once.