- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Card
- Checkbox
- Collapsible
- Combobox
- Context Menu
- Date Picker (Lite)
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP (Lite)
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupDemo() {
return (
<RadioGroup defaultValue="comfortable" class="w-fit">
<div class="flex items-center gap-3">
<RadioGroupItem value="default" id="r1" />
<Label for="r1">Default</Label>
</div>
<div class="flex items-center gap-3">
<RadioGroupItem value="comfortable" id="r2" />
<Label for="r2">Comfortable</Label>
</div>
<div class="flex items-center gap-3">
<RadioGroupItem value="compact" id="r3" />
<Label for="r3">Compact</Label>
</div>
</RadioGroup>
)
}Installation
pnpm dlx shadcnui-hono-jsx@latest add radio-groupnpx shadcnui-hono-jsx@latest add radio-groupyarn dlx shadcnui-hono-jsx@latest add radio-groupbunx shadcnui-hono-jsx@latest add radio-groupUsage
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"<RadioGroup defaultValue="option-one">
<div class="flex items-center gap-3">
<RadioGroupItem value="option-one" id="option-one" />
<Label for="option-one">Option One</Label>
</div>
<div class="flex items-center gap-3">
<RadioGroupItem value="option-two" id="option-two" />
<Label for="option-two">Option Two</Label>
</div>
</RadioGroup>Composition
Use the following composition to build a RadioGroup:
RadioGroup
├── RadioGroupItem
└── RadioGroupItemDescription
Radio group items with a description using the Field component.
Standard spacing for most use cases.
More space between elements.
Minimal spacing for dense layouts.
import {
Field,
FieldContent,
FieldDescription,
FieldLabel,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupDescription() {
return (
<RadioGroup defaultValue="comfortable" class="w-fit">
<Field orientation="horizontal">
<RadioGroupItem value="default" id="desc-r1" />
<FieldContent>
<FieldLabel for="desc-r1">Default</FieldLabel>
<FieldDescription>
Standard spacing for most use cases.
</FieldDescription>
</FieldContent>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="comfortable" id="desc-r2" />
<FieldContent>
<FieldLabel for="desc-r2">Comfortable</FieldLabel>
<FieldDescription>More space between elements.</FieldDescription>
</FieldContent>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="compact" id="desc-r3" />
<FieldContent>
<FieldLabel for="desc-r3">Compact</FieldLabel>
<FieldDescription>
Minimal spacing for dense layouts.
</FieldDescription>
</FieldContent>
</Field>
</RadioGroup>
)
}Choice Card
Use FieldLabel to wrap the entire Field for a clickable card-style selection.
import {
Field,
FieldContent,
FieldDescription,
FieldLabel,
FieldTitle,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupChoiceCard() {
return (
<RadioGroup defaultValue="plus" class="max-w-sm">
<FieldLabel for="plus-plan">
<Field orientation="horizontal">
<FieldContent>
<FieldTitle>Plus</FieldTitle>
<FieldDescription>
For individuals and small teams.
</FieldDescription>
</FieldContent>
<RadioGroupItem value="plus" id="plus-plan" />
</Field>
</FieldLabel>
<FieldLabel for="pro-plan">
<Field orientation="horizontal">
<FieldContent>
<FieldTitle>Pro</FieldTitle>
<FieldDescription>For growing businesses.</FieldDescription>
</FieldContent>
<RadioGroupItem value="pro" id="pro-plan" />
</Field>
</FieldLabel>
<FieldLabel for="enterprise-plan">
<Field orientation="horizontal">
<FieldContent>
<FieldTitle>Enterprise</FieldTitle>
<FieldDescription>
For large teams and enterprises.
</FieldDescription>
</FieldContent>
<RadioGroupItem value="enterprise" id="enterprise-plan" />
</Field>
</FieldLabel>
</RadioGroup>
)
}Fieldset
Use FieldSet and FieldLegend to group radio items with a label and description.
import {
Field,
FieldDescription,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupFieldset() {
return (
<FieldSet class="w-full max-w-xs">
<FieldLegend variant="label">Subscription Plan</FieldLegend>
<FieldDescription>
Yearly and lifetime plans offer significant savings.
</FieldDescription>
<RadioGroup defaultValue="monthly">
<Field orientation="horizontal">
<RadioGroupItem value="monthly" id="plan-monthly" />
<FieldLabel for="plan-monthly" class="font-normal">
Monthly ($9.99/month)
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="yearly" id="plan-yearly" />
<FieldLabel for="plan-yearly" class="font-normal">
Yearly ($99.99/year)
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="lifetime" id="plan-lifetime" />
<FieldLabel for="plan-lifetime" class="font-normal">
Lifetime ($299.99)
</FieldLabel>
</Field>
</RadioGroup>
</FieldSet>
)
}Disabled
Use the disabled prop on RadioGroup to disable all items.
import { Field, FieldLabel } from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupDisabled() {
return (
<RadioGroup defaultValue="option2" class="w-fit">
<Field orientation="horizontal" data-disabled>
<RadioGroupItem value="option1" id="disabled-1" disabled />
<FieldLabel for="disabled-1" class="font-normal">
Disabled
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="option2" id="disabled-2" />
<FieldLabel for="disabled-2" class="font-normal">
Option 2
</FieldLabel>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="option3" id="disabled-3" />
<FieldLabel for="disabled-3" class="font-normal">
Option 3
</FieldLabel>
</Field>
</RadioGroup>
)
}Invalid
Use aria-invalid on RadioGroupItem and data-invalid on Field to show validation errors.
import {
Field,
FieldDescription,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
export function RadioGroupInvalid() {
return (
<FieldSet class="w-full max-w-xs">
<FieldLegend variant="label">Notification Preferences</FieldLegend>
<FieldDescription>
Choose how you want to receive notifications.
</FieldDescription>
<RadioGroup defaultValue="email">
<Field orientation="horizontal" data-invalid>
<RadioGroupItem value="email" id="invalid-email" aria-invalid />
<FieldLabel for="invalid-email" class="font-normal">
Email only
</FieldLabel>
</Field>
<Field orientation="horizontal" data-invalid>
<RadioGroupItem value="sms" id="invalid-sms" aria-invalid />
<FieldLabel for="invalid-sms" class="font-normal">
SMS only
</FieldLabel>
</Field>
<Field orientation="horizontal" data-invalid>
<RadioGroupItem value="both" id="invalid-both" aria-invalid />
<FieldLabel for="invalid-both" class="font-normal">
Both Email & SMS
</FieldLabel>
</Field>
</RadioGroup>
</FieldSet>
)
}RTL
To enable RTL support in shadcn/ui, see the RTL configuration guide.
Standard spacing for most use cases.
More space between elements.
Minimal spacing for dense layouts.
تباعد قياسي لمعظم حالات الاستخدام.
مساحة أكبر بين العناصر.
تباعد أدنى للتخطيطات الكثيفة.
ריווח סטנדרטי לרוב מקרי השימוש.
יותר מקום בין האלמנטים.
ריווח מינימלי לפריסות צפופות.
// This example sets dir and uses useTranslation because this site is not RTL.
// In an RTL app you won't need them; see the RTL guide.
import {
type Translations,
useTranslation,
} from "@/components/language-selector"
import {
Field,
FieldContent,
FieldDescription,
FieldLabel,
} from "@/components/ui/field"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
const translations: Translations = {
en: {
dir: "ltr",
values: {
default: "Default",
defaultDescription: "Standard spacing for most use cases.",
comfortable: "Comfortable",
comfortableDescription: "More space between elements.",
compact: "Compact",
compactDescription: "Minimal spacing for dense layouts.",
},
},
ar: {
dir: "rtl",
values: {
default: "افتراضي",
defaultDescription: "تباعد قياسي لمعظم حالات الاستخدام.",
comfortable: "مريح",
comfortableDescription: "مساحة أكبر بين العناصر.",
compact: "مضغوط",
compactDescription: "تباعد أدنى للتخطيطات الكثيفة.",
},
},
he: {
dir: "rtl",
values: {
default: "ברירת מחדל",
defaultDescription: "ריווח סטנדרטי לרוב מקרי השימוש.",
comfortable: "נוח",
comfortableDescription: "יותר מקום בין האלמנטים.",
compact: "קומפקטי",
compactDescription: "ריווח מינימלי לפריסות צפופות.",
},
},
}
export function RadioGroupRtl() {
const { dir, t } = useTranslation(translations, "ar")
return (
<RadioGroup defaultValue="comfortable" class="w-fit" dir={dir}>
<Field orientation="horizontal">
<RadioGroupItem value="default" id="r1-rtl" dir={dir} />
<FieldContent>
<FieldLabel for="r1-rtl" dir={dir}>
{t.default}
</FieldLabel>
<FieldDescription dir={dir}>{t.defaultDescription}</FieldDescription>
</FieldContent>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="comfortable" id="r2-rtl" dir={dir} />
<FieldContent>
<FieldLabel for="r2-rtl" dir={dir}>
{t.comfortable}
</FieldLabel>
<FieldDescription dir={dir}>
{t.comfortableDescription}
</FieldDescription>
</FieldContent>
</Field>
<Field orientation="horizontal">
<RadioGroupItem value="compact" id="r3-rtl" dir={dir} />
<FieldContent>
<FieldLabel for="r3-rtl" dir={dir}>
{t.compact}
</FieldLabel>
<FieldDescription dir={dir}>{t.compactDescription}</FieldDescription>
</FieldContent>
</Field>
</RadioGroup>
)
}Notes
value/defaultValueset the initial selection;onValueChangeandreadOnlyare not supported.- Built on native
<input type="radio">elements sharing the group'sname(generated unless given): no JavaScript, arrow keys move the selection, and the value is submitted with forms.id,disabledandaria-*go to the input. - Accepts
classinstead ofclassName. - Upstream documentation: shadcn/ui Radio Group. See also Differences from shadcn/ui.
API Reference
See the Base UI Radio Group documentation.