# 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.

Page: https://sui.draco.dev/docs/components/radio-group

### Example: radio-group-demo

```tsx
import { Label } from "@workspace/ui/components/label";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupDemo() {
  const previewId = usePreviewId();

  return (
    <RadioGroup defaultValue="comfortable" className="w-fit">
      <div className="flex items-center gap-3">
        <RadioGroupItem value="default" id={`${previewId}-r1`} />
        <Label htmlFor={`${previewId}-r1`}>Default</Label>
      </div>
      <div className="flex items-center gap-3">
        <RadioGroupItem value="comfortable" id={`${previewId}-r2`} />
        <Label htmlFor={`${previewId}-r2`}>Comfortable</Label>
      </div>
      <div className="flex items-center gap-3">
        <RadioGroupItem value="compact" id={`${previewId}-r3`} />
        <Label htmlFor={`${previewId}-r3`}>Compact</Label>
      </div>
    </RadioGroup>
  );
}

export default RadioGroupDemo;
```

## Installation

```bash
bunx --bun shadcn@latest add @sui/radio-group
```

Install with the shadcn CLI or use the shared `@workspace/ui` package. Follow the [installation guide](/docs/installation) to configure the registry, load styles, and choose import aliases.

## Usage

```tsx showLineNumbers
import { Label } from "@workspace/ui/components/label"
import { RadioGroup, RadioGroupItem } from "@workspace/ui/components/radio-group"
```

```tsx showLineNumbers
<RadioGroup defaultValue="option-one">
  <div className="flex items-center gap-3">
    <RadioGroupItem value="option-one" id="option-one" />
    <Label htmlFor="option-one">Option One</Label>
  </div>
  <div className="flex items-center gap-3">
    <RadioGroupItem value="option-two" id="option-two" />
    <Label htmlFor="option-two">Option Two</Label>
  </div>
</RadioGroup>
```

## Composition

Use the following composition to build a `RadioGroup`:

```text
RadioGroup
├── RadioGroupItem
└── RadioGroupItem
```

## Description

Radio group items with a description using the `Field` component.

### Example: radio-group-description

```tsx
import {
  Field,
  FieldContent,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupDescription() {
  const previewId = usePreviewId();

  return (
    <RadioGroup defaultValue="comfortable" className="w-fit">
      <Field orientation="horizontal">
        <RadioGroupItem value="default" id={`${previewId}-desc-r1`} />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-desc-r1`}>Default</FieldLabel>
          <FieldDescription>
            Standard spacing for most use cases.
          </FieldDescription>
        </FieldContent>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem value="comfortable" id={`${previewId}-desc-r2`} />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-desc-r2`}>Comfortable</FieldLabel>
          <FieldDescription>More space between elements.</FieldDescription>
        </FieldContent>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem value="compact" id={`${previewId}-desc-r3`} />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-desc-r3`}>Compact</FieldLabel>
          <FieldDescription>
            Minimal spacing for dense layouts.
          </FieldDescription>
        </FieldContent>
      </Field>
    </RadioGroup>
  );
}

export default RadioGroupDescription;
```

## Choice Card

Use `FieldLabel` to wrap the entire `Field` for a clickable card-style selection.

### Example: radio-group-choice-card

```tsx
import {
  Field,
  FieldContent,
  FieldDescription,
  FieldLabel,
  FieldTitle,
} from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupChoiceCard() {
  const previewId = usePreviewId();

  return (
    <RadioGroup defaultValue="plus" className="max-w-sm">
      <FieldLabel htmlFor={`${previewId}-plus-plan`}>
        <Field orientation="horizontal">
          <FieldContent>
            <FieldTitle>Plus</FieldTitle>
            <FieldDescription>
              For individuals and small teams.
            </FieldDescription>
          </FieldContent>
          <RadioGroupItem value="plus" id={`${previewId}-plus-plan`} />
        </Field>
      </FieldLabel>
      <FieldLabel htmlFor={`${previewId}-pro-plan`}>
        <Field orientation="horizontal">
          <FieldContent>
            <FieldTitle>Pro</FieldTitle>
            <FieldDescription>For growing businesses.</FieldDescription>
          </FieldContent>
          <RadioGroupItem value="pro" id={`${previewId}-pro-plan`} />
        </Field>
      </FieldLabel>
      <FieldLabel htmlFor={`${previewId}-enterprise-plan`}>
        <Field orientation="horizontal">
          <FieldContent>
            <FieldTitle>Enterprise</FieldTitle>
            <FieldDescription>
              For large teams and enterprises.
            </FieldDescription>
          </FieldContent>
          <RadioGroupItem
            value="enterprise"
            id={`${previewId}-enterprise-plan`}
          />
        </Field>
      </FieldLabel>
    </RadioGroup>
  );
}

export default RadioGroupChoiceCard;
```

## Fieldset

Use `FieldSet` and `FieldLegend` to group radio items with a label and description.

### Example: radio-group-fieldset

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupFieldset() {
  const previewId = usePreviewId();

  return (
    <FieldSet className="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={`${previewId}-plan-monthly`} />
          <FieldLabel
            htmlFor={`${previewId}-plan-monthly`}
            className="font-normal"
          >
            Monthly ($9.99/month)
          </FieldLabel>
        </Field>
        <Field orientation="horizontal">
          <RadioGroupItem value="yearly" id={`${previewId}-plan-yearly`} />
          <FieldLabel
            htmlFor={`${previewId}-plan-yearly`}
            className="font-normal"
          >
            Yearly ($99.99/year)
          </FieldLabel>
        </Field>
        <Field orientation="horizontal">
          <RadioGroupItem value="lifetime" id={`${previewId}-plan-lifetime`} />
          <FieldLabel
            htmlFor={`${previewId}-plan-lifetime`}
            className="font-normal"
          >
            Lifetime ($299.99)
          </FieldLabel>
        </Field>
      </RadioGroup>
    </FieldSet>
  );
}

export default RadioGroupFieldset;
```

## Disabled

Use the `disabled` prop on `RadioGroup` to disable all items.

### Example: radio-group-disabled

```tsx
import { Field, FieldLabel } from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupDisabled() {
  const previewId = usePreviewId();

  return (
    <RadioGroup defaultValue="option2" className="w-fit">
      <Field orientation="horizontal" data-disabled>
        <RadioGroupItem
          value="option1"
          id={`${previewId}-disabled-1`}
          disabled
        />
        <FieldLabel htmlFor={`${previewId}-disabled-1`} className="font-normal">
          Disabled
        </FieldLabel>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem value="option2" id={`${previewId}-disabled-2`} />
        <FieldLabel htmlFor={`${previewId}-disabled-2`} className="font-normal">
          Option 2
        </FieldLabel>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem value="option3" id={`${previewId}-disabled-3`} />
        <FieldLabel htmlFor={`${previewId}-disabled-3`} className="font-normal">
          Option 3
        </FieldLabel>
      </Field>
    </RadioGroup>
  );
}

export default RadioGroupDisabled;
```

## Invalid

Use `aria-invalid` on `RadioGroupItem` and `data-invalid` on `Field` to show validation errors.

### Example: radio-group-invalid

```tsx
import {
  Field,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";

export function RadioGroupInvalid() {
  const previewId = usePreviewId();

  return (
    <FieldSet className="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={`${previewId}-invalid-email`}
            aria-invalid
          />
          <FieldLabel
            htmlFor={`${previewId}-invalid-email`}
            className="font-normal"
          >
            Email only
          </FieldLabel>
        </Field>
        <Field orientation="horizontal" data-invalid>
          <RadioGroupItem
            value="sms"
            id={`${previewId}-invalid-sms`}
            aria-invalid
          />
          <FieldLabel
            htmlFor={`${previewId}-invalid-sms`}
            className="font-normal"
          >
            SMS only
          </FieldLabel>
        </Field>
        <Field orientation="horizontal" data-invalid>
          <RadioGroupItem
            value="both"
            id={`${previewId}-invalid-both`}
            aria-invalid
          />
          <FieldLabel
            htmlFor={`${previewId}-invalid-both`}
            className="font-normal"
          >
            Both Email & SMS
          </FieldLabel>
        </Field>
      </RadioGroup>
    </FieldSet>
  );
}

export default RadioGroupInvalid;
```

## RTL

To enable RTL support in shadcn/ui, see the [RTL configuration guide](https://ui.shadcn.com/docs/rtl).

### Example: radio-group-rtl

```tsx
"use client";

import {
  Field,
  FieldContent,
  FieldDescription,
  FieldLabel,
} from "@workspace/ui/components/field";
import {
  RadioGroup,
  RadioGroupItem,
} from "@workspace/ui/components/radio-group";
import { useId as usePreviewId } from "react";
import { type Translations, useTranslation } from "./support";

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 previewId = usePreviewId();

  const { dir, t } = useTranslation(translations, "ar");

  return (
    <RadioGroup defaultValue="comfortable" className="w-fit" dir={dir}>
      <Field orientation="horizontal">
        <RadioGroupItem value="default" id={`${previewId}-r1-rtl`} dir={dir} />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-r1-rtl`} dir={dir}>
            {t.default}
          </FieldLabel>
          <FieldDescription dir={dir}>{t.defaultDescription}</FieldDescription>
        </FieldContent>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem
          value="comfortable"
          id={`${previewId}-r2-rtl`}
          dir={dir}
        />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-r2-rtl`} dir={dir}>
            {t.comfortable}
          </FieldLabel>
          <FieldDescription dir={dir}>
            {t.comfortableDescription}
          </FieldDescription>
        </FieldContent>
      </Field>
      <Field orientation="horizontal">
        <RadioGroupItem value="compact" id={`${previewId}-r3-rtl`} dir={dir} />
        <FieldContent>
          <FieldLabel htmlFor={`${previewId}-r3-rtl`} dir={dir}>
            {t.compact}
          </FieldLabel>
          <FieldDescription dir={dir}>{t.compactDescription}</FieldDescription>
        </FieldContent>
      </Field>
    </RadioGroup>
  );
}

export default RadioGroupRtl;
```

## API Reference

See the [Base UI Radio Group](https://base-ui.com/react/components/radio-group#api-reference) documentation.

- [Documentation](https://base-ui.com/react/components/radio-group)
- [API reference](https://base-ui.com/react/components/radio-group#api-reference)
