Skip to content

Input OTP <input>

A single native <input> with visual digit cells for one-time passcode entry. The <l-input-otp> wrapper renders individual bordered cells over a hidden input that handles keyboard, paste, and autocomplete.

HTML tag<l-input-otp>
Native HTML
Progressive
Custom
Shadow DOM
Progressive Custom Element

Options

Default

Code
html
<label class="flex flex-col gap-1.5">
  <span class="text-sm font-medium">Verification code</span>
  <l-input-otp>
    <input />
  </l-input-otp>
</label>

Digit count

Set --digits on <l-input-otp> to change the number of cells. The element automatically sets maxlength and pattern on the input.

Code
html
<label class="flex flex-col gap-1.5">
  <span class="text-sm font-medium">PIN code</span>
  <l-input-otp style="--digits: 4">
    <input />
  </l-input-otp>
</label>

Separator

Add separator-after attribute to insert a visual dash after the specified position (e.g., separator-after="3" for a 3-3 grouping).

Code
html
<label class="flex flex-col gap-1.5">
  <span class="text-sm font-medium">Verification code</span>
  <l-input-otp separator-after="3">
    <input />
  </l-input-otp>
</label>

Size

Set the size attribute on <l-input-otp>: sm, md (default), lg.

Code
html
<div class="flex flex-col gap-4 items-start">
  <l-input-otp size="sm">
    <input aria-label="Small OTP" />
  </l-input-otp>
  <l-input-otp>
    <input aria-label="Medium OTP" />
  </l-input-otp>
  <l-input-otp size="lg">
    <input aria-label="Large OTP" />
  </l-input-otp>
</div>

Disabled

Native disabled attribute.

Code
html
<l-input-otp>
  <input
    value="384291"
    disabled
    aria-label="Verification code"
  />
</l-input-otp>

Accessibility

Criteria

Role

Uses a native <input> element — built-in textbox semantics

WCAG4.1.2
RGAA11.1
Accessible name

Requires <label> or aria-label to describe the purpose of the code input

WCAG1.3.1
RGAA11.1
Input purpose

autocomplete="one-time-code" identifies the field for browser and password manager autofill

WCAG1.3.5
Validation

pattern and maxlength provide client-side validation; inputmode="numeric" triggers the numeric keyboard on mobile

WCAG3.3.1
Visual cells

Cell container is aria-hidden="true" — screen readers interact with the native input only

WCAG4.1.2

Keyboard interactions

Tab
Moves focus to/from the input
0–9
Types a digit into the next available position
Backspace
Deletes the last entered digit
CtrlV / CmdV
Pastes a full code from clipboard

Why light DOM?

The native <input> lives in the light DOM so it stays directly accessible for <label> association, form participation, and external CSS. The visual cells are purely decorative (aria-hidden="true") — screen readers only see the real input.

API reference

Importing

css
@import 'luxen-ui/css/input-otp';
js
import 'luxen-ui/input-otp';

Attributes & Properties

sizeAttribute
Control size: sm, md (default), lg
separator-afterAttribute
Position after which to insert a visual separator dash (e.g., 3 for a 3-3 grouping)

CSS custom properties

Set --digits on <l-input-otp> to change the digit count.

--digitsName
Number of digit cells (default: 6). Drives maxlength and pattern automatically
--sizeName
Cell width and height (default: 2.75rem). Font size scales automatically from this value
--gapName
Space between cells (default: 0.5rem)