diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/index.ts | 1 | ||||
-rw-r--r-- | src/components/search/SearchBackground.tsx | 27 | ||||
-rw-r--r-- | src/components/search/SearchBar.tsx | 87 | ||||
-rw-r--r-- | src/components/search/SuggestedSection.tsx | 42 | ||||
-rw-r--r-- | src/components/search/SuggestedUser.tsx | 61 | ||||
-rw-r--r-- | src/components/search/index.ts | 3 | ||||
-rw-r--r-- | src/routes/tabs/NavigationBar.tsx | 4 | ||||
-rw-r--r-- | src/screens/index.ts | 1 | ||||
-rw-r--r-- | src/screens/main/Search.tsx | 24 | ||||
-rw-r--r-- | src/screens/main/index.ts | 1 | ||||
-rw-r--r-- | src/screens/search/SearchScreen.tsx | 83 | ||||
-rw-r--r-- | src/screens/search/index.ts | 1 |
12 files changed, 308 insertions, 27 deletions
diff --git a/src/components/index.ts b/src/components/index.ts index 48b7df05..77ba0f67 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,3 +1,4 @@ export * from './common'; export * from './onboarding'; export * from './profile'; +export * from './search'; diff --git a/src/components/search/SearchBackground.tsx b/src/components/search/SearchBackground.tsx new file mode 100644 index 00000000..66e3dbdb --- /dev/null +++ b/src/components/search/SearchBackground.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import {StyleSheet, ViewProps} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; + +interface SearchBackgroundProps extends ViewProps {} +const SearchBackground: React.FC<SearchBackgroundProps> = ({ + style, + children, +}) => { + return ( + <LinearGradient + useAngle={true} + angle={167} + colors={['#421566', '#385D5E']} + style={[styles.container, style]}> + {children} + </LinearGradient> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + +export default SearchBackground; diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx new file mode 100644 index 00000000..283b6d59 --- /dev/null +++ b/src/components/search/SearchBar.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { + StyleSheet, + TextInput, + TextInputProps, + NativeSyntheticEvent, + TextInputFocusEventData, + TouchableOpacity, + Text, + View, +} from 'react-native'; +import Icon from 'react-native-vector-icons/Feather'; +import Animated from 'react-native-reanimated'; + +interface SearchBarProps extends TextInputProps { + active: boolean; +} +const SearchBar: React.FC<SearchBarProps> = ({onFocus, onBlur, active}) => { + const handleFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => { + // TODO: animate Icon & View.inputContainer.borderColor color to '#000' + // TODO: animate background color (& page color in results ScrollView) to '#ffff' (last f for opacity) + // TODO: animate TextInput width and mount "Cancel" button (& animate opacity) + // OR + // TODO: just animate "Cancel" button width and opacity (this might be easier) + onFocus && onFocus(e); + }; + const handleBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => { + // TODO: animate Icon color & View.inputContainer borderColor back + // TODO: animate background color (and page color in ScrollView) back to '#fff3' + // TODO: unmount Cancel button (and animate width change) + onBlur && onBlur(e); + }; + + return ( + <View style={styles.container}> + <Animated.View style={styles.inputContainer}> + <Icon name="search" size={25} color="#fff" style={styles.searchIcon} /> + <TextInput + onFocus={handleFocus} + onBlur={handleBlur} + style={styles.input} + placeholder={'Search...'} + /> + </Animated.View> + {active && ( + <TouchableOpacity style={styles.cancelButton}> + <Text style={styles.cancel}>Cancel</Text> + </TouchableOpacity> + )} + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + height: 40, + }, + inputContainer: { + flexDirection: 'row', + alignItems: 'center', + flex: 1, + height: '100%', + paddingHorizontal: 8, + backgroundColor: '#fff3', + borderColor: '#fff', + borderWidth: 1.5, + borderRadius: 20, + }, + searchIcon: { + marginRight: 8, + }, + input: { + flex: 1, + fontSize: 16, + }, + cancelButton: { + marginHorizontal: 5, + }, + cancel: { + color: '#818181', + fontWeight: '600', + }, +}); + +export default SearchBar; diff --git a/src/components/search/SuggestedSection.tsx b/src/components/search/SuggestedSection.tsx new file mode 100644 index 00000000..af0323a5 --- /dev/null +++ b/src/components/search/SuggestedSection.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import {View, Text, ScrollView, StyleSheet} from 'react-native'; +import SuggestedUser from './SuggestedUser'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +interface SuggestedSectionProps { + title: string; + users: Array<string>; +} +const SuggestedSection: React.FC<SuggestedSectionProps> = ({title, users}) => { + return ( + <View style={styles.container}> + <Text style={styles.header}>{title}</Text> + <ScrollView horizontal showsHorizontalScrollIndicator={false}> + {users.map((name, key) => ( + <SuggestedUser {...{name, key}} style={styles.user} /> + ))} + </ScrollView> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + marginBottom: 30, + }, + header: { + fontWeight: '600', + fontSize: 20, + color: '#fff', + marginBottom: 20, + }, + user: { + marginHorizontal: 15, + }, +}); + +export default SuggestedSection; diff --git a/src/components/search/SuggestedUser.tsx b/src/components/search/SuggestedUser.tsx new file mode 100644 index 00000000..467e5e6c --- /dev/null +++ b/src/components/search/SuggestedUser.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import {View, StyleSheet, Text, ViewProps, Image} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +interface SuggestedUserProps extends ViewProps { + name: string; +} +const SuggestedUser: React.FC<SuggestedUserProps> = ({name, style}) => { + return ( + <View style={[styles.container, style]}> + <LinearGradient + colors={['#9F00FF', '#27EAE9']} + useAngle + angle={90} + angleCenter={{x: 0.5, y: 0.5}} + style={styles.gradient}> + <Image + source={require('../../assets/images/avatar-placeholder.png')} + style={styles.profile} + /> + </LinearGradient> + <Text style={styles.name}>{name}</Text> + <Text style={styles.username}>{`@${name.split(' ').join('')}`}</Text> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + }, + gradient: { + height: 80, + width: 80, + borderRadius: 40, + justifyContent: 'center', + alignItems: 'center', + marginBottom: 10, + }, + profile: { + height: 76, + width: 76, + borderRadius: 38, + }, + name: { + fontWeight: '600', + fontSize: 16, + color: '#fff', + }, + username: { + fontWeight: '600', + fontSize: 14, + color: '#fff', + }, +}); +export default SuggestedUser; diff --git a/src/components/search/index.ts b/src/components/search/index.ts new file mode 100644 index 00000000..4e1d2b14 --- /dev/null +++ b/src/components/search/index.ts @@ -0,0 +1,3 @@ +export {default as SearchBar} from './SearchBar'; +export {default as SuggestedSection} from './SuggestedSection'; +export {default as SearchBackground} from './SearchBackground'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index aca968c2..d36b02ae 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -3,9 +3,9 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import {NavigationIcon} from '../../components'; import { ProfileScreen, + SearchScreen, Home, Notifications, - Search, Upload, } from '../../screens'; @@ -62,7 +62,7 @@ const NavigationBar: React.FC = () => { }, }}> <Tabs.Screen name="Home" component={Home} /> - <Tabs.Screen name="Search" component={Search} /> + <Tabs.Screen name="Search" component={SearchScreen} /> <Tabs.Screen name="Upload" component={Upload} /> <Tabs.Screen name="Notifications" component={Notifications} /> <Tabs.Screen name="Profile" component={ProfileScreen} /> diff --git a/src/screens/index.ts b/src/screens/index.ts index 5dd3007a..13a9799c 100644 --- a/src/screens/index.ts +++ b/src/screens/index.ts @@ -1,3 +1,4 @@ export * from './main'; export * from './onboarding'; export * from './profile'; +export * from './search'; diff --git a/src/screens/main/Search.tsx b/src/screens/main/Search.tsx deleted file mode 100644 index 19e35d04..00000000 --- a/src/screens/main/Search.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import {Text} from 'react-native-animatable'; -import {StyleSheet} from 'react-native'; -import {GradientBackground} from '../../components'; - -/** - * Search Screen for user recommendations and a search - * tool to allow user to find other users - */ - -const Search: React.FC = () => { - return ( - <GradientBackground> - <Text style={styles.text}> Search for people here 👀 </Text> - </GradientBackground> - ); -}; -const styles = StyleSheet.create({ - text: { - justifyContent: 'center', - backgroundColor: 'transparent', - }, -}); -export default Search; diff --git a/src/screens/main/index.ts b/src/screens/main/index.ts index fb1bf49b..b15f76da 100644 --- a/src/screens/main/index.ts +++ b/src/screens/main/index.ts @@ -1,4 +1,3 @@ export {default as Home} from './Home'; export {default as Notifications} from './Notifications'; -export {default as Search} from './Search'; export {default as Upload} from './Upload'; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx new file mode 100644 index 00000000..8ef56b73 --- /dev/null +++ b/src/screens/search/SearchScreen.tsx @@ -0,0 +1,83 @@ +import React, {useState} from 'react'; +import { + StatusBar, + SafeAreaView, + StyleSheet, + Text, + View, + ScrollView, +} from 'react-native'; +import {SearchBar, SuggestedSection, SearchBackground} from '../../components'; +import {SCREEN_HEIGHT} from '../../utils'; + +/** + * Search Screen for user recommendations and a search + * tool to allow user to find other users + */ + +const SearchScreen: React.FC = () => { + const sections: Array<string> = [ + 'People you follow', + 'People you may know', + 'Trending in sports', + 'Trending on Tagg', + 'Trending in music', + ]; + // dummy user data + const users: Array<string> = [ + 'Sam Davis', + 'Becca Smith', + 'Ann Taylor', + 'Clara Johnson', + 'Sarah Jung', + 'Lila Hernandez', + ]; + const [isSearching, setIsSearching] = useState<boolean>(false); + const handleFocus = () => { + setIsSearching(true); + }; + const handleBlur = () => { + setIsSearching(false); + }; + return ( + <SearchBackground style={styles.screen}> + <StatusBar /> + <SafeAreaView> + <ScrollView showsVerticalScrollIndicator={false}> + <Text style={styles.header}>Explore</Text> + <SearchBar + active={isSearching} + onFocus={handleFocus} + onBlur={handleBlur} + /> + {!isSearching && ( + <View style={styles.content}> + {sections.map((title) => ( + <SuggestedSection key={title} title={title} users={users} /> + ))} + </View> + )} + </ScrollView> + </SafeAreaView> + </SearchBackground> + ); +}; + +const styles = StyleSheet.create({ + screen: { + paddingTop: 50, + paddingBottom: SCREEN_HEIGHT / 10, + paddingHorizontal: 15, + }, + content: { + paddingVertical: 20, + }, + header: { + fontWeight: 'bold', + fontSize: 24, + color: '#fff', + marginBottom: 20, + textAlign: 'center', + }, +}); +export default SearchScreen; diff --git a/src/screens/search/index.ts b/src/screens/search/index.ts new file mode 100644 index 00000000..b6680aa4 --- /dev/null +++ b/src/screens/search/index.ts @@ -0,0 +1 @@ +export {default as SearchScreen} from './SearchScreen'; |