
Vertical Step indicator
May 06, 2023
1 min
An UI module for user-side pincode verification.
🔮 Simple and tiny 1.55 KB. Easy to use;
🚮 Clearing part of the code by clicking on the cell;
🍎 Support “fast paste SMS-code” on iOS. And custom code paste for Android;
⚡ TextInput ref support;
🛠 Highly customizable. Can be used as masked TextInput;
🤓 Readable
| Name | Type | Description | Default |
|---|---|---|---|
descriptionText | String | A description text | Please enter pincode for entry |
spaceColor | Color | Color of line under digit | #FF0000 |
closeButtonColor | Color | Color of X - close button | #FF0000 |
onEnteredPincode | Function | A function that returns entered code | - |
onCloseView | Function | On press close button, will be useful to close view | - |
onPressTouchId | Function | Touch Id is not available, but you can make it by yourself | - |
withTouchId | Boolean | If you do not neet touch id, you can set it to false | TRUE |
npm i react-native-code-verification --save --force
import {Animated, Image, SafeAreaView, Text, View} from 'react-native';
import React, {useState} from 'react';
import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import styles, {
ACTIVE_CELL_BG_COLOR,
CELL_BORDER_RADIUS,
CELL_SIZE,
DEFAULT_CELL_BG_COLOR,
NOT_EMPTY_CELL_BG_COLOR,
} from './styles';
const {Value, Text: AnimatedText} = Animated;
const CELL_COUNT = 4;
const source = {
uri:
'https://user-images.githubusercontent.com/4661784/56352614-4631a680-61d8-11e9-880d-86ecb053413d.png',
};
const animationsColor = [...new Array(CELL_COUNT)].map(() => new Value(0));
const animationsScale = [...new Array(CELL_COUNT)].map(() => new Value(1));
const animateCell = ({hasValue, index, isFocused}) => {
Animated.parallel([
Animated.timing(animationsColor[index], {
useNativeDriver: false,
toValue: isFocused ? 1 : 0,
duration: 250,
}),
Animated.spring(animationsScale[index], {
useNativeDriver: false,
toValue: hasValue ? 0 : 1,
duration: hasValue ? 300 : 250,
}),
]).start();
};
const AnimatedExample = () => {
const [value, setValue] = useState('');
const ref = useBlurOnFulfill({value, cellCount: CELL_COUNT});
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value,
setValue,
});
const renderCell = ({index, symbol, isFocused}) => {
const hasValue = Boolean(symbol);
const animatedCellStyle = {
backgroundColor: hasValue
? animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [NOT_EMPTY_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR],
})
: animationsColor[index].interpolate({
inputRange: [0, 1],
outputRange: [DEFAULT_CELL_BG_COLOR, ACTIVE_CELL_BG_COLOR],
}),
borderRadius: animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [CELL_SIZE, CELL_BORDER_RADIUS],
}),
transform: [
{
scale: animationsScale[index].interpolate({
inputRange: [0, 1],
outputRange: [0.2, 1],
}),
},
],
};
// Run animation on next event loop tik
// Because we need first return new style prop and then animate this value
setTimeout(() => {
animateCell({hasValue, index, isFocused});
}, 0);
return (
<AnimatedText
key={index}
style={[styles.cell, animatedCellStyle]}
onLayout={getCellOnLayoutHandler(index)}>
{symbol || (isFocused ? <Cursor /> : null)}
</AnimatedText>
);
};
return (
<SafeAreaView style={styles.root}>
<Text style={styles.title}>Verification</Text>
<Image style={styles.icon} source={source} />
<Text style={styles.subTitle}>
Please enter the verification code{'\n'}
we send to your email address
</Text>
<CodeField
ref={ref}
{...props}
value={value}
onChangeText={setValue}
cellCount={CELL_COUNT}
rootStyle={styles.codeFiledRoot}
keyboardType="number-pad"
textContentType="oneTimeCode"
renderCell={renderCell}
/>
<View style={styles.nextButton}>
<Text style={styles.nextButtonText}>Verify</Text>
</View>
</SafeAreaView>
);
};
export default AnimatedExample;
Coming Soon…
import {StyleSheet, Platform} from 'react-native';
export const CELL_SIZE = 55;
export const CELL_BORDER_RADIUS = 8;
export const DEFAULT_CELL_BG_COLOR = '#fff';
export const NOT_EMPTY_CELL_BG_COLOR = '#3557b7';
export const ACTIVE_CELL_BG_COLOR = '#f7fafe';
const styles = StyleSheet.create({
codeFiledRoot: {
height: CELL_SIZE,
marginTop: 30,
paddingHorizontal: 20,
justifyContent: 'center',
},
cell: {
marginHorizontal: 8,
height: CELL_SIZE,
width: CELL_SIZE,
lineHeight: CELL_SIZE - 5,
fontSize: 30,
textAlign: 'center',
borderRadius: CELL_BORDER_RADIUS,
color: '#3759b8',
backgroundColor: '#fff',
// IOS
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.22,
shadowRadius: 2.22,
// Android
elevation: 3,
},
// =======================
root: {
minHeight: 800,
padding: 20,
},
title: {
paddingTop: 50,
color: '#000',
fontSize: 25,
fontWeight: '700',
textAlign: 'center',
paddingBottom: 40,
},
icon: {
width: 217 / 2.4,
height: 158 / 2.4,
marginLeft: 'auto',
marginRight: 'auto',
},
subTitle: {
paddingTop: 30,
color: '#000',
textAlign: 'center',
},
nextButton: {
marginTop: 30,
borderRadius: 60,
height: 60,
backgroundColor: '#3557b7',
justifyContent: 'center',
minWidth: 300,
marginBottom: 100,
},
nextButtonText: {
textAlign: 'center',
fontSize: 20,
color: '#fff',
fontWeight: '700',
},
});
export default styles;
Quick Links
Legal Stuff





