Improve main menu (animation, aesthetics)

zio/stable
Paul Frazee 2022-10-11 15:16:46 -05:00
parent d7a75a2062
commit c9388a3cc5
2 changed files with 93 additions and 84 deletions

View File

@ -1,5 +1,6 @@
import {library} from '@fortawesome/fontawesome-svg-core' import {library} from '@fortawesome/fontawesome-svg-core'
import {faAddressCard} from '@fortawesome/free-regular-svg-icons/faAddressCard'
import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown' import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown'
import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft' import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight' import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight'
@ -15,6 +16,7 @@ import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark' import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark'
import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark' import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck' import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone} from '@fortawesome/free-regular-svg-icons/faClone' import {faClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment' import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis' import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis'
@ -48,6 +50,7 @@ import {faX} from '@fortawesome/free-solid-svg-icons/faX'
export function setup() { export function setup() {
library.add( library.add(
faAddressCard,
faAngleDown, faAngleDown,
faAngleLeft, faAngleLeft,
faAngleRight, faAngleRight,
@ -63,6 +66,7 @@ export function setup() {
faBookmark, faBookmark,
farBookmark, farBookmark,
faCheck, faCheck,
faCircleUser,
faClone, faClone,
faComment, faComment,
faEllipsis, faEllipsis,

View File

@ -1,23 +1,45 @@
import React from 'react' import React, {useEffect} from 'react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import { import {
Image, Image,
StyleSheet, StyleSheet,
SafeAreaView,
Text, Text,
TouchableOpacity, TouchableOpacity,
TouchableWithoutFeedback, TouchableWithoutFeedback,
View, View,
} from 'react-native' } from 'react-native'
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
interpolate,
} from 'react-native-reanimated'
import {IconProp} from '@fortawesome/fontawesome-svg-core' import {IconProp} from '@fortawesome/fontawesome-svg-core'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import LinearGradient from 'react-native-linear-gradient' import {HomeIcon} from '../../lib/icons'
import {useStores} from '../../../state' import {useStores} from '../../../state'
import {s, colors, gradients} from '../../lib/styles' import {s, colors} from '../../lib/styles'
import {DEF_AVATER} from '../../lib/assets' import {DEF_AVATER} from '../../lib/assets'
export const MainMenu = observer( export const MainMenu = observer(
({active, onClose}: {active: boolean; onClose: () => void}) => { ({active, onClose}: {active: boolean; onClose: () => void}) => {
const store = useStores() const store = useStores()
const initInterp = useSharedValue<number>(0)
useEffect(() => {
if (active) {
initInterp.value = withTiming(1, {duration: 150})
} else {
initInterp.value = 0
}
}, [initInterp, active])
const wrapperAnimStyle = useAnimatedStyle(() => ({
opacity: interpolate(initInterp.value, [0, 1.0], [0, 1.0]),
}))
const menuItemsAnimStyle = useAnimatedStyle(() => ({
marginTop: interpolate(initInterp.value, [0, 1.0], [15, 0]),
}))
// events // events
// = // =
@ -30,32 +52,30 @@ export const MainMenu = observer(
// rendering // rendering
// = // =
const FatMenuItem = ({ const MenuItem = ({
icon, icon,
label, label,
url, url,
gradient,
}: { }: {
icon: IconProp icon: IconProp
label: string label: string
url: string url: string
gradient: keyof typeof gradients
}) => ( }) => (
<TouchableOpacity <TouchableOpacity
style={[styles.fatMenuItem, styles.fatMenuItemMargin]} style={[styles.menuItem, styles.menuItemMargin]}
onPress={() => onNavigate(url)}> onPress={() => onNavigate(url)}>
<LinearGradient <View style={[styles.menuItemIconWrapper]}>
style={[styles.fatMenuItemIconWrapper]} {icon === 'home' ? (
colors={[gradients[gradient].start, gradients[gradient].end]} <HomeIcon style={styles.menuItemIcon} size={24} />
start={{x: 0, y: 0}} ) : (
end={{x: 1, y: 1}}>
<FontAwesomeIcon <FontAwesomeIcon
icon={icon} icon={icon}
style={styles.fatMenuItemIcon} style={styles.menuItemIcon}
size={24} size={24}
/> />
</LinearGradient> )}
<Text style={styles.fatMenuItemLabel} numberOfLines={1}> </View>
<Text style={styles.menuItemLabel} numberOfLines={1}>
{label} {label}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@ -69,7 +89,8 @@ export const MainMenu = observer(
<TouchableWithoutFeedback onPress={onClose}> <TouchableWithoutFeedback onPress={onClose}>
<View style={styles.bg} /> <View style={styles.bg} />
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
<View style={styles.wrapper}> <Animated.View style={[styles.wrapper, wrapperAnimStyle]}>
<SafeAreaView>
<View style={[styles.topSection]}> <View style={[styles.topSection]}>
<TouchableOpacity <TouchableOpacity
style={styles.profile} style={styles.profile}
@ -91,28 +112,22 @@ export const MainMenu = observer(
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<View style={[styles.section]}> <View style={[styles.section]}>
<View style={styles.fatMenuItems}> <Animated.View style={[styles.menuItems, menuItemsAnimStyle]}>
<FatMenuItem <MenuItem icon="home" label="Home" url="/" />
icon="house" <MenuItem
label="Feed" icon={['far', 'circle-user']}
url="/" label="Contacts"
gradient="primary" url="/contacts"
/> />
<FatMenuItem <MenuItem
icon="bell" icon={['far', 'bell']}
label="Notifications" label="Notifications"
url="/notifications" url="/notifications"
gradient="purple"
/>
<FatMenuItem
icon="gear"
label="Settings"
url="/settings"
gradient="blue"
/> />
</Animated.View>
</View> </View>
</View> </SafeAreaView>
</View> </Animated.View>
</> </>
) )
}, },
@ -125,23 +140,22 @@ const styles = StyleSheet.create({
right: 0, right: 0,
bottom: 0, bottom: 0,
left: 0, left: 0,
backgroundColor: '#000', // backgroundColor: '#000',
opacity: 0.2, opacity: 0,
}, },
wrapper: { wrapper: {
position: 'absolute', position: 'absolute',
top: 0,
bottom: 75, bottom: 75,
width: '100%', width: '100%',
backgroundColor: '#fff', backgroundColor: '#fff',
borderRadius: 8,
opacity: 1,
paddingVertical: 10,
}, },
topSection: { topSection: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 10, paddingHorizontal: 10,
paddingBottom: 10,
}, },
section: { section: {
paddingHorizontal: 10, paddingHorizontal: 10,
@ -170,41 +184,32 @@ const styles = StyleSheet.create({
marginRight: 10, marginRight: 10,
}, },
fatMenuItems: { menuItems: {
flexDirection: 'row', flexDirection: 'row',
marginTop: 10, marginTop: 10,
marginBottom: 10, marginBottom: 10,
}, },
fatMenuItem: { menuItem: {
width: 80, width: 80,
alignItems: 'center', alignItems: 'center',
marginRight: 6, marginRight: 6,
}, },
fatMenuItemMargin: { menuItemMargin: {
marginRight: 14, marginRight: 14,
}, },
fatMenuItemIconWrapper: { menuItemIconWrapper: {
borderRadius: 6, borderRadius: 6,
width: 60, width: 60,
height: 60, height: 60,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
marginBottom: 5, marginBottom: 5,
shadowColor: '#000', backgroundColor: colors.gray1,
shadowOpacity: 0.2,
shadowOffset: {width: 0, height: 2},
shadowRadius: 2,
}, },
fatMenuItemIcon: { menuItemIcon: {
color: colors.white, color: colors.gray5,
}, },
fatMenuImage: { menuItemLabel: {
borderRadius: 30,
width: 60,
height: 60,
marginBottom: 5,
},
fatMenuItemLabel: {
fontSize: 13, fontSize: 13,
}, },
}) })