React native Reanimated Conditional Animated View Movement - react-native

I am really new to React-native-reanimated. I am trying to create one custom bottom-sheet like this app. I am using PanGestureHandler from react-native-gesture-handler for move the Animated View to go up and down. For gestureHandler I am using useAnimatedGestureHandler props from react-native-reanimated. I want to move the Animated View from start point to middle screen and bottom of screen. This is My Bottom sheet start point image, when scroll the card down it should come middle of the screen like this image, again scroll down the card it will come bottom like this image.
I am having difficulties with the conditional useAnimatedGestureHandler onEnd movement. Currently I am tracking onEnd's event.translationY and make a condition out of it.
This is how it works currently:
When the App start, the Animated View is top of the screen, if I move the card scroll to bottom it goes middle of the screen and it does not go down from middle of the screen, I can move it to up from middle of the screen or if I scroll hard to bottom it goes all the way to bottom and if I try scroll the View up it does not go middle, it just goes up to start View.
I am trying to make the condition based screen size but I don't know how to make it.
I shared my code in expo-snacks
This is my all code
import React, { useState, useEffect } from "react";
import { StyleSheet, useWindowDimensions, RefreshControl } from "react-native";
import MapView from "react-native-maps";
import styled from "styled-components";
import {
PanGestureHandler,
PanGestureHandlerGestureEvent,
FlatList,
} from "react-native-gesture-handler";
import Animated, {
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
Easing,
withSpring,
} from "react-native-reanimated";
const initialRegion = {
latitudeDelta: 15,
longitudeDelta: 15,
latitude: 60.1098678,
longitude: 24.7385084,
};
const api =
"http://open-api.myhelsinki.fi/v1/events/?distance_filter=60.1699%2C24.9384%2C10&language_filter=en&limit=50";
export default function App() {
const { height } = useWindowDimensions();
const top = useSharedValue(height);
const [event, setEvent] = useState([]);
const [loading, setLoading] = useState(false);
const prevTop = useSharedValue(height * 0.5);
// This is Fetch Data
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(api);
const data = await response.json();
setEvent(data.data);
setLoading(false);
} catch (error) {
console.log("erro", error);
}
};
useEffect(() => {
fetchData();
}, []);
const animatedStyle = useAnimatedStyle(() => {
return {
top: top.value * 0.2,
bottom: 0,
};
});
const gestureHandler = useAnimatedGestureHandler(
{
onStart(_, context) {
context.translateY = top.value;
},
onActive(event, context) {
top.value = context.translateY + event.translationY;
},
onEnd(event, _) {
// THIS IS MY CONDITION OF ANIMATED VIEW
if (event.translationY > 0 && event.translationY < 400) {
console.log("middle-top", top.value);
console.log("middle-height", height);
top.value = withSpring(height * 2.5, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
} else if (event.translationY > 450 && event.translationY < 800) {
console.log("bottom-top", top.value);
console.log("bottom-height", height);
top.value = withSpring(height * 4, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
} else if (event.translationY < 0) {
console.log("start-top", top.value);
console.log("start-height", height);
top.value = withSpring(height, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
}
},
},
[top]
);
return (
<>
<MapView style={styles.mapStyle} initialRegion={initialRegion} />
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View style={[styles.container, animatedStyle]}>
<Title>I am scroll sheet</Title>
<HeroFlatList
data={event}
refreshControl={
<RefreshControl
enabled={true}
refreshing={loading}
onRefresh={fetchData}
/>
}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item, index }) => {
const image = item?.description.images.map((img) => img.url);
const startDate = item?.event_dates?.starting_day;
return (
<EventContainer key={index}>
<EventImage
source={{
uri:
image[0] ||
"https://res.cloudinary.com/drewzxzgc/image/upload/v1631085536/zma1beozwbdc8zqwfhdu.jpg",
}}
/>
<DescriptionContainer>
<Title ellipsizeMode="tail" numberOfLines={1}>
{item?.name?.en}
</Title>
<DescriptionText>
{item?.description?.intro || "No description available"}
</DescriptionText>
<DateText>{startDate}</DateText>
</DescriptionContainer>
</EventContainer>
);
}}
/>
</Animated.View>
</PanGestureHandler>
</>
);
}
const styles = StyleSheet.create({
container: {
position: "absolute",
left: 0,
right: 0,
top: 0,
backgroundColor: "white",
shadowOffset: {
height: -6,
width: 0,
},
shadowOpacity: 0.1,
shadowRadius: 5,
borderTopEndRadius: 15,
borderTopLeftRadius: 15,
},
mapStyle: {
flex: 1,
},
});
const HeroFlatList = styled(FlatList).attrs({
contentContainerStyle: {
flexGrow: 1,
},
})`
padding: 12px;
`;
const Title = styled.Text`
font-size: 16px;
font-weight: 700;
margin-bottom: 10px;
align-self: center;
padding: 10px;
`;
const DescriptionText = styled.Text`
font-size: 14px;
opacity: 0.7;
`;
const DateText = styled.Text`
font-size: 14px;
opacity: 0.8;
color: #0099cc;
`;
const EventImage = styled.Image`
width: 70px;
height: 70px;
border-radius: 70px;
margin-right: 20px;
`;
const DescriptionContainer = styled.View`
width: 200px;
`;
const EventContainer = styled(Animated.View)`
flex-direction: row;
padding: 20px;
margin-bottom: 10px;
border-radius: 20px;
background-color: #fff;
shadow-color: #000;
shadow-opacity: 0.3;
shadow-radius: 20px;
shadow-offset: 0 10px;
`;
Tech information
Tech
Version
react-native-gesture-handler
^1.10.3
react-native-reanimated
^2.2.0

Not the perfect solution...
added a new sharedValue to track if its moving up or down.
const prevTop = useSharedValue(height * 0.5);
and respective code on gesture end.
onEnd() {
if (top.value > prevTop.value) {
top.value = withTiming(height * 0.98);
} else {
top.value = withTiming(Math.min(200, top.value));
}
prevTop.value = top.value;
},
Still there is a scope of improvement.

Related

How to customise the color of spinner with react-native-paper?

I try to customise the color of the spinner to green. But the color stays purple. Whatever I try to do.
So I have this:
/* eslint-disable prettier/prettier */
import { ActivityIndicator, Colors, Searchbar, withTheme } from "react-native-paper";
import { MD3LightTheme as DefaultTheme, Provider as PaperProvider } from "react-native-paper";
import { FlatList, SafeAreaView, StatusBar } from "react-native";
import React, { useContext } from "react";
import { CategoryContext } from "../../../services/category/category.context";
import { CategoryInfoCard } from "../components/category-info-card.component";
import { Spacer } from "../../../components/spacer/spacer.component";
import { colors } from "../../../infrastructure/theme/colors";
import styled from "styled-components/native";
/* eslint-disable prettier/prettier */
/* const cardGap = 16;
const cardWidth = (Dimensions.get("window").width - cardGap * 3) / 2; */
const theme = {
...DefaultTheme,
// Specify custom property
myOwnProperty: true,
// Specify custom property in nested object
colors: {
myOwnColor: "#69da55",
},
};
const colorsTheme = {
bg: "blue",
};
const SafeArea = styled(SafeAreaView)`
flex: 1;
${StatusBar.currentHeight && `margin-top: ${StatusBar.currentHeight}px`};
`;
const SearchContainer = styled.View`
padding: ${(props) => props.theme.space[3]};
`;
const CategoryList = styled(FlatList).attrs({
contentContainerStyle: {
padding: 16,
},
})``;
const Loading = styled(ActivityIndicator)`
margin-left: -25px;
background-color: colorsTheme.bg;
`;
const LoadingContainer = styled.View`
position: absolute;
top: 50%;
left: 50%;
`;
export const CategoryScreen = () => {
const { loading, error, categoryList } = useContext(CategoryContext);
return (
<SafeArea>
{loading && (
<LoadingContainer>
<Loading size={50} animating={true} style={{ backgroundColor: theme.colors.Green90 }} />
</LoadingContainer>
)}
<SearchContainer>
<Searchbar />
</SearchContainer>
<CategoryList
data={categoryList}
renderItem={({ item }) => {
//console.log("ITEMs", item);
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard categoryList={item} />
</Spacer>
);
}}
keyExtractor={(item) => item.name}
/>
</SafeArea>
);
};
So I try it like:
style={{ backgroundColor: theme.colors.Green90 }}
Founded here: https://callstack.github.io/react-native-paper/theming.html
But the color of spinner stays purple. Not green.
Question: How to change the color of spinner with react-native paper?
you are trying to give a backgroundColor for ActivityIndicator which does not exist in its props
to change the color of the spinner you need to use the color prop
<ActivityIndicator animating={true} color={'red'} />
you can check this sandbox

How can I give priority to sibling components in the same location in React native?

I am using styled-component in React native.
I have a component called FirstContain and a sibling component SecondContain, and each of these components has a button component.
At this time, FirstContain and SecondContain overlap and SecondButton hides FirstButton, but I want to put SecondButton higher and press SecondButton,
So I tried using zIndex and elevation, but to no avail. What should I do?
this is my code
import React from 'react';
import styled from "styled-components/native";
import { Text, View, StyleSheet } from "react-native";
const FirstContain = styled.View`
background-color: lightblue;
flex:1;
`;
const FirstButton = styled.TouchableOpacity`
width: 100px;
height: 40px;
background: lavender;
`;
const SecondContain = styled.View`
position: absolute;
background-color: lightgreen;
flex:1;
top:0;
bottom:0;
right:0;
left: 5%;
`;
const SecondButton = styled.TouchableOpacity`
width: 100px;
height: 40px;
background-color: lightpink;
`;
const App = () => {
const firstConfunc = () => {
console.log("firstConfunc");
}
const secondfunc = () => {
console.log("secondconfuc");
}
return (
<>
<FirstContain>
<FirstButton
onPress={firstConfunc}>
<Text>FirstContain</Text>
</FirstButton>
</FirstContain>
<SecondContain>
<SecondButton
onPress={secondfunc}>
<Text>secondContainer</Text>
</SecondButton>
</SecondContain>
</>
);
};
this is my snack
https://snack.expo.dev/u0idGYTpA
If you want it like this:
then change your these styles to this
const FirstContain = styled.View`
background-color: lightblue;
`;
const SecondContain = styled.View`
background-color: lightgreen;
`;
This code snippet is working perfect fine, same as you are expecting, You'll get some idea from this code -
import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
export default function App() {
return (
<View>
<TouchableOpacity onPress={() => console.log("first")} style={{padding: 10, backgroundColor:'red'}}>
</TouchableOpacity>
<TouchableOpacity onPress={() => console.log("second")} style={{padding: 10, backgroundColor:'blue', position:'absolute', left: 0, right: 0, top: 0, bottom: 0}}>
</TouchableOpacity>
</View>
);
}
As per Your code, You should change this part to likewise :
const SecondContain = styled.View`
position: absolute;
background-color: lightgreen;
flex:1;
top:0;
bottom:0;
right:0;
left: 0;
`;

How can i control Offset in Reactnative Animation?

I made some code based on your lecture.
When onPanResponderRelease is executed, if dx<-50, goLeft.start() is used to move toValue: -200.
I also refreshed the position using position.flattenOffset(); In onPanResponderGrant, I saved the position value using setOffset.
However, when goLeft.start() is executed and the tovalue has shifted by -200 and the card is touched again, onPanResponderGrant starts at -200 but ,the position is set to -400 and the card starts at an entirely different position.
How can I fix the code so that after goLeft.start() is executed, the touch will start at -200?
this is my code
import React, { useRef, useState } from "react";
import { Animated, PanResponder, Text, View } from "react-native";
import styled from "styled-components/native";
import { Ionicons } from "#expo/vector-icons";
import icons from "./icons";
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
background-color: #00a8ff;
`;
const Card = styled(Animated.createAnimatedComponent(View))`
background-color: white;
width: 100px;
height: 100px;
justify-content: center;
align-items: center;
border-radius: 12px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
position: absolute;
`;
const Btn = styled.TouchableOpacity`
margin: 0px 10px;
`;
const BtnContainer = styled.View`
flex-direction: row;
flex: 1;
`;
const CardContainer = styled.View`
flex: 3;
justify-content: center;
align-items: center;
`;
export default function App() {
const [left, setLeft] = useState(false);
// Values
const position = useRef(new Animated.Value(0)).current;
// Animations
const goCenter = Animated.spring(position, {
toValue: 0,
useNativeDriver: true,
});
const goLeft = Animated.spring(position, {
toValue: -200,
tension: 5,
useNativeDriver: true,
restDisplacementThreshold: 100,
restSpeedThreshold: 100,
});
const goRight = Animated.spring(position, {
toValue: 500,
tension: 5,
useNativeDriver: true,
});
// Pan Responders
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: () => {
console.log("Grant", position._value);
position.setOffset(position._value);
position.flattenOffset();
// position.addListener(() => {});
},
onPanResponderMove: (_, { dx }) => {
console.log("Move:", dx);
position.addListener(() => {});
position.setValue(dx);
// position.addListener(() => {});
},
onPanResponderRelease: (_, { dx }) => {
console.log("Release:", dx);
if (dx < -30) {
console.log("!!!");
goLeft.start();
position.flattenOffset();
} else {
position.flattenOffset();
}
},
})
).current;
position.addListener(() => console.log("p:", position));
// State
const [index, setIndex] = useState(0);
const onDismiss = () => {
// position.setValue(-100);
// Animated.timing(position, { toValue: -60, useNativeDriver: true }).start();
};
const closePress = () => {
console.log("222");
goLeft.start(onDismiss);
};
const checkPress = () => {
console.log("111");
goRight.start(onDismiss);
};
return (
<Container>
<CardContainer>
<Card
{...panResponder.panHandlers}
style={{
transform: [{ translateX: position }],
}}
>
<Ionicons color="#192a56" size={98} />
</Card>
</CardContainer>
<BtnContainer>
<Btn onPress={closePress}>
<Ionicons name="close-circle" color="white" size={58} />
</Btn>
<Btn onPress={checkPress}>
<Ionicons name="checkmark-circle" color="white" size={58} />
</Btn>
</BtnContainer>
</Container>
);
}

Styled component in victory chart. keep showing TypeError: _native.default.div is not a function

Error message:
TypeError: _native.default.div is not a function. (In '_native.default.div(_templateObject || (_templateObject = (0, _taggedTemplateLiteralLoose2.default)([""])))', '_native.default.div' is undefined)
I am new to react native. Not sure if this is some simple problems that I didn't understand correct. I was trying to use one of the example in Victory chart.
But the error massage keep showing up. I tried everything I can find online but nothing helps.
App.js
import { StyleSheet, Text, View } from 'react-native';
import { registerRootComponent } from 'expo';
import styled from 'styled-components/native';
import React from "react";
import { VictoryBar, VictoryChart, VictoryTheme } from "victory-native";
const LIGHT_GREY = "hsl(355, 20%, 90%)";
const PRIMARY_COLOR = "hsl(355, 92%, 67%)";
const Container = styled.div``;
const Card = styled.div`
background-color: #2b2a31;
padding: 40px 36px 30px;
border-radius: 5px;
// when rendered in the gallery preview
a & {
padding: 24px 20px 10px;
}
`;
const yearToSeason = year => `${year}-${(year + 1 + "").slice(2, 4)}`;
const YEARS = Object.keys(basketballData).map(year => parseInt(year, 10));
const FIRST_YEAR = YEARS[0];
const LAST_YEAR = YEARS[YEARS.length - 1];
const TOTAL_YEARS = LAST_YEAR - FIRST_YEAR;
const getTooltipText = ({ datum }) => {
const { binnedData, x0, x1 } = datum;
const playerCount = binnedData.length;
if (!playerCount) {
return null;
}
const playerNames = binnedData
.slice(0, 2)
.map(({ player }) => {
const [firstName, lastName] = player.split(" ");
return lastName ? `${firstName.slice(0, 1)}. ${lastName}` : firstName;
})
.join(", ");
const playerNamesList = `\n (${playerNames}${
playerCount > 2 ? `, and ${playerCount - 2} more players` : ""
})`;
return `${playerCount} player${
playerCount === 1 ? "" : "s"
} averaged between ${x0}-${x1} 3PT attempts ${playerNamesList}`;
};
const sharedAxisStyles = {
axis: {
stroke: "transparent"
},
tickLabels: {
fill: LIGHT_GREY,
fontSize: 14
},
axisLabel: {
fill: LIGHT_GREY,
padding: 36,
fontSize: 15,
fontStyle: "italic"
}
};
const GradientSvg = styled.svg`
position: fixed;
opacity: 0;
`;
const App = () => {
const [year, setYear] = React.useState(FIRST_YEAR);
return (
<Container>
<GradientSvg>
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="50%" y2="100%">
<stop offset="0%" stopColor="#FFE29F" />
<stop offset="40%" stopColor="#FFA99F" />
<stop offset="100%" stopColor={PRIMARY_COLOR} />
</linearGradient>
</defs>
</GradientSvg>
<Card>
<VictoryChart
containerComponent={
<VictoryVoronoiContainer
labels={getTooltipText}
voronoiDimension="x"
labelComponent={
<VictoryTooltip
constrainToVisibleArea
style={{
fill: LIGHT_GREY,
fontSize: 11
}}
flyoutStyle={{
fill: "#24232a",
stroke: PRIMARY_COLOR,
strokeWidth: 0.5
}}
/>
}
/>
}
height={280}
>
<VictoryLabel
text={`3pt Attempts Per Game Averages (${yearToSeason(year)})`}
x={225}
y={18}
textAnchor="middle"
style={{ fill: LIGHT_GREY, fontSize: 16 }}
/>
<VictoryAxis
style={{
...sharedAxisStyles,
grid: {
fill: LIGHT_GREY,
stroke: LIGHT_GREY,
pointerEvents: "painted",
strokeWidth: 0.5
}
}}
label="# of players"
dependentAxis
/>
<VictoryAxis
style={{
...sharedAxisStyles,
axisLabel: { ...sharedAxisStyles.axisLabel, padding: 35 }
}}
label="3pt attempts per game"
/>
<VictoryHistogram
cornerRadius={2}
domain={{ y: [0, 125] }}
animate={{ duration: 300 }}
data={basketballData[year]}
bins={_.range(0, 16, 2)}
style={{
data: {
stroke: "transparent",
fill: "url(#gradient1)",
strokeWidth: 1,
},
labels: {
fill: "red"
}
}}
x="3pa"
/>
</VictoryChart>
<YearSlider year={year} setYear={setYear} />
</Card>
</Container>
);
};
const SliderContainer = styled.div`
padding: 64px 25px 10px;
// when rendered in the gallery preview
a & {
padding: 24px 36px 0px;
}
`;
const getYear = percent =>
Math.round(FIRST_YEAR + TOTAL_YEARS * (percent / 100));
const SEASONS = YEARS.map(year => yearToSeason(year));
const YearSlider = ({ year, setYear }) => {
const [value, setValue] = React.useState(0);
return (
<SliderContainer>
<Slider
onChange={newValue => {
setValue(newValue);
const calculatedYear = getYear(newValue);
if (year !== calculatedYear) {
setYear(calculatedYear);
}
}}
color={PRIMARY_COLOR}
value={value}
maxValue={100}
tooltipValues={SEASONS}
/>
</SliderContainer>
);
};
ReactDOM.render(<App/>, mountNode);

How to implement a navigation drawer based on react router 4 in react native

I want to create a navigation drawer like in uber . So Is there are any libraries or packages that i can used to develop the navigation drawer of my app based on react router 4.
Use this
https://github.com/Tinysymphony/react-native-drawer-menu
https://github.com/root-two/react-native-drawer
and you can creat a view by yourself, it't easy, like this:
import React, { PureComponent } from 'react';
import {
View,
Animated,
Easing,
Dimensions,
TouchableOpacity,
TouchableWithoutFeedback
} from 'react-native';
import mitt from 'mitt';
import styled from 'styled-components';
import { t } from '../i18n';
import { TOOLBAR_HEIGHT } from './Toolbar';
import Avatar from '../components/Avatar';
import Icon from '../components/Icon';
import Text from './Text';
const { width } = Dimensions.get('window');
//-----------------------------------------------
class MenuDrawer extends PureComponent {
static defaultProps = {
width: (width * 75) / 100
};
constructor(props) {
super(props);
this.state = { show: false };
this.emitter = mitt();
this.animateValue = {
opacity: new Animated.Value(0),
marginLeft: new Animated.Value(-props.width)
};
}
animation({ opacity, mgleft }) {
this.animateValue.opacity.setValue(opacity.start);
this.animateValue.marginLeft.setValue(mgleft.start);
return Animated.parallel([
Animated.timing(this.animateValue.opacity, {
toValue: opacity.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.timing(this.animateValue.marginLeft, {
toValue: mgleft.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
})
]);
}
subscribe = cb => {
this.emitter.on('state-change', status => {
cb(status);
});
};
show = () => {
this.emitter.emit('state-change', true);
this.setState({ ...this.state, show: true }, () => {
const opacity = { start: 0, end: 0.6 };
const mgleft = { start: this.props.width, end: 0 };
this.animation({ opacity, mgleft }).start();
});
};
hide = () => {
this.emitter.emit('state-change', false);
const opacity = { start: 0.6, end: 0 };
const mgleft = { start: 0, end: this.props.width };
this.animation({ opacity, mgleft }).start(({ finished }) => {
if (finished) {
this.setState({ ...this.state, show: false });
}
});
};
handlePressOnBackground = () => {
this.hide();
};
renderContent() {
const { me } = this.props;
const name = me.fullname;
const avatar_url = me.avatar_url;
return (
<StyledView>
<StyledMyInfo>
<Avatar size={96} uri={avatar_url} name={name} isAgent={true} />
<StyledName text={name} />
</StyledMyInfo>
<StyledMenu>
<TouchableOpacity onPress={this.props.handlePressSettings}>
<StyledMenuItem>
<StyledIcon>
<Icon size={20} source={require('../assets/setting.png')} />
</StyledIcon>
<StyledLabel text={t('general_settings')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressChangePassword}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={2}
source={require('../assets/password.png')}
/>
</StyledIcon>
<StyledLabel text={t('profile_language_change_password_link')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressLogout}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={-1}
source={require('../assets/logout.png')}
/>
</StyledIcon>
<StyledLabel text={t('agent_profile_logout')} />
</StyledMenuItem>
</TouchableOpacity>
</StyledMenu>
</StyledView>
);
}
render() {
const { id } = this.props.me;
if (!this.state.show || !id) return null;
return (
<StyledViewContainer>
<TouchableWithoutFeedback
style={{ flex: 1 }}
onPress={this.handlePressOnBackground}
>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: 'black'
},
{ opacity: this.animateValue.opacity }
]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
width: '75%'
},
{ marginLeft: -this.animateValue.marginLeft }
]}
>
{this.renderContent()}
</Animated.View>
</StyledViewContainer>
);
}
}
//-----------------------------------------------
const StyledViewContainer = styled(View)`
position: absolute;
top: ${TOOLBAR_HEIGHT};
right: 0;
bottom: 0;
left: 0;
`;
const StyledView = styled(View)`
flex: 1;
background-color: #f9f9f9;
`;
const StyledMyInfo = styled(View)`
justify-content: center;
align-items: center;
height: 240;
background-color: white;
`;
const StyledName = styled(Text)`
margin-top: 10px;
font-size: ${props => props.theme.fontSizeLarge};
font-family: ${props => props.theme.fontSemiBold};
`;
const StyledMenu = styled(View)`
padding: 12px 15px;
`;
const StyledMenuItem = styled(View)`
margin-bottom: 5px;
flex-direction: row;
align-items: center;
`;
const StyledIcon = styled(View)`
width: 40;
height: 40;
justify-content: center;
align-items: center;
`;
const StyledLabel = styled(Text)``;
export default MenuDrawer;