OTP
One accessible input with visual code slots and application-owned verification.
Installation
Import the component in your screen:
import { OTP } from '@commenda/pathfinder/otp';Load the stylesheet once in your app root, after host styles:
import '@commenda/pathfinder/styles.css';Pathfinder ships precompiled CSS; no Tailwind setup is required. In Next.js App Router, put interactive state and callbacks in a client component. See installation for the workspace setup.
API reference
| Prop | Type | Behavior |
|---|---|---|
valueConditional | string | Keep leading zeros; controlled mode requires onValueChange |
defaultValue | string | Keep leading zeros; controlled mode requires onValueChange |
length | 4|5|6|7|8 | 6 numeric characters |
groupConfig | ObjectView fields | Six digits use [3, 3]; other lengths use one group. Sizes must sum to length |
onComplete | (code: string) => void | Fires after an edit completes the code; never on mount or blur |
loadingConfig | ObjectView fields | Locks edits, retains form value, announces verification |
labelConditional | string | Visible field label. Supply an accessible name when it is omitted. |
hideLabel | boolean | Visually hide the label while preserving its accessible name. |
aria-labelConditional | string | Accessible name when the field has no visible label. |
requiredConditional | boolean | Mark the field as required. See validation guidance for the component. |
labelConfig | ObjectView fields · 2 shapes | Choose either optionalLabel or help, never both. never excludes the other field. |
description | string | Supporting guidance associated with the field. |
errorConfig | ObjectView fields | Validation message and when it becomes visible. |
disableConfig | DisableConfigView fields | Disabled state with an optional explanation. |
onValueChangeConditional | (value: string) => void | — |
groupConfigObject fields
| Field | Type | Requirement |
|---|---|---|
sizes | readonly number[] | Required |
loadingConfigObject fields
| Field | Type | Requirement |
|---|---|---|
isLoading | boolean | Required |
label | string | Optional |
labelConfigObject fields
Choose one of these 2 shapes. Do not combine fields excluded by the selected shape.
Option 1
| Field | Type | Requirement |
|---|---|---|
optionalLabel | string | Required |
Do not supply: help.
Option 2
| Field | Type | Requirement |
|---|---|---|
help | string | Required |
Do not supply: optionalLabel.
errorConfigObject fields
| Field | Type | Requirement |
|---|---|---|
message | string | Required |
reveal | "after-blur" | "immediate" | Optional |
disableConfigObject fields
| Field | Type | Requirement |
|---|---|---|
isDisabled | boolean | Required |
reason | string | Optional |
Shared label, hideLabel, description, required, errorConfig, disableConfig, and readOnly follow Input. The underlying input-otp primitive is private.
Grouping
Verification
The application starts verification from onComplete, owns pending/error state, and clears its previous server error in onValueChange. Do not submit a form automatically from both onComplete and a separate input handler. Guard against a previous request completing after the user has edited the code; associate the response with the submitted code or request ID.
States
Paste fills the code, Backspace edits the previous slot, and leading zeros remain strings. Read composite field rules for Figma provenance and accessibility rules.
Design rules
Figma guidance and reviewed implementation decisions for this component. Rule IDs remain stable for source comments and AI references.
OTP
- OTP-001: Default six 36px slots in two groups of three; radius 6, 15px medium digits. Other supported lengths are 4–8.
- OTP-002: One accessible native input; numeric string values preserve leading zeros, paste, and one-time-code autocomplete. Slots are presentational.
- OTP-003: Completion emits an event. The application verifies the code, handles stale responses, and clears server errors on edit. Figma's auto-submit wording is implemented as
onComplete, with no implicit form submission. - OTP-004: Loading makes the input read-only and announces verification without dropping its native form value. Disabled fields do not submit.
Shared rules
Labels activate the first input. Descriptions, disabled reasons, and validation messages stay associated with the field. Error icons center on the first 18px text line, including wrapped messages. Controlled values require callbacks; uncontrolled form resets restore defaults. Public props expose application values, never private primitive or calendar objects. Styles ship precompiled for React 18/19 and Next.js consumers.