I’m trying to copy a Figma design for a screen using React Native/Expo. I have fixed most of the errors I had, but I’m still stuck in one of them. I am using even and odd rows, with the odd rows having three buttons, while the even rows have two. Does anyone have any idea how to fix it? I’ll post the entire code as well as the current and reference images for the screen here so you can take a look:
The original Figma design
The design I have on my project
type RootStackParamList = {
topics: undefined;
tabs: { screen: string; params?: { selectedTopics: string[] } };
};
type TopicScreenNavigationProp = NavigationProp<RootStackParamList, 'topics'>;
import { Image, StyleSheet, Platform, ScrollView, Text, View, Button, TouchableOpacity, Pressable, SafeAreaView } from 'react-native';
import { useState } from 'react';
import { useNavigation, NavigationProp } from '@react-navigation/native';
import { Link } from 'expo-router';
import { ThemedView } from '@/components/ThemedView';
import {topics} from '@/db';
import HomeScreen from './(tabs)';
import { Navigate } from 'react-router-dom';
const groupTopicsIntoRows = (topics: any) => {
const rows = [];
let isOddRow = true;
for (let i = 0; i < topics.length;) {
const row = [];
const count = isOddRow ? 3 : 2;
for (let j = 0; j < count && i < topics.length; j++, i++) {
row.push(topics[i]);
}
rows.push(row);
isOddRow = !isOddRow;
}
return rows;
};
export default function TopicScreen( { navigation }: { navigation: NavigationProp<any> } ) {
const Webnavigation = useNavigation<TopicScreenNavigationProp>();
const [selectedTopics, setSelectedTopics] = useState<string[]>([]);
const rows = groupTopicsIntoRows(topics);
const handlePress = (topicName: any) => {
setSelectedTopics((prevSelected: any[]): any =>
prevSelected.includes(topicName)
? prevSelected.filter((name) => name !== topicName)
: [...prevSelected, topicName]
);
};
const handleContinue = () => {
if (Platform.OS === "web") {
Webnavigation.navigate('tabs', { screen: 'Home', params: { selectedTopics } });
} else {
navigation.navigate('tabs', { screen: 'Home', params: { selectedTopics } });
}
};
return (
<SafeAreaView style={{backgroundColor: '#242423'}}>
<ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollViewContent} scrollEnabled>
<View style={styles.titleContainer}>
<Text style={styles.title}>Select 5 Topics</Text>
<Pressable style={styles.button} onPress={handleContinue}><Text style={styles.buttonText}>Skip For Now</Text></Pressable>
</View>
<View style={styles.container}>
{rows.map((row, rowIndex) => (
<View style={styles.row} key={rowIndex}>
{row.map((topic: {name: string}, index) => (
<View style={styles.topicContainer} key={index}>
<ThemedView style={[ styles.stepContainer, selectedTopics.includes(topic.name) && styles.selectedStepContainer ]} >
<View style={[ styles.topic, selectedTopics.includes(topic.name) && styles.selectedTopic ]}>
<TouchableOpacity onPress={() => handlePress(topic.name)} style={[styles.topic, selectedTopics.includes(topic.name) && styles.selectedTopic]}>
<Text style={[styles.topicText, selectedTopics.includes(topic.name) && styles.selectedTopicText]}>{topic.name}</Text>
</TouchableOpacity>
</View>
</ThemedView>
</View>
))}
</View>
))}
</View>
</ScrollView>
<View style={styles.fixedContainer}>
<Text style={{color: '#808080', padding: 12}}>You Can Change This Later</Text>
<View style={styles.continue}>
<Pressable style={styles.continue} onPress={handleContinue}>
<Text style={{color: '#808080', backgroundColor: '#FFC939'}}>Continue</Text>
</Pressable>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
scrollView: {
marginBottom: 100,
},
scrollViewContent: {
flexGrow: 1,
...(Platform.OS === 'web' && { height: 450 }),
},
title: {
fontSize: 15,
fontWeight: 'bold',
lineHeight: 32,
color: '#ffffff',
},
titleContainer: {
paddingTop: 50,
padding: 15,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: 5,
},
button: {
backgroundColor: '#242423',
borderRadius: 25,
padding: -50,
},
buttonText: {
color: 'gray',
},
container: {
padding: 6,
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: -15,
},
topicContainer: {
flex: 1,
padding: 10,
marginHorizontal: -5,
backgroundColor: '#242423',
},
selectedTopicContainer: {
backgroundColor: '#FFC939',
},
topic: {
fontSize: 8,
color: '#ffffff',
textAlign: 'center',
padding:7,
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#242423',
borderRadius: 25,
},
stepContainer: {
alignItems: 'center',
marginVertical: 5,
width: '100%',
borderRadius: 25,
borderWidth: 1,
borderColor: '#E8EDDF',
backgroundColor: '#242423',
},
selectedStepContainer: {
backgroundColor: '#FFC939',
borderWidth: 1,
borderColor: '#FFC939',
color: '#000000',
},
fixedContainer: {
margin: 10,
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
height: 90,
justifyContent: 'center',
alignItems: 'center',
borderTopWidth: 1,
borderTopColor: '#272727',
},
continue: {
backgroundColor: '#FFC939',
color: '#000000',
padding: 9,
borderRadius: 30,
width: '90%',
alignItems: 'center',
justifyContent: 'center',
},
topicText: {
color: '#ffffff',
fontSize: 13,
},
selectedTopic: {
backgroundColor: '#FFC939',
},
selectedTopicText: {
color: '#000000',
},
});
I tried asking chatGPT, and it made me set another parameter or global button size which only changed the look of the buttons but didn’t make it look uniform (I don’t remember what it was, sorry for being vague)
Alessandro Amaya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.