Skip to content

Interactive Playground

Build your perfect OTP input by toggling options. The generated code updates live.

6
View Code
<OtpInput
  v-model="otp"
  theme="box"
  size="md"
  :num-inputs="6"
/>

Quick Examples

Basic 6-digit OTP

vue
<OtpInput v-model="otp" />

4-digit PIN

vue
<OtpInput v-model="pin" :num-inputs="4" />

With Separator

---
vue
<OtpInput :num-inputs="4" separator="-" />

Password Mode

vue
<OtpInput :num-inputs="4" input-type="password" />

Custom Placeholders

vue
<OtpInput :placeholder="['O', 'T', 'P', 'C', 'O', 'D']" />

Error State

Shake animation plays on mount
vue
<OtpInput :error="isError" />

Success State

Pulse animation plays on mount
vue
<OtpInput :success="isVerified" />

Disabled

vue
<OtpInput disabled />

Readonly

vue
<OtpInput readonly />

All Sizes

Small
Medium
Large
Extra Large

Programmatic Control

vue
<script setup>
const otpRef = ref(null)
</script>

<template>
  <OtpInput ref="otpRef" />

  <button @click="otpRef.fill('123456')">Fill</button>
  <button @click="otpRef.clear()">Clear</button>
  <button @click="otpRef.focus()">Focus</button>
  <button @click="otpRef.focusInput(3)">Focus 4th</button>
</template>

Real-World: Verification Form

vue
<script setup>
import { ref } from 'vue'
import { OtpInput } from 'vue-otp-pro'
import 'vue-otp-pro/dist/vue-otp-pro.css'

const otp = ref('')
const isError = ref(false)
const isSuccess = ref(false)
const isLoading = ref(false)

async function verify() {
  isLoading.value = true
  try {
    await api.verifyOtp(otp.value)
    isSuccess.value = true
  } catch {
    isError.value = true
    setTimeout(() => (isError.value = false), 600)
  } finally {
    isLoading.value = false
  }
}
</script>

<template>
  <div class="verify-form">
    <h2>Enter verification code</h2>
    <p>We sent a 6-digit code to your email.</p>

    <OtpInput
      v-model="otp"
      theme="separated"
      size="lg"
      :error="isError"
      :success="isSuccess"
      :disabled="isLoading"
      should-auto-focus
      @complete="verify"
    />
  </div>
</template>