PinField is a form component for entering PIN codes, verification codes, or other fixed-length character sequences. It provides individual input boxes for each character.
Basic usage
import { PinField } from 'reshaped';
function Example() {
return (
<PinField
name="pin"
valueLength={4}
/>
);
}
Controlled component
import { useState } from 'react';
import { PinField } from 'reshaped';
function ControlledExample() {
const [value, setValue] = useState('');
return (
<PinField
name="code"
valueLength={6}
value={value}
onChange={({ value }) => setValue(value)}
/>
);
}
Uncontrolled component
import { PinField } from 'reshaped';
function UncontrolledExample() {
return (
<PinField
name="verification"
valueLength={6}
defaultValue="123"
onChange={({ name, value }) => console.log(name, value)}
/>
);
}
Pattern types
import { PinField } from 'reshaped';
// Numeric only (default)
<PinField
name="numeric"
valueLength={4}
pattern="numeric"
/>
// Alphabetic only
<PinField
name="alphabetic"
valueLength={4}
pattern="alphabetic"
/>
// Alphanumeric
<PinField
name="alphanumeric"
valueLength={6}
pattern="alphanumeric"
/>
import { PinField } from 'reshaped';
<PinField size="small" name="small" valueLength={4} />
<PinField size="medium" name="medium" valueLength={4} />
<PinField size="large" name="large" valueLength={4} />
<PinField size="xlarge" name="xlarge" valueLength={4} />
Variants
import { PinField } from 'reshaped';
<PinField variant="outline" name="outline" valueLength={4} />
<PinField variant="faded" name="faded" valueLength={4} />
With FormControl
import { FormControl, PinField } from 'reshaped';
function FormExample() {
return (
<FormControl>
<FormControl.Label>Verification code</FormControl.Label>
<PinField
name="verificationCode"
valueLength={6}
/>
<FormControl.Helper>
Enter the 6-digit code sent to your email.
</FormControl.Helper>
</FormControl>
);
}
Validation
import { FormControl, PinField } from 'reshaped';
import { useState } from 'react';
function ValidationExample() {
const [value, setValue] = useState('');
const hasError = value.length > 0 && value.length < 6;
return (
<FormControl hasError={hasError}>
<FormControl.Label>Two-factor authentication</FormControl.Label>
<PinField
name="twoFactor"
valueLength={6}
value={value}
onChange={({ value }) => setValue(value)}
/>
<FormControl.Error>
Please enter all 6 digits.
</FormControl.Error>
</FormControl>
);
}
OTP verification example
import { PinField, View, Text, Button } from 'reshaped';
import { useState } from 'react';
function OTPExample() {
const [code, setCode] = useState('');
const [isVerifying, setIsVerifying] = useState(false);
const handleVerify = async () => {
if (code.length === 6) {
setIsVerifying(true);
// Verify code...
setIsVerifying(false);
}
};
return (
<View gap={4}>
<View gap={2}>
<Text weight="medium" variant="body-1">
Enter verification code
</Text>
<Text variant="body-2" color="neutral-faded">
We sent a 6-digit code to your phone
</Text>
</View>
<PinField
name="otp"
valueLength={6}
value={code}
onChange={({ value }) => setCode(value)}
pattern="numeric"
/>
<Button
onClick={handleVerify}
disabled={code.length !== 6 || isVerifying}
>
{isVerifying ? 'Verifying...' : 'Verify'}
</Button>
</View>
);
}
Accessibility
PinField follows accessibility best practices:
- Each input has proper ARIA attributes
- Keyboard navigation between inputs (Arrow keys, Backspace)
- Automatic focus management
- Screen reader friendly
- Paste support for complete codes
Name of the input element
Amount of characters in the pin
Value of the input element, enables controlled mode
Default value of the input element, enables uncontrolled mode
pattern
'alphabetic' | 'numeric' | 'alphanumeric'
Character pattern used in the input value
size
'small' | 'medium' | 'large' | 'xlarge'
Component size. Supports responsive values.
Input fields render variant
onChange
(args: { name: string, value: string }) => void
Callback when the input value changes
Additional classname for the root element
Additional attributes for the root element
Additional attributes for the input elements. Use for ARIA attributes.