├── .gitignore ├── README.md ├── newsfetch ├── .eslintrc.cjs ├── .firebase │ ├── hosting.ZGlzdA.cache │ └── hosting.cHVibGlj.cache ├── .firebaserc ├── .gitignore ├── README.md ├── bun.lockb ├── firebase.json ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── logo.svg │ └── vite.svg ├── src │ ├── .env.sample │ ├── Animations │ │ └── index.js │ ├── App.css │ ├── App.jsx │ ├── Layout.jsx │ ├── assets │ │ ├── image.png │ │ └── react.svg │ ├── components │ │ ├── About │ │ │ └── About.jsx │ │ ├── Blog │ │ │ └── Blog.jsx │ │ ├── Contact │ │ │ └── Contact.jsx │ │ ├── Context │ │ │ └── Theme.js │ │ ├── Footer │ │ │ └── Footer.jsx │ │ ├── Header │ │ │ ├── FireBaseConfig.js │ │ │ ├── Header.jsx │ │ │ └── ThemeButton.jsx │ │ ├── NewsDetail │ │ │ └── NewsDetail.jsx │ │ ├── Preloader │ │ │ ├── Preloader.css │ │ │ └── Preloader.jsx │ │ ├── Slider │ │ │ └── Carousel.jsx │ │ └── TrendingNews │ │ │ └── TrendingNews.jsx │ ├── index.css │ └── main.jsx ├── style.css ├── tailwind.config.js └── vite.config.js └── server ├── .env.sample ├── .firebase └── hosting.cHVibGlj.cache ├── .firebaserc ├── .github └── workflows │ ├── firebase-hosting-merge.yml │ └── firebase-hosting-pull-request.yml ├── .gitignore ├── bun.lockb ├── dist ├── assets │ ├── image-Cs6Ew6q3.png │ ├── index-BQinPF2a.js │ └── index-CxmS_tQk.css ├── index.html └── vite.svg ├── firebase.json ├── package-lock.json ├── package.json ├── server.js └── vercel.json /.gitignore: -------------------------------------------------------------------------------- 1 | newsfetch/src/.env 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NewsMania 2 | 3 | Welcome to **NewsMania**, a web application designed to keep you updated with the top business news headlines fetched from sources like Times of India and others using the https://newsapi.org. This project utilizes a combination of backend middleware and direct API calls. The middleware, built with Express.js, handles some API requests, while others are fetched directly from the frontend via the github API to fetch the admin information directly from Github account. The application also integrates Google authentication for seamless login and logout, and leverages Web3 forms to trigger emails to the admin. 4 | 5 | ## Features 6 | 7 | - **Business News Headlines**: Fetches top business Headlines from sources like Times of India and others via NEWSAPI. 8 | - **Google Authentication**: Integrates Google login/logout for user authentication. 9 | - **Github API**: Fetches user data from Github. 10 | - **Web Forms Integration**: Sends emails to the admin using Web forms. 11 | 12 | ## Middleware Explanation 13 | 14 | NEWSAPI allows fetching data from their API on localhost only. However, CORS (Cross-Origin Resource Sharing) are blocked for any other production deployment. To bypass these CORS restrictions, a middleware is created using Express.js. This middleware resolves the CORS issues by fetching the data at the backend and displaying it on the frontend. 15 | 16 | ## Live Demo 17 | 18 | You can see the live demo of the project [here](https://hunar-taupe.vercel.app). 19 | 20 | ## Technologies Used 21 | 22 | - **Frontend**: 23 | - React + Vite 24 | - Tailwind CSS 25 | - React Router DOM 26 | - GSAP(GreenSock Animation Platform) 27 | 28 | - **Backend**: 29 | - Express.js (as middleware/proxy server) 30 | - Firebase (for authentication) 31 | - Railway.app (for hosting backend) 32 | 33 | - **APIs**: 34 | - NEWSAPI (for fetching news) 35 | - Github API (for fetching user data) 36 | - Google Authentication (for user login/logout) 37 | - Web3Forms (for handling web forms and email triggers) 38 | 39 | - **Deployment**: 40 | - Vercel (for deploying frontend) 41 | - Railway.app (for deploying backend) 42 | 43 | ## Getting Started 44 | 45 | To get a local copy up and running, follow these simple steps. 46 | 47 | ### Prerequisites 48 | 49 | - Node.js installed on your machine 50 | - A NEWSAPI key 51 | - A Github API key 52 | - TailwindCSS & React + Vite Builder Pack Installed 53 | - Firebase project set up for Google authentication 54 | - Web3Forms account for handling form submissions 55 | 56 | ### Installation 57 | 58 | 1. **Clone the repository**: 59 | 60 | ```sh 61 | git clone https://github.com/happyrao78/Hunar.git 62 | ``` 63 | 64 | 2. **Navigate to the project directory**: 65 | 66 | ```sh 67 | cd newsfetch 68 | ``` 69 | 70 | 3. **Install dependencies for the frontend and backend**: 71 | 72 | ```sh 73 | cd newsfetch (Frontend) 74 | npm install 75 | cd server (Backend) 76 | npm install 77 | ``` 78 | 79 | 4. **Set up environment variables**: 80 | 81 | Create a `.env` file in the server directory and add your NEWSAPI key, and PORT for local host. 82 | 83 | ```env 84 | NEWS_API_KEY=your_newsapi_key 85 | PORT=your desired PORT 86 | ``` 87 | 88 | 5. **Set up Firebase**: 89 | 90 | - Create a Firebase project in the [Firebase Console](https://console.firebase.google.com/). 91 | - Enable Google authentication in the Firebase Authentication section. 92 | - Obtain the Firebase configuration settings (API key, Auth domain, Project ID, etc.) and add them to /newsfetch/src/components/Header/FireBaseConfig.js file. 93 | 94 | 6. **Run the backend server**: 95 | 96 | ```sh 97 | cd server 98 | node server.js 99 | ``` 100 | 101 | 7. **Run the frontend server**: 102 | 103 | Open a new terminal window and run: 104 | 105 | ```sh 106 | cd newsfetch 107 | npm run dev 108 | ``` 109 | 110 | ### Deployment 111 | 112 | 1. **Set up Railway.app**: 113 | 114 | - Create a project in [Railway.app](https://railway.app/). 115 | - Add your environment variables in the Railway platform. Railway.app uses dynamic allocation for environment variables, so the `.env` file is essential. Ensure all variables from the `.env` file are added to the Railway environment configuration. 116 | 117 | 2. **Deploy Backend**: 118 | 119 | - Deploy the backend server on Railway.app by following their documentation and connecting your repository. 120 | 121 | 3. **Deploy Frontend**: 122 | 123 | - Deploy the frontend on Vercel by connecting your repository and following their deployment steps. 124 | 125 | ## Usage 126 | 127 | 1. Open the application in your browser at `http://localhost:3000`. 128 | 2. Log in using your Google account. 129 | 3. Browse through the top business news headlines. 130 | 4. Fetch your Github user data. 131 | 5. Use the contact form to send an email to the admin. 132 | 133 | ## Contributing 134 | 135 | Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. 136 | 137 | 1. Fork the project. 138 | 2. Create your feature branch (`git checkout -b feature/AmazingFeature`). 139 | 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`). 140 | 4. Push to the branch (`git push origin feature/AmazingFeature`). 141 | 5. Open a Pull Request. 142 | 143 | ## MIT License 144 | 145 | Distributed under the MIT License. 146 | 147 | 148 | Copyright (c) [2024] [NewsMania] 149 | 150 | Permission is hereby granted, free of charge, to any person obtaining a copy 151 | of this project and associated documentation files, to deal 152 | in the project without restriction, including without limitation the rights 153 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 154 | copies of the project, and to permit persons to whom the project is 155 | furnished to do so, subject to the following conditions: 156 | 157 | The above copyright notice and this permission notice shall be included in all 158 | copies or substantial portions of the project. 159 | 160 | THE PROJECT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 162 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 163 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 164 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 165 | OUT OF OR IN CONNECTION WITH THE PROJECT OR THE USE OR OTHER DEALINGS IN THE 166 | PROJECT. 167 | 168 | 169 | ## Contact 170 | 171 | Your Name - [happyrao7091@gmail.com](mailto:happyrao7091@gmail.com) 172 | 173 | Owner's Website: [https://www.happyrao.tech](https://www.happyrao.tech) 174 | 175 | Project Link: [https://github.com/happyrao78/Hunar](https://github.com/happyrao78/Hunar) 176 | 177 | --- 178 | 179 | Thank you for checking out NewsMania! Enjoy staying updated with the latest business news. -------------------------------------------------------------------------------- /newsfetch/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react/jsx-no-target-blank': 'off', 16 | 'react-refresh/only-export-components': [ 17 | 'warn', 18 | { allowConstantExport: true }, 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /newsfetch/.firebase/hosting.ZGlzdA.cache: -------------------------------------------------------------------------------- 1 | vite.svg,1719070733215,699a02e0e68a579f687d364bbbe7633161244f35af068220aee37b1b33dfb3c7 2 | index.html,1719670418759,6efac3621d61854fc5d023e4de016e4296861c5b94d0a7f2b816a494d742a175 3 | assets/index-CxmS_tQk.css,1719670418759,ff7499b4d322d923c51e8a6ebb8fff7408c4523bf5037951d3d73dad1e649ab7 4 | assets/index-BQinPF2a.js,1719670418762,84259530a8cd31d6e348d4acf4547191d1876fc61ed160e88bcc7b5451f95d14 5 | assets/image-Cs6Ew6q3.png,1719670418759,117faebf7f84edbb05c36a48cb9264f41d2035234b30aeace9a8d9ec49b5d005 6 | -------------------------------------------------------------------------------- /newsfetch/.firebase/hosting.cHVibGlj.cache: -------------------------------------------------------------------------------- 1 | vite.svg,1719070733215,699a02e0e68a579f687d364bbbe7633161244f35af068220aee37b1b33dfb3c7 2 | -------------------------------------------------------------------------------- /newsfetch/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "hunar-8f29c" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /newsfetch/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /newsfetch/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /newsfetch/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/happyrao78/Hunar/d59138026a511f0f7bf399ea5d14623b8ed00272/newsfetch/bun.lockb -------------------------------------------------------------------------------- /newsfetch/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | }, 16 | "emulators": { 17 | "auth": { 18 | "port": 2024 19 | }, 20 | "hosting": { 21 | "port": 5000 22 | }, 23 | "ui": { 24 | "enabled": false 25 | }, 26 | "singleProjectMode": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /newsfetch/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | NewsMania 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /newsfetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newsfetch", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "axios": "^1.7.2", 14 | "cheerio": "^1.0.0-rc.12", 15 | "cors": "^2.8.5", 16 | "express": "^4.19.2", 17 | "firebase": "^10.12.2", 18 | "gsap": "^3.12.5", 19 | "lucide-react": "^0.441.0", 20 | "newsfetch": "file:", 21 | "puppeteer": "^22.12.1", 22 | "react": "^18.3.1", 23 | "react-animated-cursor": "^2.11.2", 24 | "react-dom": "^18.3.1", 25 | "react-icons": "^5.2.1", 26 | "react-marquee-slider": "^1.1.5", 27 | "react-router": "^6.24.0", 28 | "react-router-dom": "^6.24.0", 29 | "react-slick": "^0.30.2", 30 | "react-spinners": "^0.14.1", 31 | "react-tilty": "^3.0.0", 32 | "react-tsparticles": "^2.12.2", 33 | "slick-carousel": "^1.8.1", 34 | "uuid": "^10.0.0" 35 | }, 36 | "devDependencies": { 37 | "@types/react": "^18.3.3", 38 | "@types/react-dom": "^18.3.0", 39 | "@vitejs/plugin-react": "^4.3.1", 40 | "autoprefixer": "^10.4.19", 41 | "eslint": "^8.57.0", 42 | "eslint-plugin-react": "^7.34.2", 43 | "eslint-plugin-react-hooks": "^4.6.2", 44 | "eslint-plugin-react-refresh": "^0.4.7", 45 | "postcss": "^8.4.38", 46 | "tailwindcss": "^3.4.4", 47 | "vite": "^5.3.1" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /newsfetch/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /newsfetch/public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /newsfetch/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /newsfetch/src/.env.sample: -------------------------------------------------------------------------------- 1 | GITHUB_ACCESS_TOKEN=your_github_access_token -------------------------------------------------------------------------------- /newsfetch/src/Animations/index.js: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | 3 | // Declare a general timeline to use in all the animation functions. 4 | 5 | const tl = gsap.timeline(); 6 | 7 | // Preloader Animation 8 | export const preLoaderAnim = () => { 9 | tl.to("body", { 10 | duration: 0.1, 11 | css: { overflowY: "hidden" }, 12 | ease: "power3.inOut", 13 | }) 14 | .to(".landing", { 15 | duration: 0.05, 16 | css: { overflowY: "hidden", height: "90vh" }, 17 | }) 18 | .to(".texts-container", { 19 | duration: 0, 20 | opacity: 1, 21 | ease: "Power3.easeOut", 22 | }) 23 | .from(".texts-container span", { 24 | duration: 1.5, 25 | delay: 1, 26 | y: 70, 27 | skewY: 10, 28 | stagger: 0.4, 29 | ease: "Power3.easeOut", 30 | }) 31 | .to(".texts-container span", { 32 | duration: 1, 33 | y: 70, 34 | skewY: -20, 35 | stagger: 0.2, 36 | ease: "Power3.easeOut", 37 | }) 38 | 39 | .to(".landing", { 40 | duration: 0.05, 41 | css: { overflowY: "hidden", height: "unset" }, 42 | }) 43 | .to("body", { 44 | duration: 0.1, 45 | css: { overflowY: "scroll" }, 46 | ease: "power3.inOut", 47 | }) 48 | .from(".landing__top .sub", { 49 | duration: 1, 50 | opacity: 0, 51 | y: 80, 52 | ease: "expo.easeOut", 53 | }) 54 | .to( 55 | ".preloader", 56 | { 57 | duration: 1.5, 58 | height: "0vh", 59 | ease: "Power3.easeOut", 60 | onComplete: mobileLanding(), 61 | }, 62 | "-=2" 63 | ) 64 | .from(".landing__main .text", { 65 | duration: 2, 66 | // scale: 0, 67 | y: 10, 68 | opacity: 0, 69 | stagger: { 70 | amount: 2, 71 | }, 72 | ease: "power3.easeInOut", 73 | }) 74 | .from(".links .item", { 75 | duration: 0.5, 76 | opacity: 0, 77 | delay: window.innerWidth < 763 ? -3 : -0.6, 78 | // y: 80, 79 | stagger: { 80 | amount: 0.5, 81 | }, 82 | ease: "expo.easeOut", 83 | onComplete: animateMainShape(), 84 | }) 85 | .from(".main-circle", { 86 | duration: 1, 87 | opacity: 0, 88 | ease: "power3.easeInOut", 89 | onComplete: animateShapes(), 90 | }) 91 | .from(".shapes .shape", { 92 | duration: 1, 93 | opacity: 0, 94 | delay: -1, 95 | ease: "power3.easeInOut", 96 | stagger: 1, 97 | }) 98 | .to(".preloader", { 99 | duration: 0, 100 | css: { display: "none" }, 101 | }); 102 | }; 103 | 104 | export const openMenu = () => { 105 | const tl = gsap.timeline(); 106 | tl.to("body", { 107 | duration: 0.1, 108 | css: { overflowY: "hidden" }, 109 | ease: "power3.out", 110 | }) 111 | .to(".hamburger-menu", { 112 | duration: 0.1, 113 | css: { display: "block" }, 114 | }) 115 | .to(".header-item", { 116 | duration: 0.1, 117 | css: { background: "none" }, 118 | }) 119 | .to(".cls-1", { 120 | duration: 0.1, 121 | delay: 0.3, 122 | css: { fill: "#ffffff" }, 123 | }) 124 | .to( 125 | [".nav-secondary", ".nav-primary"], 126 | { 127 | duration: 0.8, 128 | height: "100%", 129 | transformOrigin: "right top", 130 | stagger: { 131 | amount: 0.1, 132 | }, 133 | ease: "power3.inOut", 134 | }, 135 | "-=.5" 136 | ) 137 | .from( 138 | ".nav-link", 139 | { 140 | duration: 0.5, 141 | x: -80, 142 | opacity: 0, 143 | stagger: { 144 | amount: 0.5, 145 | }, 146 | ease: "Power3.in", 147 | }, 148 | "-=.3" 149 | ); 150 | 151 | // change cursor color when nav is open 152 | // tl.to(".cursor", { 153 | // delay: -1, 154 | // css: { className: "+=cursor-active" }, 155 | // }).to(".cursor2", { delay: -1, css: { className: "+=cursor2-active" } }); 156 | }; 157 | 158 | export const closeMenu = () => { 159 | const tl = gsap.timeline(); 160 | tl.to("body", { 161 | duration: 0.05, 162 | css: { overflowY: "scroll" }, 163 | ease: "power3.inOut", 164 | }) 165 | .to([".nav-primary", ".nav-secondary"], { 166 | duration: 0.8, 167 | height: "0", 168 | transformOrigin: "right top", 169 | stagger: { 170 | amount: 0.1, 171 | }, 172 | ease: "power3.inOut", 173 | }) 174 | .to(".cls-1", { 175 | duration: 0.1, 176 | delay: -0.3, 177 | css: { fill: "#08e7f3" }, 178 | }) 179 | .to(".header-item", { 180 | duration: 0.5, 181 | css: { background: "rgba(11,11,15,.8)" }, 182 | }) 183 | .to(".hamburger-menu", { 184 | duration: 0.05, 185 | css: { display: "none" }, 186 | }); 187 | 188 | // tl.to(".cursor-active", { 189 | // css: { className: "+=cursor" }, 190 | // }).to(".cursor2-active", { css: { className: "+=cursor2" } }); 191 | }; 192 | 193 | // recurrent animations 194 | export const fadeUp = (el, delay = 0) => { 195 | tl.from(el, { 196 | y: 150, 197 | duration: 1, 198 | delay, 199 | opacity: 0, 200 | ease: "power3.Out", 201 | }); 202 | }; 203 | 204 | export const mobileLanding = () => { 205 | window.innerWidth < 763 && 206 | tl.from(".landing__main2", { 207 | duration: 1, 208 | delay: 0, 209 | opacity: 0, 210 | y: 80, 211 | ease: "expo.easeOut", 212 | }); 213 | }; 214 | 215 | const animateShapes = () => { 216 | const infiniteTl = gsap.timeline({ 217 | repeat: -1, 218 | }); 219 | infiniteTl 220 | .to(".shapes .shape", { 221 | duration: 4, 222 | rotate: 360, 223 | delay: -1, 224 | ease: "power3.easeInOut", 225 | stagger: 2, 226 | }) 227 | .to(".shapes .shape-3", { 228 | duration: 1, 229 | rotate: 360, 230 | delay: -2, 231 | ease: "power3.easeInOut", 232 | }) 233 | .to(".shapes .shape", { 234 | duration: 3, 235 | rotate: 0, 236 | ease: "power3.easeInOut", 237 | stagger: 1, 238 | }) 239 | .to(".shapes .shape", { 240 | duration: 1, 241 | opacity: 0, 242 | delay: -1, 243 | ease: "power3.easeInOut", 244 | stagger: 1, 245 | }) 246 | .to(".shapes .shape", { 247 | duration: 1.5, 248 | opacity: 1, 249 | ease: "power3.easeInOut", 250 | stagger: 1, 251 | }); 252 | }; 253 | 254 | const animateMainShape = () => { 255 | const infiniteTl = gsap.timeline({ 256 | repeat: -1, 257 | }); 258 | infiniteTl 259 | .to(".shapes .main-circle", { 260 | duration: 6, 261 | x: -30, 262 | y: -50, 263 | ease: "expo.easeOut", 264 | }) 265 | .to(".shapes .main-circle", { 266 | duration: 6, 267 | x: -30, 268 | y: 50, 269 | ease: "expo.easeOut", 270 | }) 271 | .to(".shapes .main-circle", { 272 | duration: 4, 273 | x: 0, 274 | y: 0, 275 | ease: "expo.easeOut", 276 | }); 277 | }; 278 | 279 | export const boxHover = (e) => { 280 | const tl = gsap.timeline(); 281 | window.innerWidth >= 986 && 282 | tl 283 | .to(e.target.querySelector(".link"), { 284 | duration: 0, 285 | opacity: 1, 286 | }) 287 | .from(e.target.querySelectorAll(".box-anim"), { 288 | duration: 0.3, 289 | opacity: 0, 290 | y: 30, 291 | stagger: 0.1, 292 | ease: "Power3.easeOut", 293 | }); 294 | }; 295 | 296 | export const boxExit = (e) => { 297 | window.innerWidth >= 986 && 298 | gsap.to(e.target.querySelector(".link"), { 299 | duration: 0, 300 | opacity: 0, 301 | }); 302 | }; 303 | 304 | export const fadeIn = (el) => { 305 | gsap.to(el, { 306 | duration: 2, 307 | opacity: 1, 308 | y: -60, 309 | ease: "power4.out", 310 | }); 311 | }; 312 | 313 | export const fadeOut = (el) => { 314 | gsap.to(el, { 315 | duration: 1, 316 | opacity: 0, 317 | y: -20, 318 | ease: "power4.out", 319 | }); 320 | }; -------------------------------------------------------------------------------- /newsfetch/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | /* @keyframes pulse { 44 | 0%, 100% { 45 | opacity: 1; 46 | } 47 | 50% { 48 | opacity: 0.5; 49 | } 50 | } */ 51 | -------------------------------------------------------------------------------- /newsfetch/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | import './App.css' 4 | 5 | function App() { 6 | 7 | return ( 8 | <> 9 | 10 | 11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /newsfetch/src/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import Header from './components/Header/Header' 3 | import Footer from './components/Footer/Footer' 4 | import {Outlet} from 'react-router-dom' 5 | import AnimatedCursor from "react-animated-cursor" 6 | import Preloader from './components/Preloader/Preloader' 7 | import ThemeBtn from './components/Header/ThemeButton' 8 | import { ThemeProvider } from './components/Context/Theme' 9 | 10 | function Layout() { 11 | const [themeMode,setThemeMode]= useState("light"); 12 | const lightTheme = ()=>{ 13 | setThemeMode('light') 14 | } 15 | const darkTheme= ()=>{ 16 | setThemeMode('dark') 17 | } 18 | useEffect(()=>{ 19 | document.querySelector('html').classList.remove("light","dark") 20 | document.querySelector('html').classList.add(themeMode) 21 | },[themeMode]) 22 | return ( 23 | <> 24 | 45 | 46 | {/*
*/} 47 | 48 |
49 | {/* */} 50 | 51 |