├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── screenshots └── preview.gif ├── src ├── components │ ├── App.js │ ├── layouts │ │ ├── Loader.js │ │ └── Sidemenu.js │ ├── pages │ │ ├── About.js │ │ ├── Contact.js │ │ └── Home.js │ ├── styling │ │ ├── _variables.scss │ │ ├── index.scss │ │ ├── loader.scss │ │ ├── page.scss │ │ └── sidemenu.scss │ └── utils │ │ └── LocationRedirect.js ├── images │ ├── logo.svg │ └── post-loader.svg └── index.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Fullpage Loader 2 | 3 | Fullpage _React Loader_ that appears when changing routes. 4 | 5 | ### Preview 6 | 7 |
React Fullpage Loader
8 | 9 | ### How to use 10 | 11 | 1. Clone/Download the repo. 12 | 2. Install dependencies yarn install or npm install 13 | 3. Run yarn start or npm start. 14 | 4. You are ready [http://localhost:3000](http://localhost:3000) 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-fullpage-loader", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "node-sass": "^4.14.1", 10 | "react": "^16.13.1", 11 | "react-dom": "^16.13.1", 12 | "react-router-dom": "^5.2.0", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Fullpage Loader 8 | 9 | 10 | 11 |
12 | 16 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /screenshots/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AchrafHamrit/react-fullpage-loader/25bb02637c4c91063d41281bee2bb0de902abd7e/screenshots/preview.gif -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; 3 | 4 | import LocationRedirect from './utils/LocationRedirect'; 5 | import Sidemenu from './layouts/Sidemenu'; 6 | import Loader from './layouts/Loader'; 7 | import Home from './pages/Home'; 8 | import About from './pages/About'; 9 | import Contact from './pages/Contact'; 10 | 11 | function App() { 12 | const [hide, setHide] = useState(true); 13 | const [newLocation, setNewLocation] = useState(null); 14 | 15 | return ( 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | ); 29 | } 30 | 31 | export default App; 32 | -------------------------------------------------------------------------------- /src/components/layouts/Loader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../styling/loader.scss'; 3 | import Logo from '../../images/logo.svg'; 4 | 5 | const Loader = ({ hide }) => { 6 | return ( 7 |
8 | logo 9 |
10 | ); 11 | }; 12 | 13 | export default Loader; 14 | -------------------------------------------------------------------------------- /src/components/layouts/Sidemenu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import '../styling/sidemenu.scss'; 4 | 5 | const Sidemenu = ({ setNewLocation }) => { 6 | const handleLinkClick = (e) => { 7 | e.preventDefault(); 8 | 9 | setNewLocation('/' + e.target.name); 10 | }; 11 | 12 | return ( 13 |
14 |
15 | 16 | 17 |
18 | 50 |
51 | ); 52 | }; 53 | 54 | export default Sidemenu; 55 | -------------------------------------------------------------------------------- /src/components/pages/About.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PostLoader from '../../images/post-loader.svg'; 3 | import '../styling/page.scss'; 4 | 5 | const About = () => { 6 | return ( 7 |
8 |
9 |

About page

10 | Post loader 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default About; 17 | -------------------------------------------------------------------------------- /src/components/pages/Contact.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PostLoader from '../../images/post-loader.svg'; 3 | import '../styling/page.scss'; 4 | 5 | const Contact = () => { 6 | return ( 7 |
8 |
9 |

Contact page

10 | Post loader 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Contact; 17 | -------------------------------------------------------------------------------- /src/components/pages/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PostLoader from '../../images/post-loader.svg'; 3 | import '../styling/page.scss'; 4 | 5 | const Home = () => { 6 | return ( 7 |
8 |
9 |

Home page

10 | Post loader 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Home; 17 | -------------------------------------------------------------------------------- /src/components/styling/_variables.scss: -------------------------------------------------------------------------------- 1 | $primary: #255dd6; 2 | $bg-light: #f2f8ff; 3 | -------------------------------------------------------------------------------- /src/components/styling/index.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | html, 4 | body { 5 | overflow-x: hidden; 6 | } 7 | 8 | body { 9 | margin: 0; 10 | font-family: 'Montserrat', sans-serif; 11 | background: $bg-light; 12 | 13 | a { 14 | text-decoration: none; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/components/styling/loader.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | .loader { 4 | position: absolute; 5 | display: flex; 6 | align-items: center; 7 | justify-content: flex-start; 8 | top: 0; 9 | bottom: 0; 10 | width: 100%; 11 | z-index: 9999; 12 | background: $primary; 13 | transition: 0.4s all ease; 14 | 15 | img { 16 | width: 100px; 17 | margin: auto; 18 | transition: 0.4s all ease; 19 | } 20 | 21 | &.hide { 22 | width: 0%; 23 | 24 | img { 25 | opacity: 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/components/styling/page.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | .page { 4 | min-height: 90vh; 5 | display: flex; 6 | flex-direction: row; 7 | align-items: center; 8 | 9 | .content { 10 | display: flex; 11 | flex-direction: column; 12 | padding: 100px 130px; 13 | 14 | h2 { 15 | color: $primary; 16 | font-size: 2rem; 17 | font-weight: 700; 18 | display: inline; 19 | } 20 | 21 | img { 22 | width: 250px; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/components/styling/sidemenu.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | .sidemenu { 4 | overflow: hidden; 5 | background-color: white; 6 | display: flex; 7 | align-items: center; 8 | position: absolute; 9 | top: 0; 10 | bottom: 0; 11 | z-index: 1; 12 | transition: 0.5s all ease; 13 | width: 90px; 14 | 15 | .humberger { 16 | padding: 0 30px; 17 | transition: 0.5s all ease; 18 | 19 | span { 20 | display: block; 21 | width: 30px; 22 | height: 4px; 23 | border-radius: 3px; 24 | background-color: $primary; 25 | transition: 0.5s all ease; 26 | 27 | &:first-child { 28 | margin-bottom: 4px; 29 | } 30 | } 31 | } 32 | 33 | ul { 34 | padding: 0 20px; 35 | list-style: none; 36 | font-size: 1.3rem; 37 | font-weight: 600; 38 | opacity: 0; 39 | transition: 0.4s all ease; 40 | 41 | li { 42 | display: flex; 43 | padding: 15px 0; 44 | transform: translateX(10px); 45 | transition: 0.4s all ease; 46 | 47 | .title { 48 | color: white; 49 | } 50 | 51 | &:hover { 52 | opacity: 0.5; 53 | } 54 | } 55 | } 56 | 57 | &:hover { 58 | background-color: $primary; 59 | width: 300px; 60 | 61 | .humberger { 62 | span { 63 | transform: rotate(90deg); 64 | background-color: white; 65 | } 66 | } 67 | 68 | ul { 69 | opacity: 1; 70 | transform: translateX(-10px); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/components/utils/LocationRedirect.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { useLocation, useHistory } from 'react-router-dom'; 3 | 4 | const LoactionRedirect = ({ newLocation, setHide }) => { 5 | const location = useLocation().pathname; 6 | const history = useHistory(); 7 | 8 | useEffect(() => { 9 | if (newLocation && newLocation !== location) { 10 | setHide(false); 11 | setTimeout(() => { 12 | history.push(newLocation); 13 | setHide(true); 14 | }, 2000); 15 | } 16 | 17 | // eslint-disable-next-line 18 | }, [newLocation]); 19 | 20 | return <>; 21 | }; 22 | 23 | export default LoactionRedirect; 24 | -------------------------------------------------------------------------------- /src/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/images/post-loader.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './components/styling/index.scss'; 4 | import App from './components/App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | --------------------------------------------------------------------------------