├── .expo-shared └── assets.json ├── .gitignore ├── App.js ├── README.md ├── app.json ├── assets ├── favicon.png ├── icon.png └── splash.png ├── babel.config.js ├── package.json ├── react-native-custom-drawer-animation-dribbble-preview.gif ├── utils.js ├── yarn-error.log └── yarn.lock /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | 12 | # macOS 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | /* 2 | Inspiration: https://dribbble.com/shots/4275765-Realweb-3 3 | Twitter: http://twitter.com/mironcatalin 4 | YouTube: http://youtube.com/c/CatalinMironDev 5 | ☕️ BuyMeACoffee: https://www.buymeacoffee.com/catalinmiron 6 | */ 7 | 8 | import * as React from 'react'; 9 | import { 10 | StatusBar, 11 | Animated, 12 | Dimensions, 13 | Text, 14 | View, 15 | StyleSheet, 16 | TouchableOpacity, 17 | } from 'react-native'; 18 | import Svg, { Polygon } from 'react-native-svg'; 19 | import { AntDesign } from '@expo/vector-icons'; 20 | import MaskedView from '@react-native-community/masked-view'; 21 | import { colors, links, routes } from './utils'; 22 | 23 | const AnimatedAntDesign = Animated.createAnimatedComponent(AntDesign); 24 | const AnimatedPolygon = Animated.createAnimatedComponent(Polygon); 25 | 26 | const { width, height } = Dimensions.get('window'); 27 | const fromCoords = { x: 0, y: height }; 28 | const toCoords = { x: width, y: 0 }; 29 | 30 | const Button = ({ title, onPress, style }) => { 31 | return ( 32 | 33 | {title} 34 | 35 | ); 36 | }; 37 | 38 | const Drawer = ({ animation, onPress }) => { 39 | const polygonRef = React.useRef(); 40 | 41 | React.useEffect(() => { 42 | const listener = animation.addListener((v) => { 43 | if (polygonRef?.current) { 44 | polygonRef.current.setNativeProps({ 45 | points: `0,0 ${v.x}, ${v.y} ${width}, ${height} 0, ${height}`, 46 | }); 47 | } 48 | }); 49 | 50 | return () => { 51 | animation.removeListener(listener); 52 | }; 53 | }); 54 | 55 | const opacity = animation.x.interpolate({ 56 | inputRange: [0, width], 57 | outputRange: [0, 1], 58 | }); 59 | 60 | const translateX = animation.x.interpolate({ 61 | inputRange: [0, width], 62 | outputRange: [-50, 0], 63 | }); 64 | 65 | const [selectedRoute, setSelectedRoute] = React.useState('Get started'); 66 | const onRoutePress = React.useCallback((route) => { 67 | setSelectedRoute(route); 68 | onPress(); 69 | }, []); 70 | 71 | return ( 72 | 81 | 87 | 88 | } 89 | > 90 | 91 | 98 | 101 | 102 | {routes.map((route, index) => { 103 | return ( 104 |