Components
Base Components
Radio Group
A set of checkable buttons where no more than one can be checked at a time.
Example
Installation
Create a radio-group.tsx file and paste the following code into it.
"use client"import * as React from "react"import { CircleIcon } from "lucide-react"import { RadioGroup as RadioGroupPrimitive } from "radix-ui"import { cn } from "@/lib/utils"const RadioGroup = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Root>, React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>>(({ className, ...props }, ref) => { return ( <RadioGroupPrimitive.Root data-slot="radio-group" className={cn("grid gap-3", className)} {...props} ref={ref} /> )})RadioGroup.displayName = "RadioGroup"interface RadioGroupItemProps extends React.ComponentProps<typeof RadioGroupPrimitive.Item> { description?: string label?: string}const RadioGroupItem = React.forwardRef< React.ElementRef<typeof RadioGroupPrimitive.Item>, RadioGroupItemProps>(({ className, description, label, id, ...props }, ref) => { const radioItem = ( <RadioGroupPrimitive.Item id={id} ref={ref} data-slot="radio-group-item" className={cn( "peer border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className )} {...props} > <RadioGroupPrimitive.Indicator data-slot="radio-group-indicator" className="relative flex items-center justify-center" > <CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" /> </RadioGroupPrimitive.Indicator> </RadioGroupPrimitive.Item> ) if (!label && !description) { return radioItem } return ( <div className="flex items-start gap-2"> {radioItem} <div className="grid gap-1.5 leading-none"> {label && ( <label htmlFor={id} className="text-sm hover:cursor-pointer font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" > {label} </label> )} {description && <p className="text-sm text-muted-foreground">{description}</p>} </div> </div> )})RadioGroupItem.displayName = "RadioGroupItem"export { RadioGroup, RadioGroupItem }Check the import paths to ensure they match your project setup.
Usage
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";<RadioGroup value={value} onValueChange={setValue}>
<div className="flex items-center gap-2">
<RadioGroupItem value="apple" id="apple" />
<label htmlFor="apple">Apple</label>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="orange" id="orange" />
<label htmlFor="orange">Orange</label>
</div>
</RadioGroup>value and onValueChange for controlled mode, or defaultValue for uncontrolled. Each RadioGroupItem must have a unique value prop.
Examples
Default
With labels
Associate each option with a label usinghtmlFor and a matching id on the RadioGroupItem for better accessibility.
Disabled
Disable the entire group withdisabled on RadioGroup, or disable a single option with disabled on RadioGroupItem.
Controlled
Control the selected value withvalue and onValueChange on RadioGroup.
const [value, setValue] = React.useState("one");
<RadioGroup value={value} onValueChange={setValue}>
<RadioGroupItem value="one" id="one" />
<RadioGroupItem value="two" id="two" />
</RadioGroup>With description
Use thelabel and description props to add a label and helper text to each radio option.
Perfect for personal projects and small teams.
Advanced features for growing businesses.
Custom solutions with dedicated support.
<RadioGroup defaultValue="free">
<RadioGroupItem
value="free"
id="plan-free"
label="Free Plan"
description="Perfect for personal projects and small teams."
/>
<RadioGroupItem
value="pro"
id="plan-pro"
label="Pro Plan"
description="Advanced features for growing businesses."
/>
<RadioGroupItem
value="enterprise"
id="plan-enterprise"
label="Enterprise Plan"
description="Custom solutions with dedicated support."
/>
</RadioGroup>Focused
The radio button shows a focus ring when focused via keyboard navigation. Click or use Tab key to focus this radio button.Description
<RadioGroup>
<RadioGroupItem
value="focused"
id="focused-example"
label="Label"
description="Description"
/>
</RadioGroup>Focused + Selected
The radio button can be both selected and focused at the same time.Description
<RadioGroup defaultValue="focused-selected">
<RadioGroupItem
value="focused-selected"
id="focused-selected-example"
label="Label"
description="Description"
autoFocus
/>
</RadioGroup>API Reference
RadioGroup
The RadioGroup component wraps Radix UI's RadioGroup.Root and manages the selected value and layout of radio items.asChildboolean
Default: -
disabledboolean
Default: -
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | - | - |
| disabled | boolean | - | - |
RadioGroupItem
RadioGroupItem represents a single option. Each item must have a uniquevalue that is used when that option is selected.
labelstring
Default: -
asChildboolean
Default: -
disabledboolean
Default: -
type"button" | "submit" | "reset"
Default: -
descriptionstring
Default: -
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | - | - |
| asChild | boolean | - | - |
| disabled | boolean | - | - |
| type | "button" | "submit" | "reset" | - | - |
| description | string | - | - |