Switch 开关

在开与关之间切换。

<script setup lang="ts">
  import { ref } from 'vue'
  import { Switch } from '@hina-ui/vue'

  const autoplay = ref(true)
</script>

<template>
  <Switch v-model="autoplay">自动播放下一话</Switch>
</template>
vue

用法

import { Switch } from '@hina-ui/vue'
ts

开关表示一个立即生效的设置,与需要提交的复选框不同。v-model 绑定布尔值,默认插槽是文字,点文字与点轨道都会切换。未声明的属性都会传给内部的轨道元素。

当前值:false

<script setup lang="ts">
  import { ref } from 'vue'
  import { Switch, Stack, Text } from '@hina-ui/vue'

  const nsfw = ref(false)
</script>

<template>
  <Stack gap="sm">
    <Switch v-model="nsfw">显示限制级内容</Switch>
    <Text size="sm" tone="muted">当前值:{{ nsfw }}</Text>
  </Stack>
</template>
vue

示例

描述

description 在文字下方补一行说明,字号比文字小一档。

<script setup lang="ts">
  import { ref } from 'vue'
  import { Switch } from '@hina-ui/vue'

  const sync = ref(true)
</script>

<template>
  <Switch v-model="sync" description="在其他设备上打开同一部作品时,从上次的位置继续。">
    同步阅读进度
  </Switch>
</template>
vue

设置行

使用 control-placement="end" 将控件放到文案末端,配合 block 撑满容器宽度。说明始终位于标题下方;start 和 end 会跟随文字方向。

<script setup lang="ts">
  import { ref } from 'vue'
  import { Switch } from '@hina-ui/vue'

  const sync = ref(true)
</script>

<template>
  <Switch
    v-model="sync"
    control-placement="end"
    block
    description="在其他设备上打开同一部作品时,从上次的位置继续。"
  >
    同步阅读进度
  </Switch>
</template>
vue

尺寸

size 有 sm、md、lg 三档,轨道高分别为 20、24、28 像素,文字随档位变化。

<script setup lang="ts">
  import { Switch, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack gap="sm">
    <Switch size="sm" model-value>小号</Switch>
    <Switch size="md" model-value>中号</Switch>
    <Switch size="lg" model-value>大号</Switch>
  </Stack>
</template>
vue

状态

invalid 给轨道加上警示色边框;disabled 禁用整个控件。

<script setup lang="ts">
  import { Switch, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack gap="sm">
    <Switch invalid>必须开启才能继续</Switch>
    <Switch disabled>已禁用</Switch>
    <Switch disabled model-value>已禁用且开启</Switch>
  </Stack>
</template>
vue

仅轨道

没有文字时只渲染轨道,此时必须用 aria-label 命名。

<script setup lang="ts">
  import { ref } from 'vue'
  import { Switch, Inline } from '@hina-ui/vue'

  const dark = ref(false)
</script>

<template>
  <Inline gap="sm">
    <Switch v-model="dark" aria-label="深色模式" />
  </Inline>
</template>
vue

在表单中

放进 FormField 后,错误信息由字段渲染并关联到开关;校验规则与提交交给 Form。开关自带文字,字段不必再写标签;它的值常常决定其他字段是否必填,这类规则写在对象层,再指定错误落在哪个字段。

<script setup lang="ts">
  import { reactive, ref } from 'vue'
  import * as v from 'valibot'
  import { Button, Form, FormField, Input, Switch, Text } from '@hina-ui/vue'

  const schema = v.pipe(
    v.object({
      isPublic: v.boolean(),
      summary: v.string(),
    }),
    v.forward(
      v.check(
        input => !input.isPublic || input.summary.trim().length > 0,
        '公开的作品需要填写简介',
      ),
      ['summary'],
    ),
  )

  const values = reactive({ isPublic: true, summary: '' })
  const saved = ref('')

  async function save(data: unknown) {
    await new Promise(resolve => setTimeout(resolve, 600))
    saved.value = JSON.stringify(data)
  }
</script>

<template>
  <Form v-slot="{ submitting }" :values="values" :rules="schema" class="w-80" @submit="save">
    <FormField name="isPublic">
      <Switch v-model="values.isPublic">公开显示</Switch>
    </FormField>
    <FormField name="summary" label="简介">
      <Input v-model="values.summary" />
    </FormField>
    <Button type="submit" :loading="submitting" class="self-start">保存</Button>
    <Text v-if="saved" tone="muted" size="sm">已保存:{{ saved }}</Text>
  </Form>
</template>
vue

行为

  • 点击文字或者轨道都会切换,拇指滑到另一侧,轨道同时换色。键盘 Tab 落在轨道上,空格切换。
  • 悬停整个控件时轨道落墨,按下时加深。

无障碍

  • 轨道是 role="switch" 的按钮,带 aria-checked。根元素是 label,文字即名称。
  • 没有文字时通过 aria-label 或者 aria-labelledby 命名。
  • invalid 会同时设置 aria-invalid。

API

Props

属性
类型
默认值
说明
modelValue
boolean
false
是否开启
size
'sm' | 'md' | 'lg'
'md'
尺寸
description
string
—
文字下方的说明
controlPlacement
'start' | 'end'
'start'
控件相对于文案的位置
block
boolean
false
整行撑满容器宽度
disabled
boolean
false
是否禁用
invalid
boolean
false
是否处于校验未通过状态
class
string
—
追加至根元素的类名

插槽

插槽
参数
说明
default
—
文字

事件

事件
参数
说明
update:modelValue
value: boolean
值变化时