OTP Input

The OtpInput component collects a one time code, the kind sent by SMS or made by an authenticator app. Each character has its own box, typing moves forward by itself, and pasting a whole code fills every box at once.

Example

Import the component and bind a string. The value is the code as one piece of text, so you can send it straight to your server.

value: ""

Svelte
<script>
  import { OtpInput } from "theui-svelte";
  let code = $state("")
</script>

<OtpInput bind:value={code}>Verification code</OtpInput>

Length

The length prop sets how many boxes there are. The default is 6.

Svelte
<OtpInput length={4} />
<OtpInput length={8} />

Types

The type prop decides what may be typed: number (default) takes digits only and opens the number keypad on a phone, text takes letters and digits, and password hides what has been typed.

Digits only
Letters and digits
Hidden
Svelte
<OtpInput type="number" length={4} />
<OtpInput type="text" length={4} />
<OtpInput type="password" length={4} />

Separator

Use separatorAfter to break a long code into two halves, the way printed codes are grouped.

Svelte
<OtpInput length={6} separatorAfter={3} />

On Complete

The oncomplete callback runs as soon as the last box is filled, which is the moment to check the code without making the user press a button.

Waiting for four digits...

Svelte
<OtpInput length={4} oncomplete={(value) => verify(value)}>
  Enter the code
</OtpInput>

Sizes and Variants

Sizes run from sm to xl, and the variant can be bordered or flat. Both are inherited from a Form or a Fieldset.

Svelte
<OtpInput length={4} size="sm" />
<OtpInput length={4} size="lg" />
<OtpInput length={4} variant="flat" />
<OtpInput length={4} rounded="full" />

In a Form

Give the component a name and the whole code is submitted as one field, not as six. Add autofocus when the code is the only thing on the page.

We sent a code to your phone
Svelte
<form method="POST">
  <OtpInput name="otp" length={6} helperText="We sent a code to your phone">
    One time code
  </OtpInput>
  <button>Verify</button>
</form>

Animation Speed

The animationSpeed prop sets how quickly each box reacts to focus and hover. It takes "none", "slower", "slow", "normal", "fast" and "faster", and the default is "normal". Inside a Form or a Fieldset the value is inherited, so one setting covers every field at once.

Svelte
<OtpInput animationSpeed="slower">Slower</OtpInput>
<OtpInput animationSpeed="faster">Faster</OtpInput>
<OtpInput animationSpeed="none">No animation</OtpInput>

Reset Styles

Set reset to true to drop the border, background and focus ring of every box and keep only the classes you pass. The boxes stay in a row and keep their width, so paste and the arrow keys are unaffected. The default is false, and a Form or a Fieldset can set it for every field it holds.

Svelte
<OtpInput reset boxClasses="border-0 border-b-2 border-gray-400">
  Underline only
</OtpInput>

Customization

Use boxClasses for the boxes themselves, and placeholder to show a character in the empty ones.

Svelte
<OtpInput length={4} placeholder="•" />
<OtpInput length={4} boxClasses="w-12 text-xl font-semibold" />
<OtpInput length={4} variant="flat" boxClasses="border-b-4 text-2xl" />

Keyboard and Paste

Typing a character moves to the next box. Backspace clears the box, or steps back and clears the one before when the box is already empty. The left and right arrows move between boxes, Home and End jump to the first and last, and Delete clears without moving. Pasting a code anywhere in the row fills the boxes from that point on, so a copied code never has to be typed.

Accessibility

Every box is a real input with its own name, such as "Character 3 of 6", which you can reword with the boxLabel prop. The row is a group, so a screen reader user hears the label of the field before the boxes. The first box carries autocomplete="one-time-code", which lets phones offer the code from an SMS, and the number type opens the numeric keypad. When you pass a name, the code is submitted once as a whole rather than as separate characters.

Configuration