Skip to content
weftGitHub

OtpField

A one-time code input, drawn as cells. One tab stop, and paste works.

SourcePackage @weft-js/warp

Preview

tsx
import { OtpField } from '@weft-js/warp'export function Four() {  return (    <OtpField label="4-digit PIN" length={4} masked autoSubmit={false} />  )}

Installation

npm install @weft-js/warp

Usage

tsx
import { OtpField } from '@weft-js/warp'<OtpField label="4-digit PIN" length={4} masked autoSubmit={false} />

Checking a code

Type 123456 for the success cascade, anything else for the error.

tsx
import { state } from '@weft-js/core'import { OtpField } from '@weft-js/warp'export function Check() {  const status = state<'idle' | 'checking' | 'success'>('idle')  const error = state<string | undefined>(undefined)  const check = async (code: string) => {    status.value = 'checking'    await wait(700)    status.value = code === '123456' ? 'success' : 'idle'    error.value = code === '123456' ? undefined : "That code didn't work. Try 123456."  }  return <OtpField hint="The sample code is 123456." status={status.value} error={error.value} autoSubmit={false} onComplete={c => void check(c)} />}const wait = (ms: number) => new Promise(done => { setTimeout(done, ms) })

Accessibility

  • It is one real input painted into cells, so SMS autofill and native editing just work.

API Reference

PropTypeDefaultDescription
labelunknown'6-digit code'Its accessible name. Fields show it; icon-only controls speak it.
namestring—The name it posts under in a form.
lengthnumber6How many digits.
hintunknown—One line of help under the control.
errorunknown—Pins every cell critical, clears them and refocuses; the message stays until the next key.
status"idle" | "checking" | "success"—checking while verifying, success for the cascade.
autoSubmitbooleantrueSubmits the form on the last digit.
maskedbooleanfalseShows dots.
idstring—The element id. One is made for you if you leave it out.
EventTypeDefaultDescription
onComplete((code: string) => void)—Called with the whole code.
onValueChange((code: string) => void)—Called on each change.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="stack"] [data-part="code-label"]

code-labelsepcellsweep-basesweepcharmessage

RelatedOtp stepMfa setup