SlideVerify

View source
流畅的滑动验证组件。

简介

MSlideVerify 是一个滑动验证组件,提供拖拽交互与状态转换动画。基于 motion-v 实现流畅过渡,适用于表单验证、敏感操作确认等场景。

使用 Motion 动画库提供拖拽交互与状态转换动画

用法

按住滑块并向右拖动至阈值即可通过验证:

请向右滑动验证
<script setup lang="ts">
const value = ref(false)
</script>

<template>
  <MSlideVerify v-model="value" />
</template>

threshold 通过阈值

threshold 决定拖动占比达到多少判定通过,默认 0.9,调低可放宽校验:

拖到一半即可
<template>
  <MSlideVerify :threshold="0.5" text="拖到一半即可" />
</template>

text 提示文案

text 设定待验证提示,successText 设定通过后的文案:

按住并向右拖动
<template>
  <MSlideVerify text="按住并向右拖动" success-text="人机校验已通过" />
</template>

icon 滑块图标

icon 设定待验证图标,successIcon 设定通过后的图标:

请向右滑动验证
<template>
  <MSlideVerify icon="i-lucide-arrow-right" success-icon="i-lucide-shield-check" />
</template>

size 尺寸

通过 size 调整组件尺寸:

请向右滑动验证
<template>
  <MSlideVerify size="md" />
</template>

disabled 禁用状态

disabled 冻结滑块,光标不可拖动且保持当前未验证态:

请向右滑动验证
<template>
  <MSlideVerify disabled />
</template>

示例

继承字段上下文

放入 UFormField 后接收字段尺寸与错误态,滑块按表单状态渲染:

请向右滑动验证
示例错误态
<template>
  <UFormField label="滑动验证" size="xs" error="示例错误态">
    <MSlideVerify />
  </UFormField>
</template>

融入UFieldGroup

与重置按钮组合时共享 UFieldGroup 尺寸,滑块区域和按钮保持统一高度:

请向右滑动验证
<template>
  <UFieldGroup size="xs">
    <MSlideVerify class="flex-1" />
    <UButton icon="i-lucide-rotate-ccw" color="neutral" variant="subtle" />
  </UFieldGroup>
</template>

自定义滑块内容

slider 插槽接管滑块内部渲染,可读取 verifiedprogress 动态展示进度:

请向右滑动验证
0%
<script setup lang="ts">
const isVerified = ref(false)
</script>

<template>
  <MSlideVerify v-model="isVerified" class="w-sm">
    <template #slider="{ verified, progress }">
      <UIcon v-if="verified" name="i-lucide-check" />
      <span v-else class="text-xs font-medium">{{ Math.round(progress * 100) }}%</span>
    </template>
  </MSlideVerify>
</template>

事件回调

开始拖动触发 dragStart,松手触发 dragEnd 并回传是否成功,达到阈值额外触发 success

请向右滑动验证
<script setup lang="ts">
const isVerified = ref(false)
const slideVerifyRef = useTemplateRef('slideVerifyRef')
const toast = useToast()

function handleSuccess() {
  toast.add({
    title: '验证成功',
    description: '已触发 success 事件',
    color: 'success'
  })
}

function handleDragEnd(success: boolean) {
  if (!success) {
    toast.add({
      title: '验证失败',
      description: '请继续滑动',
      color: 'neutral'
    })
  }
}

function handleReset() {
  slideVerifyRef.value?.reset()
  toast.add({
    title: '已重置',
    color: 'neutral'
  })
}
</script>

<template>
  <div class="w-sm flex gap-4">
    <MSlideVerify
      ref="slideVerifyRef"
      v-model="isVerified"
      class="flex-1"
      @success="handleSuccess"
      @drag-end="handleDragEnd"
    />
    <UButton size="sm" color="neutral" variant="outline" @click="handleReset"> 重置验证 </UButton>
  </div>
</template>

API

Props

Prop Default Type
text'请向右滑动验证'string

待滑动时的提示文本

icon'i-lucide-chevrons-right'any

滑块图标

successText'验证成功'string

验证成功时的提示文本

successIcon'i-lucide-check'any

验证成功时的图标

threshold0.9number

完成验证所需的阈值百分比(0-1)

size'md'"md" | "xs" | "sm" | "lg" | "xl"

尺寸大小

idstring
namestring
disabledboolean

是否禁用

modelValuefalseboolean
uiRecord<string, ClassNameValue> & { root?: SlotClass; track?: SlotClass; fill?: SlotClass; text?: SlotClass; slider?: SlotClass; icon?: SlotClass; }

Emits

Event Type
update:modelValue[value: boolean]
success[]
dragStart[]
dragEnd[success: boolean]

Slots

Slot Type
slider{ verified?: boolean; progress: number; }

Expose

您可以通过 useTemplateRef 访问该类型化组件实例。

NameType
reset()Promise<void>

重置验证状态

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    slideVerify: {
      slots: {
        root: 'w-full relative flex items-center select-none overflow-hidden rounded-md border transition-colors duration-300',
        track: 'absolute inset-0',
        fill: 'absolute inset-y-0 left-0 bg-primary/20 opacity-60',
        text: 'absolute inset-0 flex items-center justify-center font-medium pointer-events-none',
        slider: 'relative z-10 flex shrink-0 touch-none items-center justify-center rounded-md shadow-sm transition-colors',
        icon: 'shrink-0'
      },
      variants: {
        size: {
          xs: {
            root: 'p-1',
            text: 'text-xs',
            slider: 'px-2 py-1',
            icon: 'size-4'
          },
          sm: {
            root: 'p-1.5',
            text: 'text-xs',
            slider: 'px-2.5 py-1.5',
            icon: 'size-4'
          },
          md: {
            root: 'p-1.5',
            text: 'text-sm',
            slider: 'px-2.5 py-1.5',
            icon: 'size-5'
          },
          lg: {
            root: 'p-2',
            text: 'text-sm',
            slider: 'px-3 py-2',
            icon: 'size-5'
          },
          xl: {
            root: 'p-2',
            text: 'text-base',
            slider: 'px-3 py-2',
            icon: 'size-6'
          }
        },
        disabled: {
          true: {
            root: 'opacity-50 cursor-not-allowed'
          }
        },
        verified: {
          true: {
            root: 'bg-success border-transparent',
            slider: 'bg-white/90',
            icon: 'text-success'
          },
          false: {
            root: 'bg-elevated border-default',
            slider: 'bg-default cursor-grab active:cursor-grabbing ring-1 ring-default',
            icon: 'text-primary'
          }
        },
        fieldGroup: {
          horizontal: {
            root: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]'
          },
          vertical: {
            root: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
          }
        }
      },
      defaultVariants: {
        size: 'md'
      }
    }
  }
})

Changelog

No recent changes
Copyright © 2025 - 2026 YiXuan - MIT License