Component

Input OTP

A one-time-code field split into individual slots. Set the length and accepted pattern, group slots with separators, size and colour them, and read the value through two-way binding, forms, or the complete event.

Grouped 6-digit code

Value: —

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { HbInputOtpImports } from '@herbst/ui';

@Component({
  selector: 'hb-demo-input-otp-basic',
  imports: [HbInputOtpImports],
  template: `
    <div class="flex flex-col gap-3">
      <hb-input-otp [(hbValue)]="code" [hbMaxLength]="6" (hbComplete)="done.set($event)">
        <hb-input-otp-group>
          <hb-input-otp-slot [hbIndex]="0" />
          <hb-input-otp-slot [hbIndex]="1" />
          <hb-input-otp-slot [hbIndex]="2" />
        </hb-input-otp-group>
        <hb-input-otp-separator />
        <hb-input-otp-group>
          <hb-input-otp-slot [hbIndex]="3" />
          <hb-input-otp-slot [hbIndex]="4" />
          <hb-input-otp-slot [hbIndex]="5" />
        </hb-input-otp-group>
      </hb-input-otp>

      <p class="font-mono text-[12px] text-muted-foreground">
        Value: {{ code() || '—' }}{{ done() ? ' · complete' : '' }}
      </p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HbDemoInputOtpBasicComponent {
  protected readonly code = signal('');
  protected readonly done = signal('');
}

Alphanumeric & large

Status, readonly & disabled

API reference

hb-input-otp

PropertyDescriptionTypeDefault
[hbMaxLength] Total number of characters — match it to the number of slots. number 6
[(hbValue)] The entered code as a string. Also works as a form control via ngModel / formControl. string ''
[hbPattern] Accepted characters, as a preset or a RegExp matching one character. 'digits' | 'chars' | 'alphanumeric' | RegExp 'digits'
[hbSize] / [hbStatus] Slot dimensions and validation colouring, forwarded to every slot. size xs–xl / default|success|warning|error 'md' / 'default'
[hbInvalid] / [hbRing] Force the error look, and toggle the active-slot ring. boolean false / true
[hbDisabled] / [hbReadonly] Block editing entirely, or show a fixed value that cannot be changed. boolean false
[hbAutoFocus] / [hbName] / [hbInputId] / [hbAriaLabel] Focus on render, and forward name, id, and aria-label to the underlying input. boolean / string false / ''
(hbChange) / (hbComplete) Emit on every change, and once when the code reaches hbMaxLength. string

Parts

PropertyDescriptionTypeDefault
hb-input-otp-group Groups a run of slots; use several with separators between them. component
hb-input-otp-slot [hbIndex] A single character cell, bound to its position in the value. number required
hb-input-otp-separator A visual divider between groups; projects a dash icon by default. component