OTP Field
Enter a short verification code in separate or joined slots.
Enter the 6-digit code we sent to your email.
Installation
pnpm dlx shadcn@4.18.0 add @siteplane/otp-fieldComplete the one-time setup first. Registry JSON lists source files and dependencies.
For this page’s examples, also install:
pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/form @siteplane/inputField is installed with Input.
Usage
import { OTPField, OTPFieldInput } from "@/siteplane/components/otp-field";
<OTPField length={4} aria-label="Verification code">
{Array.from({ length: 4 }, (_, index) => (
<OTPFieldInput
key={index}
aria-label={index === 0 ? undefined : `Digit ${index + 1} of 4`}
/>
))}
</OTPField>;Composition
OTPField
├── OTPFieldInput × length
└── OTPFieldSeparator (optional between slots)Grouped slots
Separators do not count toward length. Render exactly the declared number of inputs.
Joined slots
Set layout="joined" to draw the slots as one field instead of separate boxes. The field has the surface and height of an Input, follows size and variant, and separates the characters with thin dividers. States follow the separate boxes: the current slot takes the focus ring inside the field while the field keeps its edge, no slot shows a caret, an invalid field shows the invalid edge, and a disabled field fades.
A joined field fills the width of its container, like an Input. Set a width on OTPField, or on the Field around it, to size it. OTPFieldSeparator still splits the slots into groups.
Enter the 6-digit code we sent to your email.
Alphanumeric codes
Set validationType="alphanumeric" to accept letters and digits, for example for recovery codes.
Enter one of the backup codes you saved when you turned on two-factor authentication.
Controlled value
Use value and onValueChange to own the code. onValueComplete fires once every slot is filled; verify the code in your application.
Enter the code from your authenticator app.
Variants, masking and disabled
Masking only hides the displayed characters. Disabled and readOnly are separate states.
Sizes
Omit size to inherit the provider's control size.
Form integration
Give the Field a name to submit the complete code. autoSubmit can submit the form once all slots are filled.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
OTPField. | separate | joined | separate | One box per slot, or one joined field with the surface of an Input and a divider between the slots. |
OTPField. | sm | md | lg | xl | provider / lg | Slot dimensions; the height of a joined field. |
OTPField. | default | elevated | inset | default | Surface of each slot, or of the joined field. |
OTPField. | string | unset | Creates a hidden Label for the first input unless aria-labelledby is supplied. |
OTPField. | string | generated when aria-label exists | First input ID. |
OTPField | boolean | false | Spelling checks disabled unless overridden. |
length | number | required | Number of input slots. |
value / default | string | uncontrolled | Complete code. |
on | (value, eventDetails) => void | unset | Code-change callback. |
on | (value, eventDetails) => void | unset | Called on completion; does not authenticate. |
on | (value, eventDetails) => void | unset | Reports characters rejected during normalization. |
validation | OTP validation mode | numeric | Allowed characters. |
mask / auto | boolean | false | Mask slots or submit on completion. |
OTPFieldProps, OTPFieldInputProps and OTPFieldSeparatorProps describe
these parts. OTPFieldPrimitive exposes Root, Input and the Base UI Separator.
Styled Separator uses a short horizontal divider and accepts Separator props. A
joined field draws the dividers between its slots itself. Other normalization,
required, readOnly, disabled, autocomplete, name and form contracts follow Base
UI OTP Field. Styled className
values are strings.
Usage notes
Typing, pasting, deletion and slot focus are handled by the component. Give the field and slots meaningful names: the first slot takes the field's label and ignores its own aria-label, so label only the following slots. Never treat a client-side completion callback as verification; server validation and retry/rate limits belong to the application.