Logo

Input OTP

One-time password input with grouped slots, separators, paste support, patterns, and reactive forms compatibility.

Preview

Value: 123456

Usage

TS

import { FR_INPUT_OTP_PATTERN_DIGITS_AND_CHARS, FrInputOtpModule } from '@frame-ui-ng/components/input-otp';

TS

import { FormControl } from '@angular/forms';

readonly code = new FormControl('');

HTML

<frame-input-otp [formControl]="code" [maxLength]="6">
  <div frInputOtpGroup>
    <div frInputOtpSlot [index]="0"></div>
    <div frInputOtpSlot [index]="1"></div>
    <div frInputOtpSlot [index]="2"></div>
    <div frInputOtpSlot [index]="3"></div>
    <div frInputOtpSlot [index]="4"></div>
    <div frInputOtpSlot [index]="5"></div>
  </div>
</frame-input-otp>

Examples

Separator

Use `FrInputOtpSeparator` to divide a code into readable groups.

Disabled

Disable the reactive form control to disable the OTP input.

Reactive Forms

Input OTP implements ControlValueAccessor and works directly with Angular reactive forms.

Value: 123456

Invalid

Angular validation state drives the error treatment and clears when the value becomes valid.

Enter all 6 digits.

Four Digits

Use a shorter `maxLength` for PIN-code patterns.

Alphanumeric

Use `FR_INPUT_OTP_PATTERN_DIGITS_AND_CHARS` to accept letters and numbers.

Form

Pair Input OTP with Field and Angular validators for full form flows.

Enter the verification code we sent to m@example.com.

RTL

Input OTP inherits text direction from its container.

Token Inspector

Inspect the root, slot, active slot, group, and separator tokens.

Design Tokens

Input OTP builds its visible slots on top of the same surface decisions as FrInput, then adds slot, group, and separator tokens for segmented code entry.

SCSS


  --frame-input-otp-gap: 0.5rem;
  --frame-input-otp-group-gap: 0;
  --frame-input-otp-slot-size: 2.5rem;
  --frame-input-otp-slot-radius: var(--frame-input-root-radius);
  --frame-input-otp-slot-bg: var(--frame-input-root-bg);
  --frame-input-otp-slot-color: var(--frame-input-root-color);
  --frame-input-otp-slot-border: var(--frame-input-root-border);
  --frame-input-otp-slot-font-size: 1rem;
  --frame-input-otp-slot-font-weight: 500;
  --frame-input-otp-slot-focus-border: var(--frame-input-root-focus-border);
  --frame-input-otp-slot-focus-shadow: var(--frame-input-root-focus-shadow);
  --frame-input-otp-slot-invalid-border: var(--frame-input-root-invalid-border);
  --frame-input-otp-slot-invalid-shadow: var(--frame-input-root-invalid-shadow);
  --frame-input-otp-slot-disabled-bg: var(--frame-input-root-disabled-bg);
  --frame-input-otp-slot-disabled-color: var(--frame-input-root-disabled-color);
  --frame-input-otp-slot-disabled-opacity: var(--frame-input-root-disabled-opacity);
  --frame-input-otp-slot-placeholder-color: var(--frame-input-root-placeholder-color);
  --frame-input-otp-separator-color: var(--frame-muted-foreground);
  --frame-input-otp-separator-size: 0.375rem;