Updated
Radio Group
NewCustomize
Cards
Vertical
Medium
Duration0.30s
Installation
npx shadcn@latest add https://uibrik.com/r/radio-group.jsonInstall the packages
npm install motionAdd the cn helper
Imports
cnfrom@/lib/utils, whichshadcn initcreates. Add it by hand without shadcn.Copy the source into your project
components/uibrik/radio-group/radio-group.tsx"use client"; import { useId, useLayoutEffect, useRef, useState, type KeyboardEvent, type ReactNode } from "react"; import { LayoutGroup, MotionConfig, motion } from "motion/react"; import { cn } from "@/lib/utils"; // Radio group. There's one dot, and choosing another option sends it across // to that option's ring instead of blinking one off and the next on, so the // eye follows the choice. In the cards layout an outline travels with it, // measured from the cards so it lands exactly on cards of any size. // // Tab lands on the chosen option, arrows move the choice (skipping disabled // options), Home and End jump to the ends. export type RadioOption = | string | { value: string; label: ReactNode; description?: ReactNode; /** Right-aligned detail, e.g. a price. */ meta?: ReactNode; icon?: ReactNode; disabled?: boolean }; export type RadioGroupProps = { options: readonly RadioOption[]; /** Chosen value (controlled). Pair with `onChange`. */ value?: string; /** Chosen value on mount (uncontrolled). Leave out for none. */ defaultValue?: string;
Adds the files to
components/uibrik/radio-group and installs motion. With the @uibrik namespace set up: npx shadcn@latest add @uibrik/radio-group.Usage
import { RadioGroup } from "@/components/uibrik/radio-group/radio-group";const options = [ { value: "standard", label: "Standard", description: "4–6 business days", meta: "Free" }, { value: "express", label: "Express", description: "2–3 business days", meta: "$9" }, // …1 more];<RadioGroup options={options} variant="cards" orientation="vertical" size="md" duration={0.3} disabled={false} defaultValue="express" label="Shipping" // value="…" // onChange={(value) => {}} // name="…"/>Where to use Radio Group
Plan choice in forms
Bordered cards with an outline that follows suit choosing a plan or tier.
Pairs with Segmented Control
Shipping and payment methods
One dot travelling to the chosen option makes the selection unmistakable.
Single-choice settings
Full arrow-key control keeps the group accessible.
Pairs with Checkbox
Props
RadioGroup- variant
- Type "cards" | "list"
- "cards"
- Plain rows, or a bordered card per option.
- orientation
- Type "vertical" | "horizontal"
- "vertical"
- A column, or side by side where they fit.
- size
- Type "sm" | "md" | "lg"
- "md"
- Ring and text size.
- duration
- Type number
- 0.3
- How long the dot takes to travel.
- disabled
- Type boolean
- false
- Grey the group out and ignore input.
- optionsrequired
- Type (string | { value; label; description?; meta?; icon?; disabled? })[]
- –
- Options in order. `meta` sits on the right, e.g. a price.
- value / onChange
- Type string / (value) => void
- –
- Controlled choice.
- defaultValue
- Type string
- –
- Choice on mount when uncontrolled. Leave out for none.
- name
- Type string
- –
- Submits the choice under this name with a surrounding form.
- label
- Type string
- –
- Names the group for screen readers.
- className
- Type string
- –
- Classes for the group.