logoChisa UI

Command Palette

Search for a command to run...

Componentschevron_rightOtpInput

OtpInput

OTP/PIN input with animated focus, cursor, and error shake effects.

9:41
signal_cellular_altwifibattery_full
Enter code: 1234

Installation

$

Usage

Example.tsx
import { OtpInput } from './components/OtpInput';
export default function App() {
const [code, setCode] = useState('');
return (
<OtpInput
length={4}
code={code}
onCodeChanged={setCode}
error={code.length === 4 && code !== '1234'}
/>
);
}

Full Component Code

OtpInput.tsx
1import React, { useEffect, useRef, useState } from 'react';
2import { View, Text, TextInput, StyleSheet } from 'react-native';
3import Animated, { useSharedValue, useAnimatedStyle, withSpring, withSequence, withTiming, withRepeat } from 'react-native-reanimated';
4
5export const OtpInput = ({ length = 4, code = '', onCodeChanged, error = false, secureTextEntry = false }) => {
6 const inputRef = useRef(null);
7 const shake = useSharedValue(0);
8
9 useEffect(() => {
10 if (error) {
11 shake.value = withSequence(withTiming(10, { duration: 50 }), withTiming(-10, { duration: 50 }), withTiming(0, { duration: 50 }));
12 }
13 }, [error]);
14
15 // Note: Detailed cell animation logic (stiffness: 400) would be in the full file
16 return (
17 <Animated.View style={[styles.container, { transform: [{ translateX: shake }] }]}>
18 <TextInput
19 ref={inputRef}
20 value={code}
21 onChangeText={onCodeChanged}
22 maxLength={length}
23 style={styles.hiddenInput}
24 keyboardType="number-pad"
25 />
26 <View style={styles.row} onTouchEnd={() => inputRef.current?.focus()}>
27 {Array.from({ length }).map((_, i) => (
28 <OtpCell
29 key={i}
30 char={code[i]}
31 isActive={i === code.length && inputRef.current?.isFocused()}
32 isError={!!error}
33 secureTextEntry={secureTextEntry}
34 />
35 ))}
36 </View>
37 </Animated.View>
38 );
39};
40
41// ... OtpCell and styles implementation

Props

NameTypeDefaultDescription
lengthnumber4Number of digits
codestring-Current value
onCodeChanged(code: string) => void-Callback
errorboolean | stringfalseError state
secureTextEntrybooleanfalseHide input