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/warpUsage
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
| Prop | Type | Default | Description |
|---|---|---|---|
label | unknown | '6-digit code' | Its accessible name. Fields show it; icon-only controls speak it. |
name | string | — | The name it posts under in a form. |
length | number | 6 | How many digits. |
hint | unknown | — | One line of help under the control. |
error | unknown | — | 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. |
autoSubmit | boolean | true | Submits the form on the last digit. |
masked | boolean | false | Shows dots. |
id | string | — | The element id. One is made for you if you leave it out. |
| Event | Type | Default | Description |
|---|---|---|---|
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