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>
The RadioGroup manages the selected value. Use 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 using htmlFor and a matching id on the RadioGroupItem for better accessibility.

Disabled

Disable the entire group with disabled on RadioGroup, or disable a single option with disabled on RadioGroupItem.

Controlled

Control the selected value with value 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 the label 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: -
PropTypeDefaultDescription
asChildboolean--
disabledboolean--

RadioGroupItem

RadioGroupItem represents a single option. Each item must have a unique value that is used when that option is selected.
labelstring
Default: -
asChildboolean
Default: -
disabledboolean
Default: -
type"button" | "submit" | "reset"
Default: -
descriptionstring
Default: -
PropTypeDefaultDescription
labelstring--
asChildboolean--
disabledboolean--
type"button" | "submit" | "reset"--
descriptionstring--

On this page