RadioGroup with motion: the dot springs into the radio you pick and shrinks out of the one you left, and with cards the picked frame glides from card to card.
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-radio-group.jsonInstallation
$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-radio-group.jsonAdds components/dashral/motion/radio-group.tsx, the Radio Group 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-radio-groupUsage
The same as Radio Group, imported from components/dashral/motion/: swap the import and it moves.
import { RadioGroup } from "@/components/dashral/motion/radio-group"
<RadioGroup label="Plan" variant="cards" value={plan} onValueChange={setPlan} options={plans} />Examples
Plan cards
The frame glides from card to card as you pick; Switch works for a moment, then the Current badge pops off the old plan and onto the new one.
Compared with Default
The dot zooms in on the picked radio. A picked card's border and tint change color in place.
Motion
The dot springs in and the one you left shrinks away; a picked card's frame and tint glide from card to card, and a card presses in while held.
How the two editions differ in general, and which to use where: Motion.
API reference
Every prop of Radio Group, and every attribute of the element it renders. The Motion edition adds no props of its own.
RadioGroup
Also takes every prop of Radix Radio Group(opens in a new tab).
| Prop | Type | Default |
|---|---|---|
value / defaultValue | string | — |
onValueChange | (value: string) => voidCalled with the new value. | — |
options | (string | { value; label?; description?; icon?; disabled? })[]The radios. Required; icon shows on cards. | — |
variant | "default" | "cards"cards draws each option as a bordered card you click anywhere on. | "default" |
indicator | booleanWith cards: false hides the radio dot; the border shows what's picked. | true |
orientation | "horizontal" | "vertical"Which arrow keys move. | — |
color | "primary" | "neutral" | "info" | "success" | "warning" | "destructive" | "highlight"The color of every picked radio. | "primary" |
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, group, item, radio }Classes for each part. | — |
Motion
- The picked radio's dot springs in from nothing with a small overshoot; the one you left shrinks away (--duration-fast, --ease-exit) instead of vanishing.
- With variant="cards", the picked card's frame and tint are one element that glides from card to card with a touch of overshoot (motion's shared layout).
- A card presses in slightly on a spring while held.
- With reduced motion the dot and frame only fade, and nothing presses in.