---
title: RadioGroup 单选框组
description: 用于从列表中选择单个选项的单选组。
icon: updated
links:
  rac: RadioField
  source: radio-group/radio-group.tsx
  styles: radio-group.css
  storybook: Components/Forms/RadioGroup
---

## 用法

```tsx
import { RadioGroup, Radio } from '@heroui/react';
```

<ComponentPreview
  name="radio-group-basic"
/>

## 组件结构

导入 RadioGroup 组件后，可通过点号访问各个子部分。

```tsx
import {RadioGroup, Radio, Label, Description, FieldError} from '@heroui/react';

export default () => (
  <RadioGroup>
    <Label />
    <Description />
    <Radio value="option1">
      <Radio.Content> {/* 可点击区域：control + label */}
        <Radio.Control>
          <Radio.Indicator>
            <span>✓</span> {/* Custom indicator (optional) */}
          </Radio.Indicator>
        </Radio.Control>
        Label {/* 纯文本 —— 可点击的标签 */}
      </Radio.Content>
      <Description /> {/* 兄弟节点 — 位于按钮外部（通过 aria-describedby 关联） */}
      <FieldError /> {/* 可选 — 单选项校验错误信息 */}
    </Radio>
    <FieldError /> {/* 可选 — 组级校验 */}
  </RadioGroup>
)
```

## 示例

### 水平排列

<ComponentPreview
  name="radio-group-horizontal"
/>

### 变体

RadioGroup 组件支持两种视觉变体：

- **`primary`**（默认）— 带默认背景的标准样式，适用于大多数场景
- **`secondary`** — 低强调变体，适合在 Surface 等表面背景上使用

<ComponentPreview name="radio-group-variants" />

### 表面样式

在 [Surface](/docs/components/surface) 内使用时，请使用 `variant="secondary"`，以应用适合表面背景的低强调变体。

<ComponentPreview
  name="radio-group-on-surface"
/>

### 禁用

<ComponentPreview
  name="radio-group-disabled"
/>

### 受控组件

<ComponentPreview
  name="radio-group-controlled"
/>

### 非受控

仅需响应更新时，将 `defaultValue` 与 `onChange` 配合使用。

<ComponentPreview
  name="radio-group-uncontrolled"
/>

### 表单校验

<ComponentPreview
  name="radio-group-validation"
/>

### 配送与支付

<ComponentPreview
  isBgSolid
  align="start"
  name="radio-group-delivery-and-payment"
/>

### 自定义指示器

<ComponentPreview
  name="radio-group-custom-indicator"
/>

### 渲染函数

<ComponentPreview
  name="radio-group-render-function"
/>

## 自定义样式

### Tailwind CSS

<ComponentPreview name="radio-group-custom-styles" />

### 全局 CSS

若要自定义组件类，可使用 `@layer components` 指令。[了解更多](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes)。

```css
@layer components {
  .radio-group {
    @apply gap-2;
  }

  .radio {
    @apply gap-4 rounded-lg border border-border p-3 hover:bg-surface-hovered;
  }

  .radio__control {
    @apply border-2 border-accent;
  }

  .radio__indicator {
    @apply bg-primary;
  }

  .radio__content {
    @apply gap-1;
  }
}
```

## 样式参考

HeroUI 遵循 [BEM](https://getbem.com/) 方法论，确保组件变体与状态可复用且易于自定义。

### CSS 类

RadioGroup 使用以下 CSS 类（[查看源码样式](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/radio-group.css)）：

#### 基础类 [!toc]
- `.radio-group` - 单选组基础容器
- `.radio` - 单个单选项
- `.radio__control` - 单选控件（圆形按钮）
- `.radio__indicator` - 单选指示器（内部圆点）
- `.radio__content` - 单选内容包裹层

#### 修饰类 [!toc]
- `.radio--disabled` - 禁用状态

### 交互状态

单选项同时支持 CSS 伪类与 data 属性，便于灵活定制：

- **Selected**：`[aria-checked="true"]` 或 `[data-selected="true"]`（显示指示器）
- **Hover**：`:hover` 或 `[data-hovered="true"]`（边框颜色变化）
- **Focus**：`:focus-visible` 或 `[data-focus-visible="true"]`（显示焦点环）
- **Pressed**：`:active` 或 `[data-pressed="true"]`（缩放变换）
- **Disabled**：`:disabled` 或 `[aria-disabled="true"]`（降低透明度并禁用指针事件）
- **Invalid**：`[data-invalid="true"]` 或 `[aria-invalid="true"]`（错误边框颜色）

## API 参考

### RadioGroup
| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `value` | `string` | - | 当前值（受控） |
| `defaultValue` | `string` | - | 默认值（非受控） |
| `onChange` | `(value: string) => void` | - | 值变化时触发的事件处理函数 |
| `isDisabled` | `boolean` | `false` | 是否禁用整个单选组 |
| `isRequired` | `boolean` | `false` | 是否必填 |
| `isReadOnly` | `boolean` | `false` | 是否只读 |
| `isInvalid` | `boolean` | `false` | 是否处于无效状态 |
| `variant` | `"primary" \| "secondary"` | `"primary"` | 组件的视觉变体。`primary` 为默认带阴影样式。`secondary` 为低强调、无阴影变体，适合用在 surface 上。 |
| `name` | `string` | - | 单选组的名称，用于提交 HTML 表单 |
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | 单选组的排列方向 |
| `children` | `React.ReactNode \| (values: RadioGroupRenderProps) => React.ReactNode` | - | 单选组内容或渲染 prop |
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioGroupRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|

### Radio
| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `value` | `string` | - | 单选项的值 |
| `isDisabled` | `boolean` | `false` | 是否禁用该单选项 |
| `name` | `string` | - | 单选项名称，用于提交 HTML 表单 |
| `children` | `React.ReactNode \| (values: RadioFieldRenderProps) => React.ReactNode` | - | 单选内容或字段级渲染 prop |
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, RadioFieldRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|

### Radio.Control
继承 `React.HTMLAttributes<HTMLSpanElement>`。

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `children` | `React.ReactNode` | - | 控件包裹层内要渲染的内容（通常为 Radio.Indicator） |

### Radio.Indicator
继承 `React.HTMLAttributes<HTMLSpanElement>`。

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | 可选内容或接收当前单选按钮状态的渲染 prop。 |

### Radio.Content
单选项的可点击区域（包裹隐藏 input 的 `<label>`）。请将 `Radio.Control` 与 `Label` 放在其中。`className` 支持接收 `RadioButtonRenderProps` 的渲染函数。

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `children` | `React.ReactNode \| (values: RadioButtonRenderProps) => React.ReactNode` | - | 可点击内容（通常为 Radio.Control 与 Label） |

### RadioFieldRenderProps

在根级 `Radio` 上使用渲染 prop 时，会提供以下字段级值：

| Prop | 类型 | 描述 |
|------|------|------|
| `isSelected` | `boolean` | 单选项是否已选中 |
| `isDisabled` | `boolean` | 是否禁用 |
| `isReadOnly` | `boolean` | 是否只读 |
| `isInvalid` | `boolean` | 是否无效 |
| `isRequired` | `boolean` | 是否必填 |

### RadioButtonRenderProps

`Radio.Control` 和 `Radio.Indicator` 使用按钮级渲染 prop（`isHovered`、`isPressed`、`isFocusVisible` 等）。将函数作为 `Radio.Control` 子节点或传给 `Radio.Indicator` 即可访问它们。

## 相关案例

<RelatedShowcases component="RadioGroup" />

## 相关组件

<RelatedComponents component="radiogroup" />