Skip to main content
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"
/>

Sizes

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

Props

name
string
required
Name of the input element
valueLength
number
default:"4"
Amount of characters in the pin
value
string
Value of the input element, enables controlled mode
defaultValue
string
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.
variant
'outline' | 'faded'
Input fields render variant
onChange
(args: { name: string, value: string }) => void
Callback when the input value changes
className
string
Additional classname for the root element
attributes
object
Additional attributes for the root element
inputAttributes
object
Additional attributes for the input elements. Use for ARIA attributes.

Build docs developers (and LLMs) love