Getting StartedInstall and bootstrap headless foundations 4
LayoutHeadless structural primitives for expandable and container patterns 6
OverlayHeadless modal and floating layer behavior 3
FeedbackHeadless notification and status communication patterns 5
FormHeadless input and selection contracts 17
UtilityReusable action, identity, and clipboard behavior 6
NavigationHeadless trails, trees, menus, and command surfaces 7

Input OTP

[tngInputOtp] is the headless state primitive for OTP roots. You own the actual inputs, keyboard handling, and slot layout while the primitive reflects mirrored state onto the host.

Imports

Primitive import

ts
import {
  TngInputOtp as TngInputOtpPrimitive,
  TngInputOtpSlot,
} from '@tailng-ui/primitives';

Usage baseline

The primitive does not render slots for you, but the root and slot directives coordinate the baseline OTP behavior so your page only owns markup and styling.

Minimal headless composition

html
<div
  tngInputOtp
  [length]="6"
  [value]="verificationCode()"
  (valueChange)="verificationCode.set($event)"
  [activeIndex]="activeIndex()"
  (activeIndexChange)="activeIndex.set($event)"
>
  @for (slotIndex of verificationSlotIndexes; track slotIndex) {
    <input [tngInputOtpSlot]="slotIndex" maxlength="1" inputmode="numeric" />
  }
</div>

OTP variants

Compare the same primitive composition across plain CSS and Tailwind CSS while keeping the slot markup fully owned.

Input OTP (Plain-CSS)

Verification code

Own the slot markup directly while the primitive reflects root state for styling.

Value: 18

State: partial

Behavior baseline

  • You own the slot markup and styling, while the primitive handles baseline OTP keyboard flow.
  • The primitive mirrors combined value state through data-empty, data-partial, and data-complete.
  • valueChange and activeIndexChange let headless pages stay controlled without reimplementing focus movement.