Specialized inputs

AppOtpInput

Code entry for MFA, email and phone verification.

<app-otp-input label="Verification code" name="Code" />

<app-otp-input> is the field a user types a one-time code into — signing in with MFA, confirming an email or phone, redeeming a backup code.

It is one input with the segment boxes drawn underneath, not one input per character. That is the whole design and it is not cosmetic: it is what makes phone autofill and screen readers work.

Playground

Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the field above it. Type or paste into the field to see the segments fill.

<app-otp-input label="Verification code" name="Code" />
Autofocus and masking are screen decisions, not attributesThere is no autofocus or masked/obscured-character attribute here. Whether the field grabs focus on mount, and whether a code is ever visually hidden, depends on the screen it lives on, not the component — a screen that wants autofocus reaches the inner <input> imperatively (document.querySelector('wui-otp input').focus()), the same way any custom element is focused.

Basic

Six digits, the default.

A verification code
Type, paste, or let the phone fill it from the SMS.
Show code
<app-otp-input label="Verification code" name="Code" />
Try pasting into itCopy a code like 123456 and paste it anywhere in the field above — even with stray spaces or dashes (12 34-56). There is no special paste handler to configure: it is one <input>, so the browser hands it the whole clipboard string and the element strips what the mode does not allow before filling the segments.
Why one input and not sixiOS and Android deliver an SMS code to the focused field, whole. With six inputs the OS puts all six digits into box one — or just the first digit — depending on version. It is the most reported OTP bug on the web and it cannot be fully worked around from script. Six inputs also announce to a screen reader as six unlabelled boxes with no stated relationship; one input is one labelled field. Paste stops being a special case for the same reason.

States

Length, mode, and the states a verify round-trip goes through. The same label / required / hint / error contract as every other field.

Length, mode, error and disabled
TOTP is six digits; backup codes are often eight, and sometimes alphanumeric.
That code has expired.
Show code
<app-otp-input label="Backup code" name="B1" length="8" mode="alphanumeric" />
<app-otp-input label="Verification code" name="B2" error="That code has expired." />
<app-otp-input label="Verification code" name="B3" disabled="true" />

When to use

Use it when

  • A one-time code: MFA, email or phone verification, backup codes.
  • Anywhere the code has a known, fixed length.

Reach for something else when

  • A password or passphrase. → app-input with type="password"
  • A code of unknown or variable length. → app-input
  • A licence key with separators — the segments here are characters, not groups. → app-input

Best practices

Do
One labelled field, six boxes drawn underneath. Autofill, paste and a screen reader all work.
Don't
Six inputs: the OS drops the whole SMS code into box one, and a screen reader announces six unlabelled boxes.

Every option

The whole surface of the component, one cell per value.

length — every length

length="4"
length="6"
length="8"

mode — numeric vs alphanumeric

mode="numeric"
mode="alphanumeric"

state

(default)
required="true"
disabled="true"
disabled="true" value="482913"
error="…"
That code has expired.
hint="…"
Sent via SMS to •••• 42
error + hint (error wins)
That code has expired.

shell — label / hint / error vs bare

(no label, no hint, no error) — bare element, no <div class="field"> wrapper
label only
label + required

Attributes

AttributeTypeDefaultDescription
asp-forModelExpression—Model property to bind to — supplies name, id, value, label and required.
labelstring—Field label, and the control's accessible name.
namestring—POST binding name.
idstring—Explicit control id — routed to the single visible input; defaults from name.
valuestring—The code entered so far.
lengthint6Characters in the code. TOTP is 6; backup codes are often 8.
modenumeric | alphanumericnumericDrives the on-screen keyboard and what the field will accept.
requiredbool—Marks the field required, in the markup and to assistive tech.
hintstring—Helper text under the field.
errorstring—Replaces the hint and marks the field invalid.
disabledbool—Disable the control.
classstring—Extra classes on the control (React className).
input-classstring—Extra classes on the control itself (the wui-otp) — the React className counterpart. The plain class attribute merges onto the .field wrapper instead.