Detent web components
By Shane Logsdon

Forms & inputs

OTP Input

Implemented

Auto-advancing digit boxes with pop feedback

detent-otp-input

Port status
Catalog status
implemented
Origin
upstream
Phase
3
Wave
phase-3-forms
Group
Forms & inputs

4.8 KB gzip for the class module

Variants

Recorded states

  • disabled recorded state; no setter

Usage

Import

import '/components/otp-input/define.js';

// or register it yourself
import { DetentOtpInput } from '/components/otp-input/otp-input.js';

Attributes

  • auto-focus
  • default-value
  • disabled
  • length
  • name
  • required
  • value

Properties

  • value
  • defaultValue
  • length
  • autoFocus
  • disabled
  • required
  • name
  • onChange
  • onComplete

Slots

No slots are recorded for this component.

Events

  • detent-change — { value: string }
  • detent-complete — { value: string }

Example

Runnable example: site/examples/otp-input.ts. The snippet below is generated from the catalogued attributes.

<detent-otp-input
  auto-focus
  default-value
  disabled
  length="6"
  name
  required
  value
></detent-otp-input>

Property-only values

const element = document.querySelector('detent-otp-input');
if (element !== null) {
  // onChange: (value: string) => void
  element.onChange = () => {};
  // onComplete: (value: string) => void
  element.onComplete = () => {};
}

Source

The pinned upstream source for this row:

  • src/components/ui/OtpInput.tsx sha256 ea638dea9245…

Native files

The native module and its artifacts:

  • src/components/otp-input/otp-input.ts
  • src/components/otp-input/styles.css
  • src/components/otp-input/define.ts
  • docs/components/otp-input.md
  • site/examples/otp-input.ts
  • tests/browser/otp-input.spec.ts
  • evidence/components/otp-input.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
auto-focusautoFocusbooleanfalsePresence semantics: present means true, absent means false.
default-value———Recorded in the catalog as an attribute.
disableddisabledbooleanfalsePresence semantics: present means true, absent means false.
lengthlengthnumber6Kebab-case attribute; camelCase property.
name———Recorded in the catalog as an attribute.
required———Recorded in the catalog as an attribute.
valuevaluestringundefinedKebab-case attribute; camelCase property.

Properties

Properties
PropertyTypeDefaultNotes
valuestringundefinedProperty-only: assign from script; not accepted as an attribute.
defaultValue——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
lengthnumber6Property-only: assign from script; not accepted as an attribute.
autoFocusbooleanfalseProperty-only: assign from script; not accepted as an attribute.
disabledbooleanfalseProperty-only: assign from script; not accepted as an attribute.
required——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
name——Recorded in the catalog without a top-level type; pinned from source when the row is ported.
onChange(value: string) => voidundefinedProperty-only: assign from script; not accepted as an attribute.
onComplete(value: string) => voidundefinedProperty-only: assign from script; not accepted as an attribute.

Events

Events
EventUpstream propPayload typeNotes
detent-changeonChange(value: string) => voidComposed, bubbles; fires only for a user action.
detent-completeonComplete(value: string) => voidComposed, bubbles; fires only for a user action.

Slots

No slots are recorded for this component.

CSS customisation

  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • Controlled/uncontrolled React pair maps to initial-value attributes plus owned state and change events.
  • `length` is validated 1-12; invalid input warns once and resolves to 6 (PC-3.4); a length change rebuilds the boxes.
  • The per-digit pop is a 240ms CSS keyframe instead of springSnappy (PC-10.4).
  • Disabled boxes are muted by border and background, not opacity, so digits keep their contrast.
  • `box-class-name` is dropped (a React class prop); the box surface is parts and custom properties.
  • Native additions: value, default-value, name, required, form association, reset/restore and validity.

What it does

A one-time-code input made of separate digit boxes, with paste handling, keyboard navigation and form submission.

Upstream behaviour
  • Auto-advances focus to the next box as each digit is entered
  • Backspace clears the current digit or steps back into the previous box
  • Full-code paste support, distributing pasted digits across all boxes
  • Per-digit spring pop animation on entry for tactile feedback
  • Works as a controlled or uncontrolled component
Differences from upstream
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React callback props become typed composed CustomEvents; programmatic state assignment emits none.
  • Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • Controlled/uncontrolled React pair maps to initial-value attributes plus owned state and change events.
  • `length` is validated 1-12; invalid input warns once and resolves to 6 (PC-3.4); a length change rebuilds the boxes.
  • The per-digit pop is a 240ms CSS keyframe instead of springSnappy (PC-10.4).
  • Disabled boxes are muted by border and background, not opacity, so digits keep their contrast.
  • `box-class-name` is dropped (a React class prop); the box surface is parts and custom properties.
  • Native additions: value, default-value, name, required, form association, reset/restore and validity.
Previous: Dropdown Next: Package Box

Docs

Components

Project