Radio Group

Radio Group

A set of mutually exclusive radio buttons built on Base UI. Three sizes, with automatic invalid styling inside a Field.

Playground

size
options
disabled
<RadioGroup defaultValue="option-1">
  <div className="flex items-center gap-4">
    <RadioGroupItem value="option-1" />
    <RadioGroupItem value="option-2" />
  </div>
</RadioGroup>

Preview

Wrap RadioGroupItems in a RadioGroup and give each a value. Use defaultValue for the initial selection.

<RadioGroup defaultValue="option-1">
  <div className="flex items-center gap-4">
    <RadioGroupItem value="option-1" />
    <RadioGroupItem value="option-2" />
  </div>
</RadioGroup>

Installation

npx shadcn@latest add https://espresso-base-ui.vercel.app/r/radio-group.json

Usage

import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
<RadioGroup defaultValue="comfortable" onValueChange={(value) => console.log(value)}>
  <RadioGroupItem value="compact" />
  <RadioGroupItem value="comfortable" />
</RadioGroup>

Sizes

size on the item scales the circle and its dot: xs (13px), sm (14px) and default (16px).

<RadioGroup defaultValue="a">
  <RadioGroupItem size="xs" value="a" />
  <RadioGroupItem size="xs" value="b" />
</RadioGroup>

<RadioGroup defaultValue="a">
  <RadioGroupItem size="sm" value="a" />
  <RadioGroupItem size="sm" value="b" />
</RadioGroup>

<RadioGroup defaultValue="a">
  <RadioGroupItem value="a" />
  <RadioGroupItem value="b" />
</RadioGroup>

Disabled

Set disabled on the group (or a single item) – items become non-interactive with muted checked and unchecked styling.

<RadioGroup defaultValue="dis-2" disabled>
  <div className="flex items-center gap-4">
    <RadioGroupItem value="dis-1" />
    <RadioGroupItem value="dis-2" />
  </div>
</RadioGroup>

Invalid

Set data-invalid="true" on an item for a destructive border and ring – or place the group inside a Field data-invalid="true" and every item inherits the invalid styling from the field context.

<RadioGroup value="">
  <RadioGroupItem data-invalid="true" value="inv-1" />
</RadioGroup>

<RadioGroup value="inv-2">
  <RadioGroupItem data-invalid="true" value="inv-2" />
</RadioGroup>

API reference

RadioGroup wraps the Base UI radio group and accepts all of its props; RadioGroupItem wraps the radio root and renders its own indicator dot. Both accept className.

RadioGroup

PropTypeDefaultDescription
valuestring–Controlled value of the selected item.
defaultValuestring–Initially selected value when uncontrolled.
onValueChange(value, eventDetails) => void–Called when the selection changes.
disabledbooleanfalseDisables every item in the group.
namestring–Name submitted with the owning form (renders a hidden input).

RadioGroupItem

PropTypeDefaultDescription
valuestring–The value this radio represents within the group. Required.
size"xs" | "sm" | "default""default"Circle size – 13px, 14px or 16px, with a matching indicator dot.
disabledbooleanfalseDisables this item only.
data-invalidstring–Set to "true" for destructive border and ring styling on this item.
ComponentDescription
RadioGroupGroup container (data-slot="radio-group"), rendered with role="radiogroup" and a grid gap-2 layout.
RadioGroupItemThe radio control (data-slot="radio-group-item", role="radio"). Reflects size as data-size and state as data-checked / data-unchecked / data-disabled. Includes an enlarged invisible hit area.

Accessibility & styling hooks

Base UI provides the radiogroup/radio roles with arrow-key navigation between items, and a hidden input for form submission when name is set. Style against the state attributes – data-checked, data-unchecked, data-disabled, data-invalid and data-size – or reuse the exported radioGroupItemVariants cva helper for custom radio surfaces.

Search documentation

Search the component docs