Simple but effective Otp input (for Vue2 only)
- Auto focus next box while typing
- Handle copy/paste nicely
- Handle mobile auto complete nicely
- Handle delete, arrow keys correctly
- Support both controlled/uncontrolled in components
- Fully tested with real life usecases
- Zero dependencies, super small bundle size ~2.3kB gziped
- WebOtp included
This sounds simple to do, but hard to make it works correctly and handles all the cases for otp. Based on my expericences with the existing libs, I created this to handle all my needs. Hope it helps you as well.
Video for autofill in mobile page (from friends)
Safari | Chrome | On/off focus suggestion |
---|---|---|
Image.from.iOS.MP4 |
Image.from.iOS.MP4 |
Image.from.iOS.MP4 |
Screen shot for tests and test coverage:
yarn add vue-simple-otp-input
import SimpleOtpInput from "vue-simple-otp-input";
Look at the App.vue for more detail, or try it here
<section class="story">
<label>Default otp input</label>
<SimpleOtpInput />
</section>
<section class="story">
<label>Password type input</label>
<SimpleOtpInput type="password" :length="4" />
</section>
<section class="story">
<label>With inital value</label>
<SimpleOtpInput value="123456" />
</section>
<section class="story">
<label>With events</label>
<SimpleOtpInput
type="password"
:length="4"
@change="handleChange"
@complete="handleComplete"
/>
<div><strong>Draft</strong> {{ otp }}</div>
<div><strong>Submitted</strong> {{ submittedOtp }}</div>
</section>
<section class="story">
<label>Lazy v-model </label>
<button @click="setLazyCodeValue">Randomize code value</button>
<SimpleOtpInput v-model="lazyCode" />
</section>
<section class="story">
<label>With extra slot to create border effect</label>
<SimpleOtpInput
class="otp-with-effect"
inputClasses="input-with-effect"
:pasteDelayMs="192"
withWebOtp
>
<template v-slot:extra>
<span class="focus-border">
<i></i>
</span>
</template>
</SimpleOtpInput>
</section>
Prop | Default | Description |
---|---|---|
length | 6 |
Length of this otp input |
value | '' |
Value for this input, v-model is supported, in rare cases, you may need to use setOtpValue to force update internal state |
type | 'text' |
Html input type of each input, you may find 'password' useful |
inputClasses | '' |
Inner input classess, allow you to fully control input styles |
pasteDelayMs | 0 |
Delay for pasting content, we may want to let the animation to take effect on pasting |
withWebOtp | false |
Should we enable WebOtp setup when browser is supported |
withExtraSpan | false |
Just like extra slot, but enabled via a flag and no customization |
inputProps | {} |
Custom input props will be set to all input, totally control edge cases |
Event | Description |
---|---|
input | Emit on every change on otp input, support v-model |
change | Emit on every update on otp input |
complete | Emit on key enter , emitted otp may not complete |
- extra: extra content next to each input, prodived you
{ idx, otp, length }
to allow fully customization. - You will find this helpful when adding separator between inputs, or adding some pseduo elements to get extra effect (e.g border on focus)
- To get default styling as the demo page, please import extra css file
vue-simple-otp-input/dist/vue-simple-otp-input.css
to your component. - Or you can pasting its content there
.simple-otp-input {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.otp-single-input {
padding: 4px;
width: 2em;
height: 2em;
text-align: center;
}
.single-input-container {
position: relative;
z-index: 1;
margin: 2px;
}
/* To grab suggestion input in IOS */
.simple-otp-input .hidden-otp-input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
box-sizing: border-box;
pointer-events: none;
}
.simple-otp-input.empty .single-input-container {
z-index: 0;
}
.simple-otp-input.empty .hidden-otp-input {
z-index: 1;
pointer-events: initial;
}
- Or just simply overriding it by your class name.