Installation
npm install @kuzenbo/core @kuzenbo/theme input-otp
Usage
import { InputOTP } from "@kuzenbo/core";
function App() {
return (
<InputOTP maxLength={6}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
);
}
Examples
A 6-digit OTP input.
import { InputOTP } from "@kuzenbo/core";
function BasicExample() {
return (
<InputOTP maxLength={6}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
);
}
With Separator
Visually group digits with a separator.
import { InputOTP } from "@kuzenbo/core";
function SeparatorExample() {
return (
<InputOTP maxLength={6}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
);
}
Controlled Value
Manage the OTP value with React state.
import { InputOTP } from "@kuzenbo/core";
import { useState } from "react";
function ControlledExample() {
const [value, setValue] = useState("");
return (
<div className="grid gap-2">
<InputOTP
maxLength={6}
value={value}
onChange={setValue}
>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
<p className="text-muted-foreground text-sm">
Value: {value || "(empty)"}
</p>
</div>
);
}
Sizes
InputOTP supports size variants.
import { InputOTP } from "@kuzenbo/core";
function SizesExample() {
return (
<div className="grid gap-3">
<InputOTP maxLength={6} size="xs">
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
<InputOTP maxLength={6} size="sm">
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
<InputOTP maxLength={6} size="md">
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
<InputOTP maxLength={6} size="lg">
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
<InputOTP maxLength={6} size="xl">
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
</div>
);
}
Pattern Validation
Restrict input to specific character patterns.
import { InputOTP } from "@kuzenbo/core";
import { REGEXP_ONLY_DIGITS } from "input-otp";
function PatternExample() {
return (
<InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
);
}
Props
InputOTP extends input-otp OTPInput props.
Maximum number of characters (number of slots).
Controlled value of the OTP input.
Callback fired when the value changes.
Callback fired when all slots are filled.
Regular expression pattern to restrict allowed characters.
Size variant of the OTP input.Options: "xs" | "sm" | "md" | "lg" | "xl"
When true, disables the OTP input.
When true, automatically focuses the first slot on mount.
pushPasswordManagerStrategy
Strategy for handling password manager autofill.
Additional CSS classes for the input element.
Additional CSS classes for the container.
InputOTP.Group and InputOTP.Separator components.
Subcomponents
Container for a group of OTP slots.
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
An individual character slot.
Zero-based index of this slot.
A visual separator between groups.
TypeScript
import type {
InputOTPProps,
InputOTPGroupProps,
InputOTPSlotProps,
InputOTPSeparatorProps,
} from "@kuzenbo/core";
const CustomInputOTP = (props: InputOTPProps) => {
return <InputOTP {...props} />;
};
Accessibility
- InputOTP uses semantic input elements
- Supports keyboard navigation between slots
- Auto-advances to next slot on input
- Backspace moves to previous slot
- Paste support for filling multiple slots
- Disabled state prevents all interactions
- Properly announces to screen readers