Radio Group
A set of radio buttons where exactly one option can be chosen.
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Label } from '@/components/ui/label'
export default function RadioGroupDemo() {
return (
<RadioGroup defaultValue="comfortable" aria-label="Density">
<div className="flex items-center gap-2">
<RadioGroupItem id="radio-demo-default" value="default" />
<Label htmlFor="radio-demo-default">Default</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem id="radio-demo-comfortable" value="comfortable" />
<Label htmlFor="radio-demo-comfortable">Comfortable</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem id="radio-demo-compact" value="compact" />
<Label htmlFor="radio-demo-compact">Compact</Label>
</div>
</RadioGroup>
)
}
Built on Base UI
Installation
pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/radio-group.jsonNeeds a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.
Radio Group imports cn() from lib/utils.ts — add it too if you don't have it yet:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Usage
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Label } from '@/components/ui/label'
<RadioGroup defaultValue="comfortable" aria-label="Density">
<div className="flex items-center gap-2">
<RadioGroupItem id="r1" value="default" />
<Label htmlFor="r1">Default</Label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem id="r2" value="comfortable" />
<Label htmlFor="r2">Comfortable</Label>
</div>
</RadioGroup>Examples
Cards with descriptions
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
const plans = [
{ value: 'starter', name: 'Starter', description: 'For a single portfolio.' },
{ value: 'studio', name: 'Studio', description: 'For a small team with shared projects.' },
{ value: 'archive', name: 'Archive', description: 'Read-only, for finished work.', disabled: true },
]
export default function RadioGroupCards() {
return (
<RadioGroup defaultValue="studio" aria-label="Plan" className="w-full max-w-sm">
{plans.map(plan => (
<label
key={plan.value}
className="flex cursor-pointer items-start gap-3 rounded-lg border border-border p-4 transition-colors has-[[data-checked]]:border-primary has-[[data-disabled]]:cursor-not-allowed has-[[data-disabled]]:opacity-50"
>
<RadioGroupItem value={plan.value} disabled={plan.disabled} className="mt-0.5" />
<span className="grid gap-1">
<span className="text-sm leading-none font-medium">{plan.name}</span>
<span className="text-sm text-muted-foreground">{plan.description}</span>
</span>
</label>
))}
</RadioGroup>
)
}
API Reference
| Name | Type | Default | Description |
|---|---|---|---|
| value / onValueChange | unknown / (value: unknown) => void | — | Controlled selected value (set on RadioGroup). |
| defaultValue | unknown | — | Initially selected value (uncontrolled). |
| name | string | — | Identifies the group when a form is submitted. |
| required | boolean | false | The visitor must choose a value before submitting a form. |
| disabled | boolean | false | Ignores user interaction (on RadioGroup, or on a single RadioGroupItem). |
| RadioGroupItem value | unknown | — | The value this radio stands for. Required. |
| Keyboard | — | — | Arrow keys move the selection; Tab enters and leaves the group as one stop. |