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

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.