Skip to content

OTP Field

A sequence of single-character inputs for entering one-time passwords and verification codes.

Enter the 6-character code we sent to your device.

Introduction

OtpField renders one input per character and keeps them in sync with a single value. It handles focus movement between slots, pasting a full code at once, keyboard navigation, masking, validation filtering, and optional auto-submit when the value becomes complete. It integrates with Field for labelling, validation, and form submission.

Anatomy

Import the components and assemble them. Render one OtpFieldInput for every slot up to length:

vue
<script setup>
import { OtpFieldInput, OtpFieldRoot } from 'base-ui-vue'

const OTP_LENGTH = 6
</script>

<template>
  <OtpFieldRoot :length="OTP_LENGTH">
    <OtpFieldInput v-for="i in OTP_LENGTH" :key="i" />
  </OtpFieldRoot>
</template>

Validation type

Use the validation-type prop to constrain which characters are accepted. Accepted values are numeric (default), alpha, alphanumeric, and none. Rejected characters emit value-invalid:

vue
<OtpFieldRoot :length="6" validation-type="alphanumeric">
  <OtpFieldInput v-for="i in 6" :key="i" />
</OtpFieldRoot>

Masking

Set mask to hide entered characters, rendering each slot as a password input:

vue
<OtpFieldRoot :length="6" mask>
  <OtpFieldInput v-for="i in 6" :key="i" />
</OtpFieldRoot>

Auto-submit

Set auto-submit to submit the owning form automatically once every slot is filled:

vue
<OtpFieldRoot :length="6" auto-submit>
  <OtpFieldInput v-for="i in 6" :key="i" />
</OtpFieldRoot>

API reference

Root

Groups all OTP field parts and manages their state. Renders a <div> element.

PropTypeDefaultDescription
lengthnumber--The number of OTP input slots. Must match the number of rendered OtpFieldInput parts.
valuestring--The controlled OTP value.
defaultValuestring--The uncontrolled initial value.
validationType'numeric' | 'alpha' | 'alphanumeric' | 'none''numeric'The type of input validation applied to the value.
normalizeValue(value: string) => string--Idempotent normalizer applied after whitespace and validation filtering.
maskbooleanfalseWhether slot inputs should mask entered characters.
autoSubmitbooleanfalseWhether to submit the owning form when the value becomes complete.
autoCompletestring'one-time-code'Autocomplete hint applied to the first slot and hidden input.
inputModestring--Virtual keyboard hint. Defaults based on validationType.
namestring--Identifies the field when a form is submitted.
formstring--The id of the form element to associate the hidden input with.
disabledbooleanfalseWhether the component should ignore user interaction.
readOnlybooleanfalseWhether the user is unable to change the value.
requiredbooleanfalseWhether a value is required before submitting a form.
asstring | Component'div'The element or component to render.
classstring | ((state: State) => string)--CSS class applied to the element.
styleStyleValue | ((state: State) => StyleValue)--Style applied to the element.
EmitArgumentsDescription
value-change(value: string, eventDetails)Fired when the OTP value changes.
value-complete(value: string, eventDetails)Fired when the value becomes complete.
value-invalid(value: string, eventDetails)Fired when typed/pasted text contains rejected characters.
Data attributeDescription
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-disabledPresent when the field is disabled.
data-readonlyPresent when the field is read-only.
data-requiredPresent when the field is required.
data-completePresent when every slot is filled.
data-filledPresent when the field has a value.
data-focusedPresent when a slot is focused.
data-touchedPresent after the field has been touched.
data-dirtyPresent when the value differs from the initial value.

Input

An individual OTP character input. Renders an <input> element.

PropTypeDefaultDescription
asstring | Component'input'The element or component to render.
classstring | ((state: State) => string)--CSS class applied to the element.
styleStyleValue | ((state: State) => StyleValue)--Style applied to the element.
Data attributeDescription
data-validPresent when the field is valid.
data-invalidPresent when the field is invalid.
data-disabledPresent when the field is disabled.
data-readonlyPresent when the field is read-only.
data-requiredPresent when the field is required.
data-completePresent when every slot is filled.
data-filledPresent when this slot contains a character.
data-focusedPresent when a slot is focused.