Added a new authentication screen with PIN, Fingerprint, and Face ID options.

Improved UI design and usability using a clean keypad layout and Ionicons.
This commit is contained in:
mansi-dev
2026-01-09 22:59:19 +05:30
parent 967e70b72d
commit c8504e1ac1
3 changed files with 327 additions and 34 deletions

181
App.tsx
View File

@@ -1,45 +1,166 @@
/** import React, { useState } from 'react';
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
*/
import { NewAppScreen } from '@react-native/new-app-screen';
import { StatusBar, StyleSheet, useColorScheme, View } from 'react-native';
import { import {
SafeAreaProvider, View,
useSafeAreaInsets, Text,
} from 'react-native-safe-area-context'; StyleSheet,
TouchableOpacity,
SafeAreaView,
} from 'react-native';
import Ionicons from '@react-native-vector-icons/ionicons';
function App() { const PIN_LENGTH = 4;
const isDarkMode = useColorScheme() === 'dark';
const App: React.FC = () => {
const [pin, setPin] = useState('');
const handlePress = (value: string) => {
if (pin.length < PIN_LENGTH) {
setPin(pin + value);
}
};
const handleDelete = () => {
setPin(pin.slice(0, -1));
};
return ( return (
<SafeAreaProvider> <SafeAreaView style={styles.container}>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} /> <Text style={styles.title}>Verify Identity</Text>
<AppContent /> <Text style={styles.subtitle}>
</SafeAreaProvider> Use PIN, Fingerprint or Face ID
); </Text>
}
function AppContent() { {/* PIN DOTS */}
const safeAreaInsets = useSafeAreaInsets(); <View style={styles.pinRow}>
{Array.from({ length: PIN_LENGTH }).map((_, i) => (
return ( <View
<View style={styles.container}> key={i}
<NewAppScreen style={[
templateFileName="App.tsx" styles.pinDot,
safeAreaInsets={safeAreaInsets} pin.length > i && styles.pinDotFilled,
]}
/> />
))}
</View> </View>
);
}
{/* BIOMETRIC OPTIONS */}
<View style={styles.bioRow}>
<TouchableOpacity style={styles.bioBtn}>
<Ionicons name="finger-print" size={36} color="#2563EB" />
<Text style={styles.bioText}>Fingerprint</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.bioBtn}>
<Ionicons name="happy-outline" size={36} color="#2563EB" />
<Text style={styles.bioText}>Face ID</Text>
</TouchableOpacity>
</View>
{/* KEYPAD */}
<View style={styles.keypad}>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, '', 0, 'del'].map((item, index) => {
if (item === '') {
return <View key={index} style={styles.key} />;
}
if (item === 'del') {
return (
<TouchableOpacity
key={index}
style={styles.key}
onPress={handleDelete}
>
<Ionicons
name="backspace-outline"
size={26}
color="#333"
/>
</TouchableOpacity>
);
}
return (
<TouchableOpacity
key={index}
style={styles.key}
onPress={() => handlePress(item.toString())}
>
<Text style={styles.keyText}>{item}</Text>
</TouchableOpacity>
);
})}
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#F8FAFF',
alignItems: 'center',
paddingHorizontal: 20,
},
title: {
fontSize: 24,
fontWeight: '700',
marginTop: 40,
color: '#111827',
},
subtitle: {
fontSize: 14,
color: '#6B7280',
marginTop: 6,
},
pinRow: {
flexDirection: 'row',
marginVertical: 28,
},
pinDot: {
width: 14,
height: 14,
borderRadius: 7,
borderWidth: 1.5,
borderColor: '#2563EB',
marginHorizontal: 8,
},
pinDotFilled: {
backgroundColor: '#2563EB',
},
bioRow: {
flexDirection: 'row',
marginBottom: 30,
},
bioBtn: {
alignItems: 'center',
marginHorizontal: 30,
},
bioText: {
marginTop: 6,
fontSize: 12,
color: '#374151',
},
keypad: {
width: '80%',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
},
key: {
width: '33%',
height: 70,
justifyContent: 'center',
alignItems: 'center',
},
keyText: {
fontSize: 26,
fontWeight: '500',
color: '#111827',
}, },
}); });
export default App; export default App;

171
package-lock.json generated
View File

@@ -8,6 +8,7 @@
"name": "authenticationsdk", "name": "authenticationsdk",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@react-native-vector-icons/ionicons": "^12.3.0",
"@react-native/new-app-screen": "0.83.1", "@react-native/new-app-screen": "0.83.1",
"react": "19.2.0", "react": "19.2.0",
"react-native": "0.83.1", "react-native": "0.83.1",
@@ -2924,6 +2925,132 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@react-native-vector-icons/common": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/@react-native-vector-icons/common/-/common-12.4.0.tgz",
"integrity": "sha512-t9W0q+AW7WH1Oj5aEg7wGNXDLZJb5sIVkAWo5qtad3PcbBADqoCdikRK/ToLK+xlB0TxjcuL0T74ogudMkYGeA==",
"license": "MIT",
"dependencies": {
"find-up": "^7.0.0",
"picocolors": "^1.1.1",
"plist": "^3.1.0"
},
"bin": {
"rnvi-update-plist": "lib/commonjs/scripts/updatePlist.js"
},
"engines": {
"node": ">=20.19.0 <21.0.0 || >=22.0.0"
},
"peerDependencies": {
"@react-native-vector-icons/get-image": "^12.3.0",
"react": "*",
"react-native": "*"
},
"peerDependenciesMeta": {
"@react-native-vector-icons/get-image": {
"optional": true
}
}
},
"node_modules/@react-native-vector-icons/common/node_modules/find-up": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz",
"integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==",
"license": "MIT",
"dependencies": {
"locate-path": "^7.2.0",
"path-exists": "^5.0.0",
"unicorn-magic": "^0.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native-vector-icons/common/node_modules/locate-path": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
"integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
"license": "MIT",
"dependencies": {
"p-locate": "^6.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native-vector-icons/common/node_modules/p-limit": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
"integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
"license": "MIT",
"dependencies": {
"yocto-queue": "^1.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native-vector-icons/common/node_modules/p-locate": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
"integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
"license": "MIT",
"dependencies": {
"p-limit": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native-vector-icons/common/node_modules/path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
"integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/@react-native-vector-icons/common/node_modules/yocto-queue": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
"integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
"license": "MIT",
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@react-native-vector-icons/ionicons": {
"version": "12.3.0",
"resolved": "https://registry.npmjs.org/@react-native-vector-icons/ionicons/-/ionicons-12.3.0.tgz",
"integrity": "sha512-H/rlYzUEm0hhwwca2k6VMNjy0rLcjan6iwyaYDXMhsJQl7O4+Qkm7uVd/KEreS5gXfGuntUlcSa9GSn+dYqnjA==",
"license": "MIT",
"dependencies": {
"@react-native-vector-icons/common": "^12.3.0"
},
"engines": {
"node": ">= 18.0.0"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/@react-native/assets-registry": { "node_modules/@react-native/assets-registry": {
"version": "0.83.1", "version": "0.83.1",
"resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.83.1.tgz", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.83.1.tgz",
@@ -3753,6 +3880,15 @@
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@xmldom/xmldom": {
"version": "0.8.11",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz",
"integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/abort-controller": { "node_modules/abort-controller": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -9611,6 +9747,20 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/plist": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
"integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==",
"license": "MIT",
"dependencies": {
"@xmldom/xmldom": "^0.8.8",
"base64-js": "^1.5.1",
"xmlbuilder": "^15.1.1"
},
"engines": {
"node": ">=10.4.0"
}
},
"node_modules/possible-typed-array-names": { "node_modules/possible-typed-array-names": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
@@ -11418,6 +11568,18 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/unicorn-magic": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
"integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/universalify": { "node_modules/universalify": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -11716,6 +11878,15 @@
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"
} }
}, },
"node_modules/xmlbuilder": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
"integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
"license": "MIT",
"engines": {
"node": ">=8.0"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

View File

@@ -10,9 +10,10 @@
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@react-native-vector-icons/ionicons": "^12.3.0",
"@react-native/new-app-screen": "0.83.1",
"react": "19.2.0", "react": "19.2.0",
"react-native": "0.83.1", "react-native": "0.83.1",
"@react-native/new-app-screen": "0.83.1",
"react-native-safe-area-context": "^5.5.2" "react-native-safe-area-context": "^5.5.2"
}, },
"devDependencies": { "devDependencies": {