Clinia UI

Input OTP

Separate boxes for a one-time code, such as two-factor sign-in.

shadcn docs →

When to use

  • A short one-time code of known length: a sign-in code, a verification code sent by email or SMS.

When not to use

  • A password, an API key or any value of variable length: use Input.
  • A code longer than about eight characters: use Input with autoComplete="one-time-code".

Install

npx shadcn@latest add @clinia/input-otp

Anatomy

4
8
2
  1. 1Groupdata-slot="input-otp-group"rounded-lg
  2. 2Boxdata-slot="input-otp-slot"border-input · size-9
  3. 3Separatordata-slot="input-otp-separator"size-4

Clinia rules

  • Each box has an input border; the active box shows the Trust ring.
  • Split a six-digit code into two groups of three with InputOTPSeparator, so it's easier to read and check.
  • Say where the code was sent right above the boxes, and how to get a new one below them.

Do and don't

Enter the code sent to j•••@clinic.ca.

Do say where the code went, and split six digits in two.
Don't show the boxes with no hint of where the code is.

States

empty
filled
4
8
2
1
invalid
4
8
disabled
focus · active box
4

Focus cells apply the component's focus-visible classes statically. Toggle the site theme to review both themes.

Accessibility

Built in

  • The boxes are one input to assistive technology. Pasting a full code fills every box.
  • It's one real input behind the boxes: typing fills the next box, Backspace clears the previous one, and the arrow keys move the caret.

Your responsibility

  • Give the group an aria-label, such as Verification code: a screen reader announces it as the field's name.
  • Set inputMode="numeric" for digit-only codes and keep autoComplete="one-time-code" so phones offer the code from the message.
  • On a wrong code, set aria-invalid and show a FieldError that says what to do next, such as request a new code.
  • Don't submit the moment the last box fills if the user can't review or correct the code first.

How to test

  1. Press Tab into the code: the first empty box shows the Trust ring and a caret.
  2. Type the digits: each box fills in turn. Press Backspace: the last digit clears.
  3. Paste a full code: every box fills at once.
  4. With a screen reader, it announces the aria-label and the typed value as one field, not six.

API

InputOTPSlot

PropValuesDefaultDescription
index
number
–

This box's position, from 0.

All other props come from input-otp.