Input OTP

One-time password input with individual digit boxes, auto-focus advance, blinking cursor, and paste support.

Default

A 6-digit OTP input with a separator between groups of 3. Click to focus, type digits, or paste a code.

<div class="sui-otp" data-sui-otp>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
  <div class="sui-otp-separator"></div>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

<script>
  // Listen for completion:
  document.querySelector('.sui-otp').addEventListener('sui-otp-complete', (e) => {
    console.log('OTP entered:', e.detail.value);
  });
</script>

Four Digits

A compact 4-digit PIN input without separators.

<div class="sui-otp" data-sui-otp>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

Alphanumeric

Add data-sui-otp-pattern="alphanumeric" to accept both letters and digits. Characters are auto-uppercased.

<div class="sui-otp" data-sui-otp data-sui-otp-pattern="alphanumeric">
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
  <div class="sui-otp-separator sui-otp-separator-dot"></div>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

Connected

Add sui-otp-connected for slots that share a single inset surface with no gap between them.

<!-- Connected with separator -->
<div class="sui-otp sui-otp-connected" data-sui-otp>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
  <div class="sui-otp-separator"></div>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

<!-- Connected without separator -->
<div class="sui-otp sui-otp-connected" data-sui-otp>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

With Separator

Use sui-otp-separator between groups. Add sui-otp-separator-dot for a dot style instead of a dash.

<!-- Dash separator -->
<div class="sui-otp" data-sui-otp>
  <div class="sui-otp-group">...</div>
  <div class="sui-otp-separator"></div>
  <div class="sui-otp-group">...</div>
</div>

<!-- Dot separator -->
<div class="sui-otp" data-sui-otp>
  <div class="sui-otp-group">...</div>
  <div class="sui-otp-separator sui-otp-separator-dot"></div>
  <div class="sui-otp-group">...</div>
</div>

Sizes

Add sui-otp-sm or sui-otp-lg for size variants.

<!-- Small -->
<div class="sui-otp sui-otp-sm" data-sui-otp>...</div>

<!-- Default -->
<div class="sui-otp" data-sui-otp>...</div>

<!-- Large -->
<div class="sui-otp sui-otp-lg" data-sui-otp>...</div>

Disabled

<div class="sui-otp" data-sui-otp data-sui-otp-disabled>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
  <div class="sui-otp-separator"></div>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>

Error State

Add sui-otp-error to indicate an invalid code.

Invalid verification code. Please try again.
<div class="sui-otp sui-otp-error" data-sui-otp>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
  <div class="sui-otp-separator"></div>
  <div class="sui-otp-group">
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
    <div class="sui-otp-slot"></div>
  </div>
</div>
<span style="color:var(--sui-danger);font-size:12px;">Invalid verification code.</span>

Delete this item?

This action cannot be undone. This will permanently delete the item and remove all associated data.