Forms & inputs
OTP Input
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
disabledrecorded 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-focusdefault-valuedisabledlengthnamerequiredvalue
Properties
valuedefaultValuelengthautoFocusdisabledrequirednameonChangeonComplete
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.tsxsha256 ea638dea9245…
Native files
The native module and its artifacts:
src/components/otp-input/otp-input.tssrc/components/otp-input/styles.csssrc/components/otp-input/define.tsdocs/components/otp-input.mdsite/examples/otp-input.tstests/browser/otp-input.spec.tsevidence/components/otp-input.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
auto-focus | autoFocus | boolean | false | Presence semantics: present means true, absent means false. |
default-value | — | — | — | Recorded in the catalog as an attribute. |
disabled | disabled | boolean | false | Presence semantics: present means true, absent means false. |
length | length | number | 6 | Kebab-case attribute; camelCase property. |
name | — | — | — | Recorded in the catalog as an attribute. |
required | — | — | — | Recorded in the catalog as an attribute. |
value | value | string | undefined | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
value | string | undefined | Property-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. |
length | number | 6 | Property-only: assign from script; not accepted as an attribute. |
autoFocus | boolean | false | Property-only: assign from script; not accepted as an attribute. |
disabled | boolean | false | Property-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) => void | undefined | Property-only: assign from script; not accepted as an attribute. |
onComplete | (value: string) => void | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-change | onChange | (value: string) => void | Composed, bubbles; fires only for a user action. |
detent-complete | onComplete | (value: string) => void | Composed, 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.