组件
切换按钮 Toggle
用于在激活(On)与未激活(Off)两种双态之间切换并持久保持状态的轻量级动作按钮。
基础用法
最简单的切换按钮。点击切换文字粗体属性并保持激活高亮状态:
Loading…
安装与引入
通过 CLI 自动添加组件,或手动复制源码至项目中:
pnpm dlx @wui-design/cli@latest add @wui/toggle安装基础依赖
pnpm add radix-ui class-variance-authority clsx tailwind-merge复制组件源码到
components/ui/toggle.tsx"use client"
import * as React from "react"
import { Toggle as TogglePrimitive } from "radix-ui"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const toggleVariants = cva(
"hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/30 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium outline-none transition-[color,background-color,border-color,box-shadow,scale] duration-200 ease-out active:scale-[0.96] motion-reduce:active:scale-100 focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "border border-transparent",
outline: "border-input bg-background shadow-xs border",
},
size: {
sm: "h-8 min-w-8 px-2",
default: "h-9 min-w-9 px-2.5",
lg: "h-10 min-w-10 px-3",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ToggleProps
extends
React.ComponentProps<typeof TogglePrimitive.Root>,
VariantProps<typeof toggleVariants> {}
/** 表示可保持开启或关闭状态的双态按钮。 */
function Toggle({
className,
variant = "default",
size = "default",
...props
}: ToggleProps) {
return (
<TogglePrimitive.Root
data-slot="toggle"
className={cn(toggleVariants({ variant, size }), className)}
{...props}
/>
)
}
export { Toggle, toggleVariants }
属性 Props
Toggle 支持以下配置属性,并继承 Radix UI TogglePrimitive.Root 的全部 HTML 按钮属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| pressed | boolean | — | 受控模式下的当前激活按下状态。 |
| defaultPressed | boolean | false | 非受控模式下的初始激活状态。 |
| onPressedChange | (pressed: boolean) => void | — | 切换按钮状态改变时触发的回调函数,返回最新的布尔值。 |
| variant | "default" | "outline" | "default" | 按钮的视觉外观风格。'outline' 提供边界框与背景底色。 |
| size | "sm" | "default" | "lg" | "default" | 切换按钮的物理尺寸密度。 |
| disabled | boolean | false | 是否禁用按钮的交互与焦点。 |
| aria-label | string | — | 纯图标模式下必须提供的无障碍文本标签。 |
| className | string | — | 应用于切换按钮的额外 CSS 类名。 |
事件 Events
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| onPressedChange | (pressed: boolean) => void | — | 当用户通过点击、触摸或按键(Space / Enter)改变切换按钮状态时触发。 |
| onFocus | (event: React.FocusEvent<HTMLButtonElement>) => void | — | 按钮获得焦点时触发。 |
| onBlur | (event: React.FocusEvent<HTMLButtonElement>) => void | — | 按钮失去焦点时触发。 |
使用场景与设计规范
Toggle 适用于状态持续保持的双态独立开关(如富文本加粗/斜体、收藏加星、窗口置顶、麦克风静音)。
- Toggle vs Button vs Switch:
- Toggle(切换按钮):以紧凑按钮形式呈现,激活后保持高亮按下状态,适合工具栏或快捷栏。
- Button(普通按钮):即点即走,触发一次性动作(如“提交”、“下载”),不保留选中状态。
- Switch(开关):具备滑动轨道的物理开关视觉,适合具有强二元开启/关闭含义的设置项。
- 纯图标无障碍要求:若
Toggle内部仅包含图标而无文字,必须显式提供aria-label(如aria-label="切换粗体"),确保屏幕阅读器用户能明确理解操作意图。
场景示例
收藏加星与业务状态
在内容流中用作收藏(Bookmark)和标星(Star)切换,支持自定义激活状态下的高亮色系,激活时图标轻微弹跳反馈:
Loading…
音视频会议控制
在会议控制栏中切换麦克风与摄像头,图标以旋转缩放的方式交叉切换。纯图标 Toggle 的 aria-label 应保持稳定,由 aria-pressed 表达当前状态:
Loading…
尺寸与外观风格
提供 sm、default、lg 三种尺寸,支持无边框默认风格与 outline 带边框风格:
Loading…
无障碍与交互 Accessibility
- ARIA 规范:底层基于 Radix UI Toggle,自动挂载
role="button"与aria-pressed="true|false"属性,清晰表达按压状态。 - 键盘导航:
- Tab:按 DOM 顺序将焦点移动至切换按钮。
- Space / Enter:触发状态切换。
- 焦点环高亮:提供统一的高对比度
focus-visible:ring,确保键盘导航清晰可见。 - 按压反馈:按下时有轻微缩放(0.96),系统开启“减少动态效果”时自动关闭。