OTP Input
A one-time password input that renders a row of individual character boxes with auto-advance, paste support, and configurable length and input type.
<arc-otp-input> Overview
>
OTPInput provides a specialized multi-box code entry field commonly used for verification codes, two-factor authentication, and PIN inputs. It renders a configurable number of individual input boxes (defaulting to 6) in a horizontal row, each accepting a single character. As the user types, focus automatically advances to the next box, and pressing Backspace on an empty box moves focus backward and clears the previous character — creating a smooth, uninterrupted typing flow.
The component supports two input modes via the `type` prop. The default `number` mode filters out non-digit characters and sets `inputmode="numeric"` for mobile keyboard optimisation. Setting `type="text"` allows any character, suitable for alphanumeric verification codes. Each box uses a monospace font at 20px for clear character visibility, with an accent-primary caret and focus ring to highlight the active input position.
Paste handling is built in — pasting a code into any box distributes the characters across subsequent boxes and advances focus to the end of the pasted content. The component fires `arc-input` on every character addition or removal, with the partial concatenated value in the event detail, and `arc-change` once every box is filled — the commit for a fixed-length code. Arrow keys, Home, and End provide horizontal navigation across boxes, and the `autocomplete="one-time-code"` attribute enables browser autofill from SMS or authenticator apps.Guidelines
When to use
- Set `length` to match the expected code length from your authentication backend
- Use `type="number"` for numeric-only codes to get the mobile numeric keyboard
- Listen for `arc-change` to auto-submit — it fires only once the code is complete
- Place OTPInput in a focused, distraction-free context like a verification step
- Provide a clear label or heading above the input explaining what code to enter
When not to use
- Do not use OTPInput for general text entry — it is designed specifically for short codes
- Do not set `length` higher than 8 — very long code inputs become unwieldy on mobile screens
- Do not use `type="text"` when the code is purely numeric — the wrong keyboard will appear on mobile
- Do not place multiple OTP Inputs on the same page — it creates confusion about which code to enter
- Avoid removing the component from the DOM before the user has finished entering the code
Features
- Row of individual character boxes with configurable `length` (default 6)
- Auto-advance: focus moves to the next box on character entry
- Backspace moves focus backward and clears the previous box when the current box is empty
- Paste support: distributes pasted characters across boxes and advances focus
- Two input modes: `number` (digits only with numeric keyboard) and `text` (any character)
- Arrow key, Home, and End navigation across individual boxes
- Browser autofill support via `autocomplete="one-time-code"` on each input
- Fires `arc-input` on every character change and `arc-change` once the code is complete
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<arc-otp-input length="6" type="number"></arc-otp-input> import { OtpInput } from '@arclux/arc-ui-react';
export default function Example() {
return (
<OtpInput length={6} type="number" />
);
} <script setup>
import { OtpInput } from '@arclux/arc-ui-vue';
</script>
<template>
<OtpInput :length="6" type="number" />
</template> <script>
import { OtpInput } from '@arclux/arc-ui-svelte';
</script>
<OtpInput length={6} type="number" /> import { Component } from '@angular/core';
import { OtpInput } from '@arclux/arc-ui-angular';
@Component({
imports: [OtpInput],
template: `
<arc-otp-input [length]="6" type="number"></arc-otp-input>
`,
})
export class MyComponent {} import { OtpInput } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<OtpInput length={6} type="number" />
);
} import { OtpInput } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<OtpInput length={6} type="number" />
);
} API
-
size'sm' | 'md' | 'lg''md' - Control size. `md` is the default; `sm` and `lg` scale the digit boxes.
-
lengthnumber6 - Number of individual character boxes to render. Reflected as an attribute.
-
valuestring'' - The concatenated value of all boxes. Reflected as an attribute and updated on every input.
-
namestring'' -
disabledbooleanfalse - Disables all input boxes, reducing opacity to 40% and blocking pointer events.
-
type'number' | 'text''number' - Input mode. `number` filters non-digits and uses the numeric keyboard; `text` allows any character.
-
readonlybooleanfalse - Prevents typing, pasting, and clearing digits while the boxes stay focusable and the value still submits.
-
formAssociatedbooleantrue -
propertiesobject{ required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, } - Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
-
autoValidatesbooleantrue - Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
-
form -
validity -
validationMessage -
requiredbooleanfalse
Events
-
arc-inputdetail: { value: string } - Fired on every digit entered or deleted, with the partial value.
-
arc-changedetail: { value: string } - Fired when the code is complete — every box filled. That is the commit for a fixed-length code.
See Also
- Pin Input One-character-per-box input for PINs, OTPs, and verification codes with auto-advance, paste support, and optional masking.
- Input Versatile form control supporting single-line text, email, password, and multiline textarea modes with built-in label, placeholder, and validation states. Pairs with Form for complete data-entry workflows.