代码演示
如何引入
import { Space, Switch, Typography } from '@fibrous/semi-ui-solid';
基本
你可以通过 onChange 监听状态变化,通过 defaultChecked 或受控的 checked 指定选中状态。
通过 aria-label 描述该 Switch 开关的具体作用
代码
import { Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
return (
<div>
<Switch onChange={(checked) => console.log(checked)} aria-label="a switch for demo" />
<br />
<Switch defaultChecked onChange={(checked) => console.log(checked)} aria-label="a switch for semi demo" />
</div>
);
}尺寸
你可以通过 size 指定尺寸
代码
import { Space, Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
return (
<div>
<Space style={{ 'margin-bottom': '10px', display: 'block' }}>
<Switch size="small" aria-label="a switch for demo" />
<Switch defaultChecked size="small" aria-label="a switch for demo" />
<Switch size="small" loading aria-label="a switch for demo" />
<Switch size="small" loading defaultChecked aria-label="a switch for demo" />
</Space>
<Space style={{ 'margin-bottom': '10px', display: 'block' }}>
<Switch aria-label="a switch for demo" />
<Switch defaultChecked aria-label="a switch for demo" />
<Switch loading aria-label="a switch for demo" />
<Switch loading defaultChecked aria-label="a switch for demo" />
</Space>
<Space>
<Switch size="large" aria-label="a switch for demo" />
<Switch defaultChecked size="large" aria-label="a switch for demo" />
<Switch size="large" loading aria-label="a switch for demo" />
<Switch size="large" loading defaultChecked aria-label="a switch for demo" />
</Space>
</div>
);
}不可用
代码
import { Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
return (
<div>
<Switch disabled aria-label="a switch for demo" />
<br />
<Switch disabled checked aria-label="a switch for demo" />
</div>
);
}带文本
可以通过 checkedText 与 uncheckedText 设置开关时的文本
注意:此项功能在最小的开关(即 size='small'时)无效
关
〇
开
|
关
〇
开
|
代码
import { Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
return (
<div>
<Switch aria-label="带开关文字的开关" checkedText="开" uncheckedText="关" />
<Switch aria-label="带符号文字的开关" checkedText="|" uncheckedText="〇" style={{ 'margin-left': '5px' }} />
<br />
<br />
<Switch aria-label="带开关文字的开关,已开启" defaultChecked checkedText="开" uncheckedText="关" />
<Switch aria-label="带符号文字的开关,已开启" defaultChecked checkedText="|" uncheckedText="〇" style={{ 'margin-left': '5px' }} />
<br />
<br />
<Switch aria-label="大号带开关文字的开关" checkedText="开" uncheckedText="关" size="large" />
<Switch aria-label="大号带符号文字的开关" checkedText="|" uncheckedText="〇" size="large" style={{ 'margin-left': '5px' }} />
<br />
<br />
<Switch aria-label="大号带开关文字的开关,已开启" defaultChecked checkedText="开" uncheckedText="关" size="large" />
<Switch aria-label="大号带符号文字的开关,已开启" defaultChecked checkedText="|" uncheckedText="〇" size="large" style={{ 'margin-left': '5px' }} />
</div>
);
}相比于通过 checkedText 与 uncheckedText 设置内嵌的文本,我们更推荐将文本说明放置在 Switch 外部
已关闭
代码
import { createSignal } from 'solid-js';
import { Switch, Typography } from '@fibrous/semi-ui-solid';
const { Title } = Typography;
export default function SwitchDemo() {
const [open, setOpen] = createSignal<boolean>();
return (
<div style={{ display: 'flex', 'align-items': 'center' }}>
<Title heading={6} style={{ margin: '8px' }}>
{open() ? '已开启' : '已关闭'}
</Title>
<Switch checked={open()} onChange={(value) => setOpen(value)} aria-label="a switch for demo" />
</div>
);
}受控组件
组件是否选中完全取决于传入的 checked 值,配合 onChange 回调函数使用。只传 checked 而不在回调中回写时,点击仅触发通知,显示由传入的值决定。
代码
import { createSignal } from 'solid-js';
import { Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
const [checked, setChecked] = createSignal(true);
return <Switch checked={checked()} aria-label="a switch for demo" onChange={(value) => setChecked(value)} />;
}加载中
可以通过设置 loading="true" 开启加载中状态。
代码
import { Switch } from '@fibrous/semi-ui-solid';
export default function SwitchDemo() {
return (
<div>
<Switch loading aria-label="Loading switch" />
<br />
<Switch loading defaultChecked aria-label="Loading switch, on" />
</div>
);
}API 参考
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| checked | 选中状态。不为 undefined 时为受控:显示由该值决定,点击只触发 onChange,需在回调中更新该值。变回 undefined 后取消选中并转为非受控。 | boolean | - |
| checkedText | 选中时展示的内容,size 为 small 时不显示。 | JSX.Element | - |
| defaultChecked | 非受控时的初始选中状态,只在首次渲染时读取。 | boolean | - |
| disabled | 是否禁用。 | boolean | false |
| loading | 是否处于加载中;加载中 input 仍可聚焦并带 aria-disabled,切换被忽略且不触发 onChange。 | boolean | false |
| name | 原生 input 的 name,用于表单提交。 | string | - |
| onBlur | 原生 input 失去焦点时的回调。焦点事件不冒泡,因此挂在 input 上。 | TypeJSX.EventHandlerUnion<HTMLInputElement, FocusEvent> | - |
| onChange | 切换状态时的回调,参数为新的选中状态与原生 change 事件;加载中不触发。 | Type(checked: boolean, event: Event & { currentTarget: HTMLInputElement; target: HTMLInputElement }) => void | - |
| onFocus | 原生 input 获得焦点时的回调。焦点事件不冒泡,因此挂在 input 上。 | TypeJSX.EventHandlerUnion<HTMLInputElement, FocusEvent> | - |
| size | 开关尺寸,可选 large、default 或 small。 | Size | "default" |
| uncheckedText | 未选中时展示的内容,size 为 small 时不显示。 | JSX.Element | - |
class、style、ref 与其他原生属性和事件(如 onMouseEnter)落在根元素上;id、name、tabIndex、autofocus、aria-*,以及 onFocus、onBlur 落在内部的原生 input 上。
Accessibility
ARIA
- Switch 内部的 input 具有
switchrole,开关状态由原生 input 的 checked 表达 - 作为表单控件应该带有 Label
- 使用
FormSwitch时 Label 会自动被带上;如果你单独使用 Switch,建议使用aria-label描述当前标签作用,或用aria-labelledby关联页面上的可见标签
键盘和焦点
- 键盘用户可以使用
Tab及Shift + Tab切换焦点 - 聚焦时可以通过
Space键切换开启或关闭状态
文案规范
- 开关描述
- 首字母大写,不需要标点符号
- 间接明了地说明该设置的开启或关闭状态
- 如果需要,解释给用户开启和关闭状态所代表的情况
设计变量
下表是组件内部的 Sass 变量,不能覆写。定制样式请覆写 --semi-* CSS 变量(见 Design Token 页),或写不分层的 CSS 规则。
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $transition_duration-switch-bg | 200ms | 开关-背景色-动画持续时间 |
| $transition_function-switch-bg | var(--semi-transition_function-easeIn) | 开关-背景色-过渡曲线 |
| $transition_delay-switch-bg | var(--semi-transition_delay-none) | 开关-背景色-延迟时间 |
| $spacing-switch_unchecked-translateX | 2px | 未选中态开关滑块位移距离 |
| $spacing-switch_spin_unchecked-translateX | 2px | 未选中态加载图标位移距离 |
| $spacing-switch_checked-translateX | 18px | 选中态开关滑块位移距离 |
| $spacing-switch_spin_checked-translateX | 16px | 选中态加载图标位移距离 |
| $spacing-switch_expand_large-translateX | 10px | |
| $spacing-switch_unchecked_large-translateX | 3px | 大尺寸未选中态开关滑块位移距离 |
| $spacing-switch_spin_unchecked_large-translateX | 2px | 大尺寸未选中态加载图标位移距离 |
| $spacing-switch_checked_large-translateX | 26px | 大尺寸选中态开关滑块位移距离 |
| $spacing-switch_spin_checked_large-translateX | 22px | 大尺寸选中态加载图标位移距离 |
| $spacing-switch_expand_small-translateX | 2px | |
| $spacing-switch_unchecked_small-translateX | 1px | 小尺寸未选中态开关滑块位移距离 |
| $spacing-switch_spin_unchecked_small-translateX | 2px | 小尺寸未选中态加载图标位移距离 |
| $spacing-switch_checked_small-translateX | 11px | 小尺寸选中态开关滑块位移距离 |
| $spacing-switch_spin_checked_small-translateX | 10px | 小尺寸选中态加载图标位移距离 |
| $motion-switch-transitionDuration | 200ms | 开关动画时长 |
| $color-switch_default-bg-default | var(--semi-color-fill-0) | 关闭态(未选中)开关背景色 - 默认 |
| $color-switch_default-bg-hover | var(--semi-color-fill-1) | 关闭态开关背景色 - 悬浮 |
| $color-switch_default-bg-active | var(--semi-color-fill-2) | 关闭态开关背景色 - 按下 |
| $color-switch_default-border-default | transparent | 关闭态开关描边颜色 |
| $color-switch_checked-bg-default | var(--semi-color-success) | 开启态开关背景色 - 默认 |
| $color-switch_checked-bg-hover | var(--semi-color-success-hover) | 开启态开关背景色 - 悬浮 |
| $color-switch_checked-bg-active | var(--semi-color-success-active) | 开启态开关背景色 - 按下 |
| $color-switch_disabled-bg-default | transparent | 禁用态开关背景色 |
| $color-switch_disabled-bg-hover | transparent | 禁用态开关背景色 - 悬浮 |
| $color-switch_disabled-bg-active | transparent | 禁用态开关背景色 - 按下 |
| $color-switch_disabled-border-default | var(--semi-color-border) | 禁用态开关描边颜色 |
| $color-switch_disabled-bg-hover | transparent | 禁用态开关背景色 - 悬浮 |
| $color-switch_checked_disabled-bg-default | var(--semi-color-success-disabled) | 禁用开启态开关背景颜色 |
| $color-switch_checked_disabled-border-default | transparent | 禁用开启态开关描边颜色 |
| $color-switch_knob-bg-default | var(--semi-white) | 开关滑块背景颜色 - 关闭态 |
| $color-switch_knob-bg-checked | var(--semi-white) | 开关滑块背景颜色 - 开启态 |
| $color-switch_knob-border-default | var(--semi-color-border) | 开关滑块描边颜色 |
| $color-switch_checked-text-default | var(--semi-color-white) | 开启态开关文案颜色 |
| $color-switch_unchecked-text-default | var(--semi-color-text-2) | 关闭态开关文案颜色 |
| $color-switch_loading_spin-default | var(--semi-color-white) | 加载态开关loading图标颜色 |
| $color-switch_spin_checked-bg-default | var(--semi-color-success-hover) | 已开启开关加载态loading背景颜色 |
| $color-switch_spin_unchecked-bg-default | var(--semi-color-fill-1) | 已关闭开关加载态loading背景颜色 |
| $color-switch_primary-outline-focus | $color-focus-ring | 开关轮廓 - 聚焦 |
| $width-switch | 40px | 开关宽度 |
| $height-switch | 24px | 开关高度 |
| $width-switch_knob_expand | 6px | 开关滑块按压时延展宽度 |
| $width-switch_knob_default | 18px | 开关滑块宽度 |
| $width-switch_knob_active | $width-switch_knob_default + $width-switch_knob_expand | 开关滑块按下态宽度 |
| $height-switch_large | 32px | 大尺寸开关高度 |
| $width-switch_large | 54px | 大尺寸开关宽度 |
| $width-switch_knob_large | 24px | 大尺寸开关滑块宽度 |
| $width-switch_knob_large_active | $width-switch_knob_large + $spacing-switch_expand_large-translateX | 大尺寸开关滑块按下态宽度 |
| $height-switch_small | 16px | 小尺寸开关高度 |
| $width-switch_small | 26px | 小尺寸开关宽度 |
| $width-switch_knob_large_small | 12px | 小尺寸开关滑块宽度 |
| $width-switch_knob_small_active | $width-switch_knob_large_small + $spacing-switch_expand_small-translateX | 小尺寸开关滑块按下态宽度 |
| $width-switch_knob_disabled-border | 1px | 禁用态开关滑块边框宽度 |
| $width-switch_checked_unchecked_text | 26px | 开关文案宽度 |
| $width-switch_spin-small | 10px | 小尺寸开关加载 spin 宽度 |
| $width-switch_spin-default | 18px | 默认尺寸开关加载 spin 宽度 |
| $width-switch_spin-large | 28px | 大尺寸开关加载 spin 宽度 |
| $width-switch-outline | $width-focus-ring | 开关轮廓宽度 |
| $spacing-switch_knob-padding | 2px | 开关滑块顶部边距 |
| $spacing-switch_knob_large-padding | 3px | 大尺寸开关滑块顶部边距 |
| $spacing-switch_knob_small-padding | 1px | 小尺寸开关滑块顶部边距 |
| $spacing-switch_knob-left | 0px | 开关滑块左侧偏移距离 |
| $radius-switch | $height-switch * 0.5 | 开关圆角 |
| $radius-switch_large | $height-switch_large * 0.5 | 大尺寸开关圆角 |
| $radius-switch_small | $height-switch_small * 0.5 | 小尺寸开关圆角 |