# Switch 开关 · HeroUI

> 用于布尔状态的开关组件。

- 页面: https://jiguang132.com/zh/systems/heroui/docs/components/switch
- 改编自: HeroUI 文档 (Apache-2.0) @ 60edd8ed751b1d2a270623fbb182bbcfa8baa9af

## 引入

```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';
```

### 用法


> 示例 `switch-basic`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 组件结构

引入 Switch 组件，并通过点语法访问各部分。

```tsx
import { Switch, Description, FieldError } from '@heroui/react';

export default () => (
  <Switch>
    <Switch.Content>
      <Switch.Control>
        <Switch.Thumb>
          <Switch.Icon /> {/* 可选 */}
        </Switch.Thumb>
      </Switch.Control>
      Label {/* 纯文本 —— 可点击的标签，同时作为无障碍名称 */}
    </Switch.Content>
    <Description /> {/* 可选 — 字段级帮助文本 */}
    <FieldError /> {/* 可选 — 校验错误信息 */}
  </Switch>
);
```

要对多个 Switch 进行分组，请使用 `SwitchGroup` 组件：

```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';

export default () => (
  <SwitchGroup>
    <Switch>
      <Switch.Content>
        <Switch.Control>
          <Switch.Thumb />
        </Switch.Control>
        Option 1
      </Switch.Content>
    </Switch>
    <Switch>
      <Switch.Content>
        <Switch.Control>
          <Switch.Thumb />
        </Switch.Control>
        Option 2
      </Switch.Content>
    </Switch>
  </SwitchGroup>
);
```

### 禁用


> 示例 `switch-disabled`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 默认选中


> 示例 `switch-default-selected`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 受控


> 示例 `switch-controlled`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 无标签


> 示例 `switch-without-label`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 尺寸


> 示例 `switch-sizes`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 标签位置


> 示例 `switch-label-position`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 带图标


> 示例 `switch-with-icons`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 带描述


> 示例 `switch-with-description`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 分组


> 示例 `switch-group`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 横向分组


> 示例 `switch-group-horizontal`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### Render Props


> 示例 `switch-render-props`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 表单集成


> 示例 `switch-form`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 自定义样式


> 示例 `switch-custom-styles`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


### 自定义渲染函数


> 示例 `switch-custom-render-function`: 交互预览见 https://jiguang132.com/zh/systems/heroui/docs/components/switch


## 样式

### 传入 Tailwind CSS 类

你可以自定义各个 Switch：

```tsx
import { Switch, Label } from '@heroui/react';

function CustomSwitch() {
  return (
    <Switch>
      {({isSelected}) => (
        <>
          <Switch.Control
            className={`h-[31px] w-[51px] bg-blue-500 ${isSelected ? "bg-cyan-500 shadow-[0_0_12px_rgba(6,182,212,0.5)]" : ""}`}
          >
            <Switch.Thumb
              className={`size-[27px] bg-white shadow-sm ${isSelected ? "translate-x-5 shadow-lg" : ""}`}
            />
          </Switch.Control>
          Custom Switch
        </>
      )}
    </Switch>
  );
}
```

或自定义 SwitchGroup 布局：

```tsx
import { Switch, SwitchGroup, Label } from '@heroui/react';

function CustomSwitchGroup() {
  return (
    <SwitchGroup className="gap-8" orientation="horizontal">
      <Switch>
        <Switch.Content>
          <Switch.Control>
            <Switch.Thumb />
          </Switch.Control>
          Option 1
        </Switch.Content>
      </Switch>
      <Switch>
        <Switch.Content>
          <Switch.Control>
            <Switch.Thumb />
          </Switch.Control>
          Option 2
        </Switch.Content>
      </Switch>
    </SwitchGroup>
  );
}
```

### 自定义组件类

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

```css
@layer components {
  .switch {
    @apply inline-flex gap-3 items-center;
  }

  .switch__control {
    @apply h-5 w-8 bg-gray-400 data-[selected=true]:bg-blue-500;
  }

  .switch__thumb {
    @apply bg-white shadow-sm;
  }

  .switch__content {
    @apply items-center gap-3;
  }

  .switch__icon {
    @apply h-3 w-3 text-current;
  }
}
```

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

### CSS 类

#### Switch 类

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

- `.switch` - Switch 根容器（字段）
- `.switch__content` - 包裹控件与标签文本的可点击 label
- `.switch__control` - Switch 轨道
- `.switch__thumb` - 可移动的滑块
- `.switch__icon` - 滑块内可选图标
- `.switch--sm` - 小尺寸变体
- `.switch--md` - 中尺寸变体（默认）
- `.switch--lg` - 大尺寸变体

#### SwitchGroup 类

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

- `.switch-group` - Switch 组容器
- `.switch-group__items` - Switch 项容器
- `.switch-group--horizontal` - 横向布局
- `.switch-group--vertical` - 纵向布局（默认）

### 交互状态

该 Switch 同时支持 CSS 伪类与 data 属性，以提供更灵活的状态控制：

- **已选中**：`[data-selected="true"]`（滑块位置与背景色变化）
- **悬停**：`:hover` 或 `[data-hovered="true"]`（作用于 `Switch.Control` / 按钮）
- **聚焦**：`:focus-visible` 或 `[data-focus-visible="true"]`（在按钮上显示轨道焦点环）
- **禁用**：`[data-disabled="true"]`（降低透明度，包括帮助文本）
- **按压**：`:active` 或 `[data-pressed="true"]`

## API 参考

### Switch Props

继承自 [React Aria SwitchField](https://react-spectrum.adobe.com/react-aria/Switch.html)。

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Switch 尺寸。 |
| `isSelected` | `boolean` | `false` | Switch 是否打开。 |
| `defaultSelected` | `boolean` | `false` | 默认是否打开（非受控）。 |
| `isDisabled` | `boolean` | `false` | Switch 是否禁用。 |
| `isInvalid` | `boolean` | `false` | Switch 是否无效。 |
| `isReadOnly` | `boolean` | `false` | Switch 是否只读。 |
| `isRequired` | `boolean` | `false` | Switch 是否必须打开。 |
| `validate` | `(value: boolean) => ValidationError \| true \| null \| undefined` | - | 自定义校验函数。 |
| `validationBehavior` | `'native' \| 'aria'` | `'native'` | 使用原生 HTML 校验或 ARIA 校验。 |
| `name` | `string` | - | 输入元素名称，用于提交 HTML 表单。 |
| `value` | `string` | - | 输入元素值，用于提交 HTML 表单。 |
| `onChange` | `(isSelected: boolean) => void` | - | Switch 值变化时的事件处理函数。 |
| `onPress` | `(e: PressEvent) => void` | - | Switch 被按下时的事件处理函数。 |
| `children` | `React.ReactNode \| (values: SwitchFieldRenderProps) => React.ReactNode` | - | Switch 内容或字段级渲染 prop。 |
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, SwitchFieldRenderProps>` | - | 使用自定义渲染函数覆盖默认 DOM 元素。|

### Switch.Content Props

包裹控件与标签文本的可点击 `<label>`。请把 `Switch.Control` 与 `Label` 放在它内部；`Description`/`FieldError` 作为 `Switch.Content` 的兄弟节点。对于没有标签的 switch，省略 `Label` 并在 `Switch` 上传入 `aria-label`。

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `children` | `React.ReactNode \| (values: SwitchButtonRenderProps) => React.ReactNode` | - | 按钮内容（控件 + 标签），或按钮级渲染 prop |
| `className` | `string \| (values: SwitchButtonRenderProps) => string` | - | 应用到可点击 label 的类名 |

### SwitchFieldRenderProps

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

| Prop | 类型 | 描述 |
|------|------|------|
| `isSelected` | `boolean` | Switch 当前是否打开。 |
| `isDisabled` | `boolean` | Switch 是否禁用。 |
| `isReadOnly` | `boolean` | Switch 是否只读。 |
| `isInvalid` | `boolean` | Switch 是否无效。 |
| `isRequired` | `boolean` | Switch 是否必填。 |
| `state` | `ToggleState` | Switch 的状态。 |

### SwitchButtonRenderProps

`Switch.Control` 使用按钮级渲染 prop（`isHovered`、`isPressed`、`isFocusVisible` 等）。将函数作为 `Switch.Control` 的子元素即可访问。

### SwitchGroup Props

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | Switch 组方向。 |
| `children` | `React.ReactNode` | - | 要渲染的 Switch 项。 |
| `className` | `string` | - | 额外的 CSS 类。 |

---

JGuang 全部资源索引: https://jiguang132.com/llms.txt
