OTP Field

Forms

A one-time-password input split across several single-character slots.

OTP fields chunk a code into individual boxes for fast, focused entry. Typing advances automatically, and the value can be read or controlled as a single string.

npx shadcn@latest add otp-field

Basic usage

Six slots that fill as the code is typed. onValueChange reports the full value.

Preview
Live

Code: empty

tsx
1const [value, setValue] = useState("")
2
3<OtpField
4 value={value}
5 onValueChange={setValue}
6 length={6}
7 className="flex w-full gap-2"
8>
9 <OtpFieldGroup>
10 <OtpFieldInput aria-label="Digit 1" />
11 <OtpFieldInput aria-label="Digit 2" />
12 <OtpFieldInput aria-label="Digit 3" />
13 </OtpFieldGroup>
14 <OtpFieldSeparator />
15 <OtpFieldGroup>
16 <OtpFieldInput aria-label="Digit 4" />
17 <OtpFieldInput aria-label="Digit 5" />
18 <OtpFieldInput aria-label="Digit 6" />
19 </OtpFieldGroup>
20</OtpField>

Completion

React when the code becomes complete with onValueComplete.

Preview
Live
tsx
1<OtpField
2 length={4}
3 onValueComplete={(value) => {
4 console.log("Code entered:", value)
5 }}
6 className="flex gap-2"
7>
8 <OtpFieldInput aria-label="Digit 1" />
9 <OtpFieldInput aria-label="Digit 2" />
10 <OtpFieldInput aria-label="Digit 3" />
11 <OtpFieldInput aria-label="Digit 4" />
12</OtpField>

API reference

All props of the underlying Base UI primitive are forwarded. The table below documents the Shelf-specific props.

PropTypeDescription
valuestringThe controlled OTP value.
defaultValuestringThe uncontrolled initial value.
onValueChange(value: string) => voidCalled when the value changes.
onValueComplete(value: string) => voidCalled once all slots are filled.
lengthnumberThe number of input slots. Required.
maskboolean= falseMasks the entered characters.