PinInput
A component for entering PIN codes, OTP, and verification codes.
import { PinInput } from "@ninna-ui/forms"pnpm add @ninna-ui/formsRequires @ninna-ui/core (auto-installed) + CSS setup.
Usage
Import and use the PinInput component in your application.
import { PinInput } from "@ninna-ui/forms";
export default function Example() { return ( <PinInput length={6} onComplete={(pin) => console.log('PIN:', pin)} /> );}Basic
Basic 4-digit PIN input.
Length
PinInput with different number of fields.
4 digits (default)
6 digits
8 digits
Input Types
Text, number, and password input types.
Text (default)
Number only
Password (masked)
Sizes
PinInput in different sizes.
Extra Small
Small
Medium
Large
Extra Large
OTP Mode
6-digit OTP input with number-only mode.
Enter the 6-digit code sent to your phone
Masked
PIN input with masked/hidden values.
Enter your PIN (masked)
States
Different states of the PIN input.
Normal
With Default Value
Disabled
Invalid
React Hook Form
PinInput works with React Hook Form using the Controller pattern.
API Reference
Complete list of props for the PinInput component.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
length | number | 4 | Number of input fields |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Size of the inputs |
type | 'text' | 'password' | 'number' | 'text' | Input type |
mask | boolean | false | Mask input value |
otp | boolean | false | One-time password mode (enables autocomplete) |
value | string | - | Controlled value |
defaultValue | string | - | Default value (uncontrolled) |
onChange | (value: string) => void | - | Callback when value changes |
onComplete | (value: string) => void | - | Callback when all fields are filled |
disabled | boolean | false | Disabled state |
invalid | boolean | false | Invalid state |
placeholder | string | '○' | Placeholder for each field |
autoFocus | boolean | false | Auto focus the first input on mount |
name | string | - | Name for hidden form submission input |
aria-label | string | 'PIN input' | Accessible label for the input group |
Accessibility
- Uses
role="group"with a customizablearia-label(default: "PIN input") - Each input has an
aria-labelindicating its position (e.g. "Pin digit 1 of 6") - Arrow keys navigate between inputs
- Backspace moves to previous input when empty
- Paste support for filling multiple inputs at once
- Proper
aria-invalidandaria-disabledstates - OTP mode enables
autocomplete="one-time-code"