Components
Radio Group

Radio Group

A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.

How it works

Install the following dependencies:

pnpm add @radix-ui/react-radio-group tailwind-merge clsx

Create a new file at lib/utils.ts and add the provided code.

import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}

Create a file at components/ui/radio-group.tsx and paste the given code.

radio-group.tsx

"use client";
 
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import * as React from "react";
 
import { cn } from "@/lib/utils";
 
const RadioGroup = React.forwardRef<
    React.ComponentRef<typeof RadioGroupPrimitive.Root>,
    React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
    return (
        <RadioGroupPrimitive.Root
            className={cn("grid gap-3", className)}
            {...props}
            ref={ref}
        />
    );
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
 
const RadioGroupItem = React.forwardRef<
    React.ComponentRef<typeof RadioGroupPrimitive.Item>,
    React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
    return (
        <RadioGroupPrimitive.Item
            ref={ref}
            className={cn(
                "aspect-square size-4 rounded-full border border-input shadow-sm shadow-black/5 outline-offset-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring/70 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
                className,
            )}
            {...props}
        >
            <RadioGroupPrimitive.Indicator className="flex items-center justify-center text-current">
                <svg
                    width="6"
                    height="6"
                    viewBox="0 0 6 6"
                    fill="currentcolor"
                    xmlns="http://www.w3.org/2000/svg"
                >
                    <circle cx="3" cy="3" r="3" />
                </svg>
            </RadioGroupPrimitive.Indicator>
        </RadioGroupPrimitive.Item>
    );
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
 
export { RadioGroup, RadioGroupItem };

Import and use the radio-group component in your application.

import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
 
export default function RadioDemo() {
    return (
        <RadioGroup defaultValue="r1">
            <div className="flex items-center gap-2">
                <RadioGroupItem value="r1" id="radio-01-r1" />
                <Label htmlFor="radio-01-r1">Option 1</Label>
            </div>
            <div className="flex items-center gap-2">
                <RadioGroupItem value="r2" id="radio-01-r2" />
                <Label htmlFor="radio-01-r2">Option 2</Label>
            </div>
            <div className="flex items-center gap-2">
                <RadioGroupItem value="r3" id="radio-01-r3" />
                <Label htmlFor="radio-01-r3">Option 3</Label>
            </div>
        </RadioGroup>
    );
}

Examples

Default

Horizontal radio group

Tabs

You can use this card with a label and a description.

You can use this card with a label and a description.

Radion group w/ description

You can use this card with a label and a description.

You can use this card with a label and a description.

Feedback

How did it go?