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 {faAddressCard} from '@fortawesome/free-regular-svg-icons/faAddressCard'
import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown'
import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
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 as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
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 {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
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() {
library.add(
faAddressCard,
faAngleDown,
faAngleLeft,
faAngleRight,
@ -63,6 +66,7 @@ export function setup() {
faBookmark,
farBookmark,
faCheck,
faCircleUser,
faClone,
faComment,
faEllipsis,

View File

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