OTP Field
A one-time password input composed of individual character slots.
Enter the 6-character code we sent to your device.
Usage guidelines
- Form controls must have an accessible name: It can be created using a
<label>element or theFieldcomponent. See Labeling an OTP field and the forms guide.
Anatomy
Import the component and assemble its parts:
Examples
Labeling an OTP field
Pass an id to <OTPField.Root> and use a native <label> with a matching for. Let the
first input use the field label, and add aria-label to the remaining inputs so assistive
technology can announce which slot is focused.
Optionally, add aria-describedby when supporting text should be announced with the field.
Form integration
Use Field to handle label associations and form integration:
Pass autoSubmit to submit the owning form automatically when all slots are filled, or use onValueComplete to react to completion without submitting.
Alphanumeric verification codes
Use validationType="alphanumeric" for recovery, backup, or invite codes that mix letters and
numbers.
Accept letters and numbers for backup codes such as A7C9XZ.
Grouped layouts
Wrap subsets of inputs in your own layout elements and use <OTPField.Separator> when you
want the code presented in smaller visual chunks such as 123-456.
Placeholder hints
<OTPField.Input> is a real input, so native placeholder props and CSS work as usual. This
example keeps placeholder hints visible until the active slot receives focus.
Placeholder hints can stay visible until the active slot is focused.
Custom normalization
Use normalizeValue to normalize accepted values before state updates, such as converting
alphanumeric codes to uppercase. It runs after validationType filtering, and the result is filtered
against validationType again. Use validationType="none" when the normalizer should provide the
full validation rule.
Pair custom rules with inputmode for keyboard hints and onValueInvalid for rejected characters.
Letters and digits only. Letters are converted to uppercase.
Masked entry
Use mask when the code should be obscured while it is being typed.
Use mask to obscure the code on shared screens.
API reference
Root
Groups all OTP field parts and manages their state. Renders a <div> element and a visually hidden validation input.
id string | null โ
- Name
- Description
The id of the first input element. Later slots use
{id}-2,{id}-3, and so on.- Type
string | null
autocomplete FullAutoFill | null 'one-time-code'
- Name
- Description
The input autocomplete attribute. Applied to the first slot and hidden validation input.
- Type
FullAutoFill | null- Default
'one-time-code'
form string | null โ
- Name
- Description
Identifies the form that owns the hidden input and the slots. The value must match a form element's id in the same document.
- Type
string | null
length* number โ
- Name
- Description
The number of OTP input slots. Required so the root can clamp values, detect completion, and render validation markup before every slot has mounted.
- Type
number
autoSubmit boolean false
- Name
- Description
Whether to submit the owning form when the OTP becomes complete.
- Type
boolean- Default
false
mask boolean false
- Name
- Description
Whether the slot inputs should mask entered characters. Pass
typeon an individual input to override that slot.- Type
boolean- Default
false
inputmode "text" | "none" | "search" | "email" | "tel" | "url" | "numeric" | "decimal" | null โ
- Name
- Description
Virtual keyboard hint for the slots and the hidden validation input.
- Type
"text" | "none" | "search" | "email" | "tel" | "url" | "numeric" | "decimal" | null
validationType OTPFieldValidationType 'numeric'
- Name
- Description
Which characters the OTP accepts.
- Type
OTPFieldValidationType- Default
'numeric'
normalizeValue function โ
- Name
- Description
Normalizes the OTP value after whitespace and
validationTypefiltering. The result is filtered again, then clamped tolength. It should be idempotent.- Type
(value: string) => string
required boolean | null false
- Name
- Description
Whether the user must enter a value before submitting a form.
- Type
boolean | null- Default
false
disabled boolean | null false
- Name
- Description
Whether the component should ignore user interaction.
- Type
boolean | null- Default
false
readonly boolean | null false
- Name
- Description
Whether the user should be unable to change the field value.
- Type
boolean | null- Default
false
name string | null โ
- Name
- Description
Identifies the field when a form is submitted.
- Type
string | null
value string โ
- Name
- Description
The OTP value. Use
bind:valueto share it with the parent.- Type
string- Binding
bind:value
defaultValue string ''
- Name
- Description
The value an empty
valuestarts from, as on an HTML input.- Type
string- Default
''
onValueChange function โ
- Name
- Description
Called when the OTP value changes.
eventDetails.cancel()vetoes the change.eventDetails.reasonisinput-change,input-clear,input-paste, orkeyboard.- Type
(value: string, eventDetails: OTPFieldChangeEventDetails) => void
onValueInvalid function โ
- Name
- Description
Called when typed or pasted text contains characters rejected before the value updates.
valueis the attempted string before normalization.- Type
(value: string, eventDetails: OTPFieldInvalidEventDetails) => void
onValueComplete function โ
- Name
- Description
Called when the OTP becomes complete, or when a complete value is pasted over a complete OTP. When the value changes, it runs after that change is stored.
autoSubmitsubmits just after.- Type
(value: string, eventDetails: OTPFieldCompleteEventDetails) => void
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: OTPFieldRootState, children: Snippet | undefined]> โ
- Name
- Description
Replace the default
<div>. Spreadpropsonto the host and renderchildreninside it.- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: OTPFieldRootState, children: Snippet | undefined]>
complete boolean
- Name
complete- Description
Whether all slots are filled.
- Type
boolean
disabled boolean
- Name
disabled- Description
Whether the component should ignore user interaction.
- Type
boolean
length number
- Name
length- Description
The number of OTP input slots.
- Type
number
readOnly boolean
- Name
readOnly- Description
Whether the user should be unable to change the field value.
- Type
boolean
required boolean
- Name
required- Description
Whether the user must enter a value before submitting a form.
- Type
boolean
value string
- Name
value- Description
The OTP value.
- Type
string
touched boolean
- Name
touched- Description
Whether the field has been touched.
- Type
boolean
dirty boolean
- Name
dirty- Description
Whether the field value has changed from its initial value.
- Type
boolean
valid boolean | null
- Name
valid- Description
Whether the field is valid.
nullmeans validity is not known yet.- Type
boolean | null
filled boolean
- Name
filled- Description
Whether the field has a value.
- Type
boolean
focused boolean
- Name
focused- Description
Whether the field is focused.
- Type
boolean
data-disabled
data-readonly
data-required
data-valid
data-invalid
data-dirty
data-touched
data-complete
data-filled
data-focused
Input
An individual OTP character input. Renders an <input> element.
render Snippet<[props: HTMLInputAttributes, state: OTPFieldInputState, children: Snippet | undefined]> โ
- Name
- Description
Replace the default
<input>. Spreadpropsonto the host.- Type
Snippet<[props: HTMLInputAttributes, state: OTPFieldInputState, children: Snippet | undefined]>
filled boolean
- Name
filled- Description
Whether this input contains a character.
- Type
boolean
index number
- Name
index- Description
The input index.
- Type
number
value string
- Name
value- Description
The character rendered in this slot.
- Type
string
disabled boolean
- Name
disabled- Description
Whether the component should ignore user interaction.
- Type
boolean
required boolean
- Name
required- Description
Whether the user must enter a value before submitting a form.
- Type
boolean
readOnly boolean
- Name
readOnly- Description
Whether the user should be unable to change the field value.
- Type
boolean
touched boolean
- Name
touched- Description
Whether the field has been touched.
- Type
boolean
dirty boolean
- Name
dirty- Description
Whether the field value has changed from its initial value.
- Type
boolean
valid boolean | null
- Name
valid- Description
Whether the field is valid.
nullmeans validity is not known yet.- Type
boolean | null
focused boolean
- Name
focused- Description
Whether the field is focused.
- Type
boolean
complete boolean
- Name
complete- Description
Whether all slots are filled.
- Type
boolean
length number
- Name
length- Description
The number of OTP input slots.
- Type
number
data-disabled
data-readonly
data-required
data-valid
data-invalid
data-dirty
data-touched
data-complete
data-filled
data-focused
Separator
A separator element accessible to screen readers. Renders a <div>.
orientation "horizontal" | "vertical" 'horizontal'
- Name
- Description
The orientation of the separator.
- Type
"horizontal" | "vertical"- Default
'horizontal'
render Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SeparatorState, children: Snippet | undefined]> โ
- Name
- Description
Replace the default
<div>. Spreadpropsonto the host element.- Type
Snippet<[props: HTMLAttributes<HTMLDivElement>, state: SeparatorState, children: Snippet | undefined]>
orientation 'horizontal' | 'vertical'
- Name
orientation- Description
The orientation of the separator.
- Type
'horizontal' | 'vertical'