Introduction
In this second part of our multi-part series, we will continue building our multi-page signup/login app in React Native. In this blog, we will cover the following topics:
- Styling components using TailwindCSS
- Creating individual React Native components with the ability to pass props.
You can find the source code on my Github.
Disclaimer: This project is UI-focused, with an emphasis on styling and design. It's a mobile app, but it's not connected to any backend or database, so all the data is hard-coded in the pages. The primary goal of this project is to practice coding and explore various design ideas, with the aim of producing a visually appealing and functional mobile app.
Few steps to follow before we start.
- To keep our reusable React Native components in an organized manner, let's create a folder named
components
. - You can create a folder named
assets
to store images, SVGs, and other static resources that are required in your React Native app.
Design System (colors)
We are going to use the following colors:
- For Backgroud: #fff ie
white
in tailwindcss - For dark text: '#3F3D56'
- For white text: '#f3f4f6'
- Primary Color: '#8B5CF6' ie
blue-500
in tailwindcss - bgGray: '#e4e4e7'
To use colors more conveniently in Tailwind CSS classes, we can add them to the Tailwind config file:
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./App.{js,jsx,ts,tsx}",
"./components/*.{js,jsx,ts,tsx}",
"./pages/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
textDark: "#3F3D56",
},
},
},
plugins: [],
};
To ensure that we can apply Tailwind CSS to the components that will be present inside the components
directory, we have included this directory in the content section of the Tailwind CSS configuration file.
To style components using props, we will also use React Native Stylesheet. To define all the necessary color values, we will create a colors.js
file in the assets/folder
.
assets/colors.js
export default {
textDark: "#3F3D56",
textWhite: "#f3f4f6",
primary: "#8B5CF6",
bgGray: "#e4e4e7",
};
Creating Heading Component.
Creating a Header Text
that will be visible on all the pages.
Greeting.tsx
<Text className="text-textDark text-4xl font-extrabold">CodeGenius</Text>
To ensure reusability of the Heading component across all pages, it is best practice to create a separate component file for it.
Create a Heading component components/Heading.tsx
.
import { Text } from "react-native";
import React from "react";
export default function Heading(props) {
return (
<Text className="text-textDark text-4xl font-extrabold">
{props.content}
</Text>
);
}
We will make the Heading component reusable by passing text as a prop, enabling us to use the same component for displaying headings with different text.
We will import the reusable Heading
component in pages/Greeting.tsx
and pass the content prop to it, as shown below:
import Heading from "../components/Heading";
const Greeting = ({ navigation }) => {
return (
<SafeAreaView className="bg-white container h-full px-7">
<Heading content="CodeGenius" />
<View className="mt-6">
<TouchableOpacity
className="mt-3 rounded-xl py-3"
style={{ elevation: 1, backgroundColor: colors.primary }}
onPress={() => navigation.navigate("Login")}
>
<Text
className="text-center text-base"
style={{ color: colors.textWhite }}
>
Login
</Text>
</TouchableOpacity>
<CustomButton
navigation={navigation}
bgColor={colors.bgGray}
textColor={colors.textDark}
goto={"Signup"}
content={"Singup"}
/>
</View>
</SafeAreaView>
);
};
This is how our application looks now:
Fig. 1 - Heading Component
Hero image
While there are plenty of image and vector art resources available online, we'll be using an image from undraw for this demonstration. First, download the image and save it in the assets folder of your project. Then, follow these steps to add the vector art to your project.
pages/Greeting.tsx
<View className="flex justify-center items-center mt-24">
<Image
source={require('./../assets/hero.png')}
style={{width: 400, height: 300}}
/>
</View>
<Heading content="CodeGenius" />
Fig. 2 - Hero Component
Buttons
Writing code for resusable button component.
The CustomButton component in our code has been designed to be reusable in different ways. We can customize the button's appearance and functionality by passing values to different props. For example, we can use the "navigation" prop to navigate to a different page, set the background color with "bgColor" prop, set the text color with "textColor" prop, set the text content with "content" prop, and set the navigation destination with "goto" prop. By using these different props in different combinations, we can create a CustomButton component that meets our specific requirements. This allows us to create buttons quickly and efficiently for various parts of our application without having to write new code each time.
compnents/CustomButton.tsx
import { TouchableOpacity, Text } from "react-native";
import React from "react";
const CustomButton = props => {
return (
<TouchableOpacity
className="mt-3 rounded-xl py-3"
style={{ elevation: 1, backgroundColor: props.bgColor }}
onPress={() => props.navigation.navigate(props.goto)}
>
<Text
className="text-center text-base"
style={{ color: props.textColor }}
>
{props.content}
</Text>
</TouchableOpacity>
);
};
export default CustomButton;
With the reusable CustomButton component we have created, we can create multiple buttons with different colors and text using props. By passing different values to the bgColor and textColor props, we can create buttons with different color schemes. Additionally, we can change the text displayed on the button by passing the desired text to the content prop. We can also use the goto prop to specify the page that the button should navigate to when it is clicked. By utilizing these props in different combinations, we can create custom buttons according to our needs.
<CustomButton
navigation={navigation}
bgColor={'#f87171'}
textColor={'#fff'}
goto={'Signup'}
content={'Hello'}
/>
<CustomButton
navigation={navigation}
bgColor={'#059669'}
textColor={'#fff'}
goto={'Signup'}
content={'Click Here'}
/>
<CustomButton
navigation={navigation}
bgColor={colors.primary}
textColor={colors.textWhite}
goto={'Login'}
content={'Login'}
/>
<CustomButton
navigation={navigation}
bgColor={colors.bgGray}
textColor={colors.textDark}
goto={'Signup'}
content={'Singup'}
/>
Fig. 3 - Buttons
Form elements
In this section, we will be styling a form that includes the following elements:
- Text inputs for entering first name, last name, email, and password.
- A signup button to create a new account.
- Google and Facebook buttons to login with those accounts.
- A link to the login page for users who already have an account.
The form will provide a simple and user-friendly way for users to sign up for our service and log in using their preferred method. By incorporating popular social media platforms, we can make the process more convenient for users and potentially attract more users to our platform. The text inputs will allow users to provide their basic information securely, and the signup button will complete the registration process. If users already have an account, they can easily access it through the login page linked in the form.
Text inputs
Creating a text input for First Name
. We will use useState
hook which is a built-in hook in React/Reat-Native that allows functional components to have state variables and update them. It takes an initial value and returns an array with two elements: the current state value and a function to update it. This means that you can update the data within your component and React will automatically re-render the component to reflect the changes.
pages/Signup.tsx
const [firstName, setFirstName] = useState("");
The TextInput component is used to take input from keyboard in react native.
<TextInput
onChangeText={setFirstName}
placeholder={"First Name"}
placeholderTextColor={colors.textDark}
value={firstName}
className="bg-zinc-200 text-textgray rounded-xl py-3 px-5"
/>
When the user types something into the input field, the setFirstName
function is called with the new value as an argument, and the firstName
state variable is updated with that value. The placeholder
prop sets the initial text displayed in the input field, while the value
prop sets the current value of the input field. The className
prop sets the CSS classes used for styling the input field, in this case a light gray background, dark text, and rounded corners.
In the same way we can create multiple text inputs like Last Name, Email and password.
Social buttons
Creating a functional component called "SocialIcons" that displays two TouchableOpacity buttons with Google and Facebook logos as images.
components/SocialIcons.tsx
import { View, TouchableOpacity, Image } from "react-native";
import React from "react";
const SocialIcons = () => {
return (
<View className="flex flex-row items-center justify-center">
<TouchableOpacity className="bg-zinc-200 mx-2 rounded-lg px-16 py-2">
<Image
source={require("./../assets/google.png")}
style={{ width: 30, height: 30 }}
/>
</TouchableOpacity>
<TouchableOpacity className="bg-zinc-200 mx-2 rounded-lg px-16 py-2">
<Image
source={require("./../assets/facebook.png")}
style={{ width: 30, height: 30 }}
/>
</TouchableOpacity>
</View>
);
};
export default SocialIcons;
Complete Signup Page Code
pages/Signup.tsx
import { View, Text, TouchableOpacity, TextInput } from "react-native";
import { useState } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import Heading from "../components/Heading";
import CustomButton from "../components/CustomButton";
import colors from "../assets/colors";
import SocialIcons from "../components/SocialIcons";
const Signup = ({ navigation }) => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
return (
<SafeAreaView className="bg-white container h-full px-7">
<View className="mt-24">
<Heading content="Create Account" />
</View>
<View className="mt-4">
<TextInput
onChangeText={setFirstName}
placeholder={"First Name"}
placeholderTextColor={colors.textDark}
value={firstName}
className="bg-zinc-200 text-textgray rounded-xl py-3 px-5"
/>
<TextInput
onChangeText={setLastName}
placeholder={"Last Name"}
placeholderTextColor={colors.textDark}
value={lastName}
className="bg-zinc-200 text-textgray mt-3 rounded-xl py-3 px-5"
// style={{color: '#000000'}}
/>
<TextInput
onChangeText={setEmail}
placeholder={"Email"}
placeholderTextColor={colors.textDark}
value={email}
className="bg-zinc-200 text-textgray mt-3 rounded-xl py-3 px-5"
/>
<TextInput
secureTextEntry={true}
onChangeText={setPassword}
placeholder={"Password"}
placeholderTextColor={colors.textDark}
value={password}
className="bg-zinc-200 text-textgray mt-3 rounded-xl py-3 px-5"
/>
<TouchableOpacity
className="mt-2 flex items-end"
onPress={() => navigation.goBack()}
>
<Text className="text-textgray font-bold">Forgot Password?</Text>
</TouchableOpacity>
</View>
<CustomButton
navigation={navigation}
bgColor={colors.primary}
textColor={colors.textWhite}
goto={"Items"}
content={"Signup"}
/>
<View className="mt-10">
<Text className="text-textgray text-center">Or Continue With</Text>
<View className="mt-2">
<SocialIcons />
</View>
<View className="mt-24 flex flex-row items-center justify-center">
<Text className="text-textgray">Already have a accout?</Text>
<TouchableOpacity onPress={() => navigation.navigate("Login")}>
<Text className="text-textgray underline">Login</Text>
</TouchableOpacity>
</View>
</View>
</SafeAreaView>
);
};
export default Signup;
Fig. 4 - Signup Page
Login Page
Similary create Login page
pages/Login.tsx
import { View, Text, TouchableOpacity, TextInput, Image } from "react-native";
import { useState } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import Heading from "../components/Heading";
import CustomButton from "../components/CustomButton";
import colors from "../assets/colors";
import SocialIcons from "../components/SocialIcons";
const Login = ({ navigation }) => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
return (
<SafeAreaView className="bg-white container h-full px-7">
<View className="mt-36">
<Heading content="Welcome Back" />
</View>
<View className="mt-4">
<TextInput
onChangeText={setEmail}
placeholder={"Email"}
placeholderTextColor={colors.textDark}
value={email}
className="bg-zinc-200 rounded-xl py-3 pl-5"
/>
<TextInput
secureTextEntry={true}
onChangeText={setPassword}
placeholder={"Password"}
placeholderTextColor={colors.textDark}
value={password}
className="bg-zinc-200 mt-3 rounded-xl py-3 pl-5"
/>
<TouchableOpacity
className="mt-2 flex items-end"
onPress={() => navigation.goBack()}
>
<Text className="text-textDark font-bold">Forgot Password?</Text>
</TouchableOpacity>
</View>
<CustomButton
navigation={navigation}
bgColor={colors.primary}
textColor={colors.textWhite}
goto={"Items"}
content={"Login"}
/>
<View className="mt-10">
<Text className="text-textDark text-center">Or Continue With</Text>
<View className="mt-2">
<SocialIcons />
</View>
<View className="mt-44 flex flex-row items-center justify-center">
<Text className="text-textDark">Does'nt have a accout?</Text>
<TouchableOpacity onPress={() => navigation.navigate("Signup")}>
<Text className="text-textDark underline">Signup</Text>
</TouchableOpacity>
</View>
</View>
</SafeAreaView>
);
};
export default Login;
Fig. 5 - Login Page
Conclusion
In conclusion, building a UI for a login and signup form in React Native using TailwindCSS and functional reusable components can help streamline the development process and improve the overall user experience. By leveraging the power of React Native and the flexibility of TailwindCSS, we can create stunning UIs with minimal effort, while also maintaining a high degree of customization and flexibility. Additionally, the use of functional reusable components allows developers to create modular, reusable code that can be easily scaled and adapted for future projects. Overall, the process of building a login and signup form UI in React Native with TailwindCSS is a powerful and efficient way to create sleek and user-friendly interfaces for any mobile app.
Top comments (0)