shadcn.io is not affiliated with official shadcn/ui
Shadcn Radio Group for React and Tailwind
Allows single selection from multiple options.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/radio-group.jsonpnpm dlx shadcn@latest add https://kit.dev/r/radio-group.jsonnpx shadcn@latest add https://kit.dev/r/radio-group.jsonyarn shadcn@latest add https://kit.dev/r/radio-group.json<Step>This component depends on Field. Install it first if you haven't already.</Step>
Install the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactCopy and paste the following code into your project.
"use client";
import {
RadioGroup as ArkRadioGroup,
useRadioGroupContext,
} from "@ark-ui/react/radio-group";
import type React from "react";
import { cn } from "@/lib/utils";
import { FieldLabel } from "@/components/ui/field";
export const useRadioGroup = useRadioGroupContext;
export const RadioGroup = (
props: React.ComponentProps<typeof ArkRadioGroup.Root>
) => {
const { className, children, ...rest } = props;
return (
<ArkRadioGroup.Root
className={cn(
"flex flex-col gap-3",
"data-invalid:text-destructive dark:data-invalid:text-destructive-foreground",
className
)}
data-slot="radio-group"
{...rest}
>
{children}
</ArkRadioGroup.Root>
);
};
export const RadioGroupItem = (
props: React.ComponentProps<typeof ArkRadioGroup.Item>
) => {
const { tabIndex, className, children, ...rest } = props;
return (
<ArkRadioGroup.Item
className={cn(
"inline-flex items-center gap-2",
"data-disabled:opacity-64",
className
)}
data-slot="radio-group-item"
{...rest}
>
<ArkRadioGroup.ItemControl
className={cn(
"relative",
"inline-flex shrink-0 items-center justify-center",
"size-4",
"border border-input shadow-xs/5",
"bg-input/30",
"rounded-full",
"before:size-1.5 before:rounded-full",
"data-focus-visible:border-primary data-focus-visible:ring-[3px] data-focus-visible:ring-ring/32 data-focus-visible:ring-offset-1 data-focus-visible:ring-offset-background",
"data-focus-visible:data-invalid:border-destructive/64 data-focus-visible:data-invalid:ring-destructive/48",
"data-invalid:border-destructive data-invalid:text-destructive data-invalid:ring-[3px] data-invalid:ring-destructive/24",
"dark:data-invalid:border-destructive-foreground dark:data-invalid:text-destructive dark:data-invalid:ring-[3px] dark:data-invalid:ring-destructive-foreground/20",
"data-[state=checked]:bg-primary data-[state=checked]:before:bg-primary-foreground",
"data-invalid:data-[state=checked]:bg-transparent data-invalid:data-[state=checked]:before:bg-destructive-foreground"
)}
data-slot="radio-group-item-control"
/>
<RadioGroupText>{children}</RadioGroupText>
<ArkRadioGroup.ItemHiddenInput tabIndex={tabIndex} />
</ArkRadioGroup.Item>
);
};
export const RadioGroupText = (
props: React.ComponentProps<typeof ArkRadioGroup.ItemText>
) => {
const { className, children, ...rest } = props;
return (
<FieldLabel asChild>
<ArkRadioGroup.ItemText data-slot="radio-group-item-text" {...rest}>
{children}
</ArkRadioGroup.ItemText>
</FieldLabel>
);
};
export const RadioGroupLabel = (
props: React.ComponentProps<typeof ArkRadioGroup.Label>
) => {
const { children, ...rest } = props;
return (
<FieldLabel asChild>
<ArkRadioGroup.Label data-slot="radio-group-label" {...rest}>
{children}
</ArkRadioGroup.Label>
</FieldLabel>
);
};Update the import paths to match your project setup.
Anatomy
RadioGroup
└── RadioGroupItemUsage
import {
RadioGroup,
RadioGroupItem,
} from "@/components/ui/radio-group";<RadioGroup>
<RadioGroupItem value="item-1">{/* label */}</RadioGroupItem>
<RadioGroupItem value="item-2">{/* label */}</RadioGroupItem>
</RadioGroup>Controlled
Use the value and onValueChange props to control the radio group.
States
Invalid
Use the invalid prop on RadioGroup to indicate an invalid state.
Disabled
Use the disabled on RadioGroup to disable all the radio group items or on RadioGroupItem to disable a single item.
Examples
With Description
Use FieldDescription to add a description to the radio group.
Card Style
Use FieldLabel to wrap the entire Field for a clickable card-style selection.
API Reference
RadioGroup
Root component. Manages single selection from options.
| Prop | Type | Default |
|---|---|---|
value | string | - |
defaultValue | string | - |
disabled | boolean | false |
name | string | - |
onValueChange | (details: ValueChangeDetails) => void | - |
className | string | - |
RadioGroupItem
Single radio option. Use value for selection.
| Prop | Type | Default |
|---|---|---|
value | string | - |
disabled | boolean | false |
invalid | boolean | false |
className | string | - |
For a complete list of props, see the Ark UI documentation.