├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── _redirects ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.js ├── homepage ├── Home.js ├── HomeCard.js ├── HomeStyled.js └── homeData.js ├── index.css ├── index.js ├── logo.svg ├── projects ├── accordion │ ├── Accordion.js │ ├── AccordionStyled.js │ └── accordionData.js ├── back-to-top │ ├── BackTop.js │ └── BackTopStyled.js ├── clicked-modal │ ├── ClickedModal.js │ ├── ClickedModalBox.js │ ├── ClickedModalStyled.js │ └── clickedModalData.js ├── counter │ ├── Counter.js │ └── CounterStyled.js ├── filterable-gallery │ ├── FilterableGallery.js │ ├── FilterableGalleryStyled.js │ └── galleryData.js ├── loadMore │ ├── LoadMore.js │ └── LoadMoreStyled.js ├── modal │ ├── Modal.js │ ├── ModalBox.js │ └── ModalStyled.js ├── readmore │ ├── ReadMore.js │ ├── ReadMoreCard.js │ ├── ReadMoreStyled.js │ └── readMoreData.js ├── search-filter │ ├── SearchFilter.js │ └── SearchFilterStyled.js ├── sidebar │ ├── Sidebar.js │ ├── SidebarStyled.js │ └── sidebarData.js ├── sticky-header │ ├── StickyHeader.js │ ├── StickyHeaderStyled.js │ └── stickyHeaderData.js └── tabs │ ├── Tabs.js │ ├── TabsStyled.js │ └── tabsData.js └── reportWebVitals.js /.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 Projects 2 | 3 | ### [Demo Link](https://react-practical-projects.netlify.app/) 🔗 4 | 5 | List of mostly used UI Elements (or Components) in a Website, built with **React JS**. 6 | 7 |
8 | 9 | ## Table of Contents: 10 | 11 | - ### [Counter](https://react-practical-projects.netlify.app/counter) 12 | - ### [Accordion](https://react-practical-projects.netlify.app/accordion) 13 | - ### [Tabs](https://react-practical-projects.netlify.app/tabs) 14 | - ### [Sidebar](https://react-practical-projects.netlify.app/sidebar) 15 | - ### [Modal](https://react-practical-projects.netlify.app/modal) 16 | - ### [Open Clicked Modal](https://react-practical-projects.netlify.app/clicked-modal) 17 | - ### [Filterable Gallery](https://react-practical-projects.netlify.app/filterable-gallery) 18 | - ### [Search Filter](https://react-practical-projects.netlify.app/search-filter) 19 | - ### [Sticky Header](https://react-practical-projects.netlify.app/sticky-header) 20 | - ### [Back To Top Button](https://react-practical-projects.netlify.app/back-top) 21 | - ### [Read More Button](https://react-practical-projects.netlify.app/read-more) 22 | - ### [Load More Button](https://react-practical-projects.netlify.app/load-more) 23 | 24 |
25 | 26 | ## Technologies used: 27 | 28 | - #### **React JS** 29 | - #### **React Router** 30 | - #### **Styled Components** 31 | 32 |
33 | 34 | ## Author: 35 | 36 | - **Gulshan Songara** - **[Portfolio Website](https://gulshansongara.netlify.app)**, **[Linkedin](https://www.linkedin.com/in/gulshan-songara/)** 37 | 38 |
39 | 40 | ## Available Scripts: 41 | 42 | #### `npm start` 43 | 44 | #### `npm test` 45 | 46 | #### `npm run build` 47 | 48 | #### `npm run eject` 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-projects", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.4", 7 | "@testing-library/react": "^13.3.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.1.0", 10 | "react-dom": "^18.1.0", 11 | "react-router-dom": "^6.3.0", 12 | "react-scripts": "5.0.1", 13 | "styled-components": "^5.3.5", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gulshancodes/react-projects/a06634679cca460b27bcf38badb93a36356d324c/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | React Projects 26 | 27 | 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gulshancodes/react-projects/a06634679cca460b27bcf38badb93a36356d324c/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gulshancodes/react-projects/a06634679cca460b27bcf38badb93a36356d324c/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from 'react-router-dom'; 2 | import Home from './homepage/Home'; 3 | import Counter from './projects/counter/Counter'; 4 | import Accordion from './projects/accordion/Accordion'; 5 | import Tabs from './projects/tabs/Tabs'; 6 | import Sidebar from './projects/sidebar/Sidebar'; 7 | import StickyHeader from './projects/sticky-header/StickyHeader'; 8 | import BackTop from './projects/back-to-top/BackTop'; 9 | import ReadMore from './projects/readmore/ReadMore'; 10 | import Modal from './projects/modal/Modal'; 11 | import ClickedModal from './projects/clicked-modal/ClickedModal'; 12 | import LoadMore from './projects/loadMore/LoadMore'; 13 | import FilterableGallery from './projects/filterable-gallery/FilterableGallery'; 14 | import SearchFilter from './projects/search-filter/SearchFilter'; 15 | 16 | 17 | function App() { 18 | return ( 19 | <> 20 | 21 | } /> 22 | } /> 23 | } /> 24 | } /> 25 | } /> 26 | } /> 27 | } /> 28 | } /> 29 | } /> 30 | } /> 31 | } /> 32 | } /> 33 | } /> 34 | 35 | 36 | ); 37 | } 38 | 39 | export default App; 40 | -------------------------------------------------------------------------------- /src/homepage/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import HomeCard from './HomeCard'; 3 | import homeData from './homeData'; 4 | import { HomePage, HomeWrapper } from './HomeStyled'; 5 | 6 | const Home = () => { 7 | 8 | // if mistakenly, body contains the overflow_hide class then remove it. 9 | document.body.classList.contains('overflow_hide') && document.body.classList.remove('overflow_hide'); 10 | 11 | 12 | return ( 13 | <> 14 | 15 |
16 | 22 | 23 | { 24 | homeData.map((currValue) => { 25 | return ( 26 | 30 | ); 31 | }) 32 | } 33 | 34 | 37 |
38 |
39 | 40 | ); 41 | }; 42 | 43 | export default Home; -------------------------------------------------------------------------------- /src/homepage/HomeCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from "react-router-dom"; 3 | 4 | const HomeCard = (props) => { 5 | 6 | const { title, path } = props; 7 | 8 | return ( 9 | <> 10 |
11 | 12 | 18 | 19 | 20 |

21 | 22 | {title} 23 | 24 |

25 |
26 | 27 | ); 28 | }; 29 | 30 | export default HomeCard; -------------------------------------------------------------------------------- /src/homepage/HomeStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const HomePage = styled.main` 4 | padding-top: 3rem; 5 | padding-bottom: 2rem; 6 | overflow: hidden; 7 | text-align: center; 8 | 9 | #header { 10 | 11 | h1 { 12 | letter-spacing: 0.4px; 13 | margin-bottom: 0.8rem; 14 | 15 | span { 16 | color: var(--color); 17 | } 18 | } 19 | 20 | a { 21 | opacity: 0.8; 22 | transition: opacity 0.2s ease; 23 | 24 | &:hover { 25 | opacity: 1; 26 | } 27 | } 28 | 29 | } 30 | 31 | #footer { 32 | 33 | p { 34 | text-transform: uppercase; 35 | letter-spacing: 0.6px; 36 | 37 | a { 38 | color: var(--color); 39 | opacity: 0.9; 40 | transition: opacity 0.2s ease; 41 | 42 | &:hover { 43 | opacity: 1; 44 | } 45 | } 46 | } 47 | } 48 | `; 49 | 50 | export const HomeWrapper = styled.main` 51 | display: grid; 52 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 53 | gap: 3rem; 54 | margin-top: 5rem; 55 | margin-bottom: 6rem; 56 | 57 | @media (max-width: 576px) { 58 | grid-template-columns: 1fr; 59 | } 60 | 61 | .card { 62 | height: 480px; 63 | border: 1px solid #333; 64 | overflow: hidden; 65 | box-shadow: 5px 5px 10px rgba(0,0,0,0.5); 66 | transition: border-color 0.3s ease; 67 | 68 | &:hover { 69 | border-color: #666; 70 | } 71 | } 72 | 73 | .iframe_wrapper { 74 | display: block; 75 | position: relative; 76 | width: 100%; 77 | height: 85%; 78 | overflow: hidden; 79 | 80 | 81 | iframe { 82 | width: 100%; 83 | height: 100%; 84 | object-fit: cover; 85 | user-select: none; 86 | pointer-events: none; 87 | } 88 | } 89 | 90 | .iframe_title { 91 | background-color: var(--color-2); 92 | width: 100%; 93 | height: 15%; 94 | display: grid; 95 | place-items: center; 96 | border-top: 1px solid #333; 97 | letter-spacing: 1px; 98 | } 99 | `; -------------------------------------------------------------------------------- /src/homepage/homeData.js: -------------------------------------------------------------------------------- 1 | const homeData = [ 2 | { 3 | id: 1, 4 | title: "Counter", 5 | path: "/counter", 6 | }, 7 | { 8 | id: 2, 9 | title: "Accordion", 10 | path: "/accordion", 11 | }, 12 | 13 | { 14 | id: 3, 15 | title: "Tabs", 16 | path: "/tabs", 17 | }, 18 | 19 | { 20 | id: 4, 21 | title: "Sidebar", 22 | path: "/sidebar", 23 | }, 24 | 25 | { 26 | id: 5, 27 | title: "Sticky Header", 28 | path: "/sticky-header", 29 | }, 30 | { 31 | id: 6, 32 | title: "Back To Top", 33 | path: "/back-top", 34 | }, 35 | 36 | { 37 | id: 7, 38 | title: "Read More", 39 | path: "/read-more", 40 | }, 41 | 42 | { 43 | id: 8, 44 | title: "Modal", 45 | path: "/modal", 46 | }, 47 | { 48 | id: 9, 49 | title: "Open Clicked Modal", 50 | path: "/clicked-modal", 51 | }, 52 | { 53 | id: 10, 54 | title: "Load More", 55 | path: "/load-more", 56 | }, 57 | { 58 | id: 11, 59 | title: "Filterable Gallery", 60 | path: "/filterable-gallery", 61 | }, 62 | { 63 | id: 12, 64 | title: "Search Filter", 65 | path: "/search-filter", 66 | }, 67 | ]; 68 | 69 | export default homeData; 70 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap'); 2 | 3 | 4 | /*=====-- Global Variables --=====*/ 5 | :root { 6 | --color: #61DAFB; 7 | --color-1: #13131f; 8 | --color-2: #161623; 9 | --color-3: #a9afc3; 10 | --color-4: #202324; 11 | --color-5: #454a4d; 12 | --color-6: #60696e; 13 | --shadow: inset 8px 8px 10px rgba(255, 255, 255, 0.2), inset -10px -10px 15px rgba(0, 0, 0, 0.9); 14 | } 15 | 16 | 17 | /*=====-- CSS Resets --=====*/ 18 | ::-moz-selection { 19 | background-color: var(--color-5); 20 | color: #fff; 21 | } 22 | 23 | ::selection { 24 | background-color: var(--color-5); 25 | color: #fff; 26 | } 27 | 28 | ::-webkit-scrollbar { 29 | width: auto; 30 | } 31 | 32 | ::-webkit-scrollbar-track { 33 | background-color: var(--color-4); 34 | } 35 | 36 | ::-webkit-scrollbar-thumb { 37 | background-color: var(--color-5); 38 | } 39 | 40 | ::-webkit-scrollbar-thumb:hover { 41 | background-color: var(--color-6); 42 | } 43 | 44 | *, 45 | *::before, 46 | *::after { 47 | margin: 0; 48 | padding: 0; 49 | box-sizing: border-box; 50 | } 51 | 52 | html { 53 | font-size: 16px; 54 | scrollbar-color: var(--color-5) var(--color-4); 55 | } 56 | 57 | body { 58 | font-family: 'Roboto', sans-serif; 59 | background-color: var(--color-1); 60 | color: var(--color-3); 61 | } 62 | 63 | input, 64 | button, 65 | textarea { 66 | border: none; 67 | outline: none; 68 | background-color: transparent; 69 | color: inherit; 70 | font-size: inherit; 71 | font-family: inherit; 72 | } 73 | 74 | button { 75 | cursor: pointer; 76 | } 77 | 78 | textarea { 79 | resize: vertical; 80 | } 81 | 82 | ul { 83 | list-style-type: none; 84 | } 85 | 86 | a { 87 | text-decoration: none; 88 | color: inherit; 89 | } 90 | 91 | img { 92 | max-width: 100%; 93 | height: auto; 94 | } 95 | 96 | img, 97 | svg { 98 | vertical-align: middle; 99 | user-select: none; 100 | } 101 | 102 | 103 | /*=====-- Common Styles --=====*/ 104 | .section { 105 | min-height: 100vh; 106 | padding: 1rem; 107 | display: grid; 108 | place-items: center; 109 | } 110 | 111 | .container { 112 | max-width: 1340px; 113 | margin-left: auto; 114 | margin-right: auto; 115 | padding-left: 0.75rem; 116 | padding-right: 0.75rem; 117 | } 118 | 119 | .overflow_hide { 120 | overflow: hidden; 121 | } 122 | 123 | .modal_centered { 124 | min-height: calc(100% - 3rem); 125 | margin: 1.5rem; 126 | display: grid; 127 | place-items: center; 128 | } 129 | 130 | @media (max-width: 576px) { 131 | .modal_centered { 132 | min-height: calc(100% - 1rem); 133 | margin: 0.5rem; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import { BrowserRouter } from "react-router-dom"; 7 | 8 | const root = ReactDOM.createRoot(document.getElementById('root')); 9 | root.render( 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/projects/accordion/Accordion.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import accordionData from './accordionData'; 3 | import { AccordionWrapper } from './AccordionStyled'; 4 | 5 | const Accordion = () => { 6 | 7 | const [isClicked, setIsClicked] = useState(null); 8 | 9 | const handleIsClicked = (id) => { 10 | if (isClicked === id) { 11 | // if previously clicked accordion-item is already open, then close it. 12 | return setIsClicked(null); 13 | } 14 | 15 | // and open the currently clicked accordion-item having the id value we passed. 16 | setIsClicked(id); 17 | }; 18 | 19 | return ( 20 | <> 21 |
22 | 23 | { 24 | accordionData.map((currValue) => { 25 | const { id, title, content } = currValue; 26 | return ( 27 |
28 | 29 | {/*===== Accordion-title =====*/} 30 |
handleIsClicked(id)} 33 | > 34 |

{title}

35 |
36 | 37 | 38 |
39 |
40 | 41 | {/* ===== Accordion-content ===== */} 42 |
43 |

{content}

44 |
45 | 46 |
47 | ); 48 | }) 49 | } 50 |
51 |
52 | 53 | ); 54 | }; 55 | 56 | export default Accordion; -------------------------------------------------------------------------------- /src/projects/accordion/AccordionStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const AccordionWrapper = styled.div` 4 | max-width: 800px; 5 | width: 100%; 6 | 7 | .accordion_item { 8 | border: 1px solid #333; 9 | 10 | .accordion_title { 11 | background-color: var(--color-2); 12 | box-shadow: 0px 4px 8px rgba(0,0,0,0.6); 13 | padding: 1.25rem; 14 | display: flex; 15 | justify-content: space-between; 16 | align-items: center; 17 | cursor: pointer; 18 | 19 | h2 { 20 | font-size: 1.2rem; 21 | 22 | @media (max-width: 576px) { 23 | font-size: 1rem; 24 | } 25 | } 26 | 27 | .toggle_icon { 28 | width: 15px; 29 | height: 15px; 30 | display: flex; 31 | flex-direction: column; 32 | justify-content: center; 33 | overflow: hidden; 34 | 35 | span { 36 | width: 100%; 37 | height: 2px; 38 | margin-top: -2px; 39 | background-color: var(--color-3); 40 | 41 | &:first-child { 42 | transform: rotate(-90deg); 43 | transition: transform 0.3s ease-out; 44 | } 45 | } 46 | } 47 | 48 | 49 | /* when the accordion_title has 'active' class then... */ 50 | &.active { 51 | 52 | .toggle_icon span:first-child { 53 | transform: rotate(0deg); 54 | } 55 | 56 | & + .accordion_content { 57 | display: block; 58 | animation: fadein 0.5s ease-out; 59 | 60 | @keyframes fadein { 61 | 0% { 62 | opacity: 0; 63 | } 64 | 100% { 65 | opacity: 1; 66 | } 67 | } 68 | } 69 | 70 | } 71 | } 72 | 73 | .accordion_content { 74 | display: none; 75 | padding: 1.25rem; 76 | line-height: 1.4; 77 | letter-spacing: 0.6px; 78 | } 79 | } 80 | `; -------------------------------------------------------------------------------- /src/projects/accordion/accordionData.js: -------------------------------------------------------------------------------- 1 | const accordionData = [ 2 | { 3 | id: 1, 4 | title: "What is the virtual DOM?", 5 | content: "DOM stands for Document Object Model. The DOM represents an HTML document with a logical tree structure. Each branch of the tree ends in a node, and each node contains objects." 6 | }, 7 | { 8 | id: 2, 9 | title: "What are synthetic events in React?", 10 | content: "Synthetic events combine the response of different browser's native events into one API, ensuring that the events are consistent across different browsers." 11 | }, 12 | { 13 | id: 3, 14 | title: "What are the components in React?", 15 | content: "Components are the building blocks of any React application, and a single app usually consists of multiple components. A component is essentially a piece of the user interface. It splits the user interface into independent, reusable parts that can be processed separately." 16 | }, 17 | { 18 | id: 4, 19 | title: "Can web browsers read JSX directly?", 20 | content: "Web browsers cannot read JSX directly. This is because they are built to only read regular JS objects and JSX is not a regular JavaScript object. For a web browser to read a JSX file, the file needs to be transformed into a regular JavaScript object. For this, we use Babel" 21 | }, 22 | ] 23 | 24 | export default accordionData; -------------------------------------------------------------------------------- /src/projects/back-to-top/BackTop.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { BackTopWrapper } from './BackTopStyled'; 3 | 4 | const BackTop = () => { 5 | 6 | const [isVisible, setIsVisible] = useState(false); 7 | 8 | // back-to-top visibility toggling 9 | useEffect(() => { 10 | const handleIsVisible = () => { 11 | if (window.scrollY >= 300) { 12 | setIsVisible(true); 13 | } else { 14 | setIsVisible(false); 15 | } 16 | }; 17 | 18 | window.addEventListener('scroll', handleIsVisible); 19 | 20 | return () => { 21 | window.removeEventListener('scroll', handleIsVisible); 22 | }; 23 | }, []); 24 | 25 | 26 | // back-to-top functionality 27 | const backToTop = () => { 28 | window.scrollTo({ 29 | top: 0, 30 | behavior: 'smooth' 31 | }); 32 | }; 33 | 34 | 35 | return ( 36 | <> 37 |
38 |

Scroll Down

39 |
40 |
41 |

Back To Top

42 |
43 | 44 | {/*===== Back-to-top =====*/} 45 | 50 | 51 | 52 | 53 | 54 | 55 | ); 56 | }; 57 | 58 | export default BackTop; -------------------------------------------------------------------------------- /src/projects/back-to-top/BackTopStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const BackTopWrapper = styled.div` 4 | position: fixed; 5 | bottom: 3vh; 6 | right: 2vw; 7 | z-index: 99; 8 | background-color: var(--color-5); 9 | color: #fff; 10 | padding: 0.8rem; 11 | border-radius: 50%; 12 | cursor: pointer; 13 | overflow: hidden; 14 | opacity: 0; 15 | visibility: hidden; 16 | transform: translateY(200%); 17 | transition: all 0.3s ease-out; 18 | 19 | &.show { 20 | opacity: 1; 21 | visibility: visible; 22 | transform: translateY(0); 23 | } 24 | 25 | svg { 26 | width: 25px; 27 | height: 25px; 28 | transition: transform 0.2s ease; 29 | } 30 | 31 | &:hover svg { 32 | transform: translateY(-2px); 33 | } 34 | `; -------------------------------------------------------------------------------- /src/projects/clicked-modal/ClickedModal.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import ClickedModalBox from './ClickedModalBox'; 3 | import clickedModalData from './clickedModalData'; 4 | import { ClickedModalWrapper, Button } from './ClickedModalStyled'; 5 | 6 | const ClickedModal = () => { 7 | 8 | const [isModalOpen, setIsModalOpen] = useState(false); 9 | 10 | 11 | // disable the body-scroll when the Modal is open. 12 | const docBody = document.body; 13 | isModalOpen ? docBody.classList.add('overflow_hide') : docBody.classList.remove('overflow_hide'); 14 | 15 | 16 | // closing the Modal on clicking outside of it. 17 | useEffect(() => { 18 | const outsideClose = (e) => { 19 | if (e.target.className === 'modal_centered') { 20 | setIsModalOpen(false); 21 | } 22 | }; 23 | 24 | window.addEventListener('click', outsideClose); 25 | 26 | return () => { 27 | window.removeEventListener('click', outsideClose); 28 | }; 29 | }, [isModalOpen]); 30 | 31 | 32 | // closing the Modal on pressing the 'Escape' key. 33 | useEffect(() => { 34 | const escapeClose = (e) => { 35 | if (e.key === 'Escape') { 36 | setIsModalOpen(false); 37 | } 38 | }; 39 | 40 | window.addEventListener('keydown', escapeClose); 41 | 42 | return () => { 43 | window.removeEventListener('keydown', escapeClose); 44 | }; 45 | }, [isModalOpen]); 46 | 47 | 48 | return ( 49 | <> 50 |
51 | 52 | { 53 | clickedModalData.map((currValue) => { 54 | const { id, img, title, desc } = currValue; 55 | return ( 56 |
57 | {title} 58 |

{title}

59 |

{desc.slice(0, 40)}...

60 | 66 |
67 | ); 68 | }) 69 | } 70 |
71 |
72 | 73 | 74 | {/*===== All the Modals =====*/} 75 | { 76 | clickedModalData.map((currValue) => { 77 | return ( 78 | 84 | ); 85 | }) 86 | } 87 | 88 | ); 89 | }; 90 | 91 | export default ClickedModal; -------------------------------------------------------------------------------- /src/projects/clicked-modal/ClickedModalBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button, ModalBox } from './ClickedModalStyled'; 3 | 4 | const ClickedModalBox = (props) => { 5 | 6 | const { id, img, title, desc, isModalOpen, setIsModalOpen } = props; 7 | 8 | return ( 9 | <> 10 | 11 |
12 |
13 | {title} 14 |

{title}

15 |

{desc}

16 | 22 |
23 |
24 |
25 | 26 | ); 27 | }; 28 | 29 | export default ClickedModalBox; -------------------------------------------------------------------------------- /src/projects/clicked-modal/ClickedModalStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const ClickedModalWrapper = styled.div` 4 | width: 100%; 5 | display: grid; 6 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 7 | gap: 2.4rem; 8 | 9 | @media (max-width: 576px) { 10 | grid-template-columns: 1fr; 11 | } 12 | 13 | .modal_card { 14 | background-color: var(--color-2); 15 | padding: 3rem 2rem; 16 | text-align: center; 17 | overflow: hidden; 18 | border-radius: 8px; 19 | box-shadow: var(--shadow); 20 | 21 | img { 22 | width: 80px; 23 | } 24 | 25 | h3 { 26 | font-size: 1.6rem; 27 | margin-top: 1.5rem; 28 | } 29 | 30 | p { 31 | margin: 1rem 0 2rem; 32 | letter-spacing: 0.5px; 33 | line-height: 1.5; 34 | } 35 | } 36 | `; 37 | 38 | 39 | export const Button = styled.button` 40 | border: 1px solid #444; 41 | border-radius: 2px; 42 | padding: 0.8rem 2rem; 43 | transition: background-color 0.3s ease, color 0.2s ease; 44 | 45 | &:hover { 46 | background-color: var(--color-3); 47 | color: #000; 48 | } 49 | `; 50 | 51 | 52 | export const ModalBox = styled.div` 53 | background-color: rgba(0, 0, 0, 0.4); 54 | position: fixed; 55 | top: 0; 56 | left: 0; 57 | z-index: 99; 58 | width: 100%; 59 | height: 100%; 60 | overflow-x: hidden; 61 | overflow-y: auto; 62 | pointer-events: none; 63 | opacity: 0; 64 | visibility: hidden; 65 | transition: opacity 0.3s ease, visibility 0.2s ease; 66 | 67 | &.open { 68 | pointer-events: all; 69 | opacity: 1; 70 | visibility: visible; 71 | } 72 | 73 | .modalbox_content { 74 | background: var(--color-2); 75 | box-shadow: var(--shadow); 76 | max-width: 600px; 77 | padding: 3rem; 78 | text-align: center; 79 | border-radius: 8px; 80 | overflow: hidden; 81 | transform: translateY(-50px); 82 | transition: transform 0.4s ease; 83 | 84 | @media (max-width: 576px) { 85 | padding: 2rem; 86 | } 87 | 88 | h2 { 89 | font-size: 1.8rem; 90 | margin-top: 1.2rem; 91 | } 92 | 93 | p { 94 | margin: 1rem 0 2.4rem; 95 | letter-spacing: 0.5px; 96 | line-height: 1.5; 97 | } 98 | } 99 | 100 | /* when the ModalBox has 'open' class then modalbox_content will... */ 101 | &.open .modalbox_content { 102 | transform: translateY(0); 103 | } 104 | `; -------------------------------------------------------------------------------- /src/projects/clicked-modal/clickedModalData.js: -------------------------------------------------------------------------------- 1 | const clickedModalData = [ 2 | { 3 | id: 1, 4 | img: "https://img.icons8.com/color/2x/angularjs.png", 5 | title: 'Angular JS', 6 | desc: 'AngularJS is a structural JavaScript framework for developing single-page applications. It was maintained mainly by Google' 7 | }, 8 | { 9 | id: 2, 10 | img: "https://img.icons8.com/color/2x/react-native.png", 11 | title: 'React JS', 12 | desc: 'React is a declarative, efficient, and flexible JavaScript library for building user interfaces based on UI components.' 13 | }, 14 | { 15 | id: 3, 16 | img: "https://img.icons8.com/color/2x/vue-js.png", 17 | title: 'Vue JS', 18 | desc: 'VueJS is a progressive JavaScript framework for building user interfaces and single-page applications.' 19 | }, 20 | ]; 21 | 22 | export default clickedModalData; -------------------------------------------------------------------------------- /src/projects/counter/Counter.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CounterWrapper } from './CounterStyled'; 3 | 4 | const Counter = () => { 5 | 6 | const [count, setCount] = useState(0); 7 | 8 | // decrement 9 | const decrement = () => { 10 | if (count <= 0) { 11 | setCount(0); 12 | } else { 13 | setCount(prevState => prevState - 1); 14 | } 15 | }; 16 | 17 | // increment 18 | const increment = () => { 19 | setCount(prevState => prevState + 1); 20 | }; 21 | 22 | 23 | return ( 24 | <> 25 |
26 | 27 |

React Counter

28 | 29 |
30 | 38 | 39 |

{count}

40 | 41 | 48 |
49 | 50 | {/* Counter Reset-btn */} 51 | 59 |
60 |
61 | 62 | ); 63 | }; 64 | 65 | export default Counter; -------------------------------------------------------------------------------- /src/projects/counter/CounterStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const CounterWrapper = styled.div` 4 | background-color: var(--color-2); 5 | max-width: 800px; 6 | width: 100%; 7 | padding: 5rem; 8 | text-align: center; 9 | border-radius: 20px; 10 | box-shadow: var(--shadow); 11 | user-select: none; 12 | overflow: hidden; 13 | 14 | @media (max-width: 768px) { 15 | padding: 3rem; 16 | } 17 | 18 | .counter { 19 | display: grid; 20 | grid-template-columns: 0.4fr 1fr 0.4fr; 21 | gap: 2rem; 22 | margin-top: 6rem; 23 | margin-bottom: 5rem; 24 | 25 | @media (max-width: 576px) { 26 | grid-template-columns: 1fr; 27 | margin-top: 4rem; 28 | margin-bottom: 3rem; 29 | } 30 | 31 | .counter_count, 32 | .counter_btn { 33 | background-color: var(--color-1); 34 | border-radius: 100px; 35 | } 36 | 37 | .counter_count { 38 | font-size: 3.5rem; 39 | padding: 0.3rem 0; 40 | } 41 | 42 | .counter_btn { 43 | font-size: 3rem; 44 | transition: transform 0.2s ease, opacity 0.2s ease; 45 | 46 | &:active { 47 | transform: scale(0.9); 48 | } 49 | 50 | &[disabled] { 51 | opacity: 0.6; 52 | pointer-events: none; 53 | } 54 | } 55 | } 56 | 57 | .reset_btn { 58 | background-color: var(--color-3); 59 | color: #000; 60 | font-size: 1.4rem; 61 | padding: 1rem 4rem; 62 | border-radius: 100px; 63 | transition: transform 0.3s ease, opacity 0.2s ease; 64 | 65 | @media (max-width: 768px) { 66 | transform: scale(0.8); 67 | } 68 | 69 | &:hover { 70 | transform: translateY(-2px); 71 | } 72 | 73 | &:active { 74 | transform: translateY(0); 75 | } 76 | 77 | &[disabled] { 78 | opacity: 0.7; 79 | pointer-events: none; 80 | } 81 | } 82 | `; -------------------------------------------------------------------------------- /src/projects/filterable-gallery/FilterableGallery.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import galleryData from './galleryData'; 3 | import { GalleryWrapper, FilterList } from './FilterableGalleryStyled'; 4 | 5 | const FilterableGallery = () => { 6 | 7 | const [galleryItems, setGalleryItems] = useState(galleryData); 8 | const [isActive, setIsActive] = useState(0); 9 | 10 | 11 | // making a unique set of items-category 12 | const uniqueList = [ 13 | 'all', 14 | ...new Set( 15 | galleryData.map((currValue) => { 16 | return currValue.category; 17 | }) 18 | ) 19 | ]; 20 | 21 | 22 | // filtering the clicked item 23 | const filterItem = (category, i) => { 24 | 25 | if (category === 'all') { 26 | setGalleryItems(galleryData); 27 | setIsActive(i); 28 | return; 29 | } 30 | 31 | const filteredData = galleryData.filter((currValue) => { 32 | return category === currValue.category; 33 | 34 | }); 35 | 36 | setGalleryItems(filteredData); 37 | setIsActive(i); 38 | }; 39 | 40 | 41 | return ( 42 | <> 43 |
44 | 45 | { 46 | uniqueList.map((currValue, index) => { 47 | return ( 48 |
  • filterItem(currValue, index)} 52 | > 53 | {currValue} 54 |
  • 55 | ); 56 | }) 57 | } 58 |
    59 | 60 | 61 | { 62 | galleryItems.map((currValue) => { 63 | const { id, img } = currValue; 64 | return ( 65 |
    66 | gallery-img 67 |
    68 | ); 69 | }) 70 | } 71 |
    72 |
    73 | 74 | ); 75 | }; 76 | 77 | export default FilterableGallery; 78 | -------------------------------------------------------------------------------- /src/projects/filterable-gallery/FilterableGalleryStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const FilterList = styled.ul` 4 | background-color: var(--color-2); 5 | margin: 2rem 0 3rem; 6 | padding: 1.5rem 1rem; 7 | display: flex; 8 | flex-wrap: wrap; 9 | justify-content: space-around; 10 | row-gap: 0.5rem; 11 | border-radius: 8px; 12 | box-shadow: var(--shadow); 13 | 14 | li { 15 | padding: 0.7rem 2rem; 16 | border-radius: 50px; 17 | font-size: 0.94rem; 18 | letter-spacing: 0.6px; 19 | text-transform: uppercase; 20 | cursor: pointer; 21 | transition: color 0.3s ease; 22 | 23 | &.active { 24 | color: var(--color); 25 | } 26 | } 27 | `; 28 | 29 | export const GalleryWrapper = styled.div` 30 | display: grid; 31 | grid-template-columns: repeat(4, 1fr); 32 | gap: 1rem; 33 | margin-bottom: 2rem; 34 | 35 | @media (max-width: 768px) { 36 | grid-template-columns: repeat(3, 1fr); 37 | gap: 0.5rem; 38 | } 39 | 40 | @media (max-width: 576px) { 41 | grid-template-columns: repeat(2, 1fr); 42 | } 43 | 44 | .gallery_item { 45 | border-radius: 10px; 46 | overflow: hidden; 47 | 48 | img { 49 | width: 100%; 50 | height: 100%; 51 | object-fit: cover; 52 | } 53 | } 54 | `; 55 | -------------------------------------------------------------------------------- /src/projects/filterable-gallery/galleryData.js: -------------------------------------------------------------------------------- 1 | const galleryData = [ 2 | { 3 | id: 1, 4 | img: "https://cdn.pixabay.com/photo/2016/12/13/22/25/bird-1905255__340.jpg", 5 | category: "birds", 6 | }, 7 | { 8 | id: 2, 9 | img: "https://cdn.pixabay.com/photo/2015/04/19/08/33/flower-729512_960_720.jpg", 10 | category: "flowers", 11 | }, 12 | { 13 | id: 3, 14 | img: "https://cdn.pixabay.com/photo/2016/12/05/11/39/fox-1883658__340.jpg", 15 | category: "animals", 16 | }, 17 | { 18 | id: 4, 19 | img: "https://cdn.pixabay.com/photo/2016/10/25/12/28/iceland-1768744__340.jpg", 20 | category: "waterfalls", 21 | }, 22 | { 23 | id: 5, 24 | img: "https://cdn.pixabay.com/photo/2012/02/24/16/59/swan-16736__340.jpg", 25 | category: "birds", 26 | }, 27 | { 28 | id: 6, 29 | img: "https://cdn.pixabay.com/photo/2015/10/09/00/55/lotus-978659_960_720.jpg", 30 | category: "flowers", 31 | }, 32 | { 33 | id: 7, 34 | img: "https://cdn.pixabay.com/photo/2016/11/29/10/07/tiger-1868911__340.jpg", 35 | category: "animals", 36 | }, 37 | { 38 | id: 8, 39 | img: "https://cdn.pixabay.com/photo/2019/06/08/11/17/waterfall-4259935__340.jpg", 40 | category: "waterfalls", 41 | }, 42 | { 43 | id: 9, 44 | img: "https://cdn.pixabay.com/photo/2020/07/01/15/29/landscape-5359998__340.jpg", 45 | category: "waterfalls", 46 | }, 47 | { 48 | id: 10, 49 | img: "https://cdn.pixabay.com/photo/2013/07/21/13/00/rose-165819_960_720.jpg", 50 | category: "flowers", 51 | }, 52 | { 53 | id: 11, 54 | img: "https://cdn.pixabay.com/photo/2014/05/11/13/39/bird-341898__340.jpg", 55 | category: "birds", 56 | }, 57 | { 58 | id: 12, 59 | img: "https://cdn.pixabay.com/photo/2020/05/03/18/49/baby-elephant-5126326__340.jpg", 60 | category: "animals", 61 | }, 62 | ]; 63 | 64 | export default galleryData; -------------------------------------------------------------------------------- /src/projects/loadMore/LoadMore.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { LoadMoreWrapper } from './LoadMoreStyled'; 3 | 4 | const LoadMore = () => { 5 | 6 | const [items, setItems] = useState([]); 7 | const [visibleItems, setVisibleItems] = useState(3); 8 | 9 | 10 | useEffect(() => { 11 | fetch('https://jsonplaceholder.typicode.com/posts/?_limit=20') 12 | .then(resp => resp.json()) 13 | .then(data => setItems(data)); 14 | }, []); 15 | 16 | 17 | // Load More functionality 18 | const loadMoreItems = () => { 19 | setVisibleItems(prevState => prevState + 3); 20 | }; 21 | 22 | 23 | return ( 24 | <> 25 |
    26 |
    27 | 28 | { 29 | items.slice(0, visibleItems).map((currValue) => { 30 | const { id, body } = currValue; 31 | return ( 32 |
    33 |

    {id}

    34 |

    {body}

    35 |
    36 | ); 37 | }) 38 | } 39 |
    40 | 41 |
    42 | 49 |
    50 |
    51 |
    52 | 53 | ); 54 | }; 55 | 56 | export default LoadMore; -------------------------------------------------------------------------------- /src/projects/loadMore/LoadMoreStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const LoadMoreWrapper = styled.div` 4 | display: grid; 5 | grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); 6 | gap: 3rem; 7 | 8 | @media (max-width: 576px) { 9 | grid-template-columns: 1fr; 10 | } 11 | 12 | .load_more_card { 13 | background-color: var(--color-2); 14 | box-shadow: var(--shadow); 15 | padding: 2.5rem 3rem; 16 | 17 | h2 { 18 | margin-bottom: 1rem; 19 | } 20 | } 21 | 22 | & + .load_more_btn { 23 | text-align: center; 24 | margin-top: 3rem; 25 | user-select: none; 26 | 27 | button { 28 | background-color: var(--color-2); 29 | box-shadow: var(--shadow); 30 | padding: 1.2rem 2rem; 31 | font-size: 1.2rem; 32 | transition: transform 0.3s ease; 33 | 34 | &:hover { 35 | transform: scale(1.03); 36 | } 37 | 38 | &[disabled] { 39 | opacity: 0.5; 40 | pointer-events: none; 41 | } 42 | } 43 | } 44 | `; -------------------------------------------------------------------------------- /src/projects/modal/Modal.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import ModalBox from './ModalBox'; 3 | import { Button } from './ModalStyled'; 4 | 5 | const Modal = () => { 6 | 7 | const [isModalOpen, setIsModalOpen] = useState(false); 8 | 9 | 10 | // disable the body-scroll when the Modal is open. 11 | const docBody = document.body; 12 | isModalOpen ? docBody.classList.add('overflow_hide') : docBody.classList.remove('overflow_hide'); 13 | 14 | 15 | // closing the Modal on clicking outside of it. 16 | useEffect(() => { 17 | const outsideClose = (e) => { 18 | if (e.target.className === 'modal_centered') { 19 | setIsModalOpen(false); 20 | } 21 | }; 22 | 23 | window.addEventListener('click', outsideClose); 24 | 25 | return () => { 26 | window.removeEventListener('click', outsideClose); 27 | }; 28 | }, [isModalOpen]); 29 | 30 | 31 | // closing the Modal on pressing the 'Escape' key. 32 | useEffect(() => { 33 | const escapeClose = (e) => { 34 | if (e.key === 'Escape') { 35 | setIsModalOpen(false); 36 | } 37 | }; 38 | 39 | window.addEventListener('keydown', escapeClose); 40 | 41 | return () => { 42 | window.removeEventListener('keydown', escapeClose); 43 | }; 44 | }, [isModalOpen]); 45 | 46 | 47 | return ( 48 | <> 49 |
    50 | 56 |
    57 | 58 | 59 | {/*===== Modal =====*/} 60 | 64 | 65 | ); 66 | }; 67 | 68 | export default Modal; -------------------------------------------------------------------------------- /src/projects/modal/ModalBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button, ModalWrapper } from './ModalStyled'; 3 | import img from '../../logo.svg'; 4 | 5 | const ModalBox = (props) => { 6 | 7 | const { isModalOpen, setIsModalOpen } = props; 8 | 9 | return ( 10 | <> 11 | 12 |
    13 |
    14 |
    15 | modal-img 16 |
    17 |

    This modal is made using ReactJs. ReactJs is a JavaScript library for building user interfaces. React makes it painless to create interactive UIs.

    18 | 24 |
    25 |
    26 |
    27 | 28 | ); 29 | }; 30 | 31 | export default ModalBox; -------------------------------------------------------------------------------- /src/projects/modal/ModalStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Button = styled.button` 4 | color: var(--color); 5 | border: 2px solid var(--color); 6 | font-size: 1.2rem; 7 | padding: 0.8rem 1.5rem; 8 | transition: background-color 0.3s ease, color 0.2s ease; 9 | 10 | &:hover { 11 | background-color: var(--color); 12 | color: #000; 13 | } 14 | `; 15 | 16 | 17 | export const ModalWrapper = styled.div` 18 | background-color: rgba(0, 0, 0, 0.4); 19 | position: fixed; 20 | top: 0; 21 | left: 0; 22 | z-index: 99; 23 | width: 100%; 24 | height: 100%; 25 | overflow-x: hidden; 26 | overflow-y: auto; 27 | pointer-events: none; 28 | opacity: 0; 29 | visibility: hidden; 30 | transition: opacity 0.3s ease, visibility 0.2s ease; 31 | 32 | &.open { 33 | pointer-events: all; 34 | opacity: 1; 35 | visibility: visible; 36 | } 37 | 38 | .modal_content { 39 | background-color: var(--color-2); 40 | box-shadow: var(--shadow); 41 | max-width: 600px; 42 | padding: 3rem; 43 | display: grid; 44 | place-items: center; 45 | text-align: center; 46 | overflow: hidden; 47 | transform: scale(0); 48 | transition: transform 0.4s ease; 49 | 50 | .modal_img { 51 | width: 150px; 52 | } 53 | 54 | .modal_txt { 55 | margin-top: 1rem; 56 | margin-bottom: 2rem; 57 | line-height: 1.6; 58 | letter-spacing: 0.8px; 59 | } 60 | } 61 | 62 | /* when the ModalWrapper has 'open' class then modal_content will... */ 63 | &.open .modal_content { 64 | transform: scale(1); 65 | } 66 | `; -------------------------------------------------------------------------------- /src/projects/readmore/ReadMore.js: -------------------------------------------------------------------------------- 1 | import ReadMoreCard from './ReadMoreCard'; 2 | import readMoreData from './readMoreData'; 3 | import { ReadMoreWrapper } from './ReadMoreStyled'; 4 | 5 | const ReadMore = () => { 6 | return ( 7 | <> 8 |
    9 | 10 | { 11 | readMoreData.map((currValue) => { 12 | return ( 13 | 17 | ); 18 | }) 19 | } 20 | 21 |
    22 | 23 | ); 24 | }; 25 | 26 | export default ReadMore; -------------------------------------------------------------------------------- /src/projects/readmore/ReadMoreCard.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { ReadMoreCardWrapper } from './ReadMoreStyled'; 3 | 4 | const ReadMoreCard = (props) => { 5 | 6 | const { title, desc } = props; 7 | 8 | const [isTruncated, setIsTruncated] = useState(true); 9 | 10 | const handleIsTruncated = () => { 11 | setIsTruncated(prevState => !prevState); 12 | }; 13 | 14 | 15 | return ( 16 | <> 17 | 18 |

    {title}

    19 |

    20 | {isTruncated ? desc.slice(0, 70) + '...' : desc} 21 |

    22 | 25 |
    26 | 27 | ); 28 | }; 29 | 30 | export default ReadMoreCard; -------------------------------------------------------------------------------- /src/projects/readmore/ReadMoreStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const ReadMoreWrapper = styled.div` 4 | width: 100%; 5 | display: grid; 6 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); 7 | gap: 2.2rem; 8 | 9 | @media(max-width: 576px) { 10 | grid-template-columns: 1fr; 11 | } 12 | `; 13 | 14 | export const ReadMoreCardWrapper = styled.div` 15 | background-color: var(--color-2); 16 | box-shadow: var(--shadow); 17 | padding: 3rem 2.5rem; 18 | text-align: center; 19 | border-radius: 6px; 20 | 21 | p { 22 | line-height: 1.6; 23 | margin: 1rem 0 1.6rem; 24 | letter-spacing: 0.5px; 25 | } 26 | 27 | button { 28 | background: var(--color-1); 29 | padding: 1rem 1.8rem; 30 | font-size: 1rem; 31 | border-radius: 4px; 32 | box-shadow: 0 4px 8px rgba(0,0,0,0.4); 33 | opacity: 0.875; 34 | 35 | &:hover { 36 | opacity: 1; 37 | } 38 | } 39 | `; -------------------------------------------------------------------------------- /src/projects/readmore/readMoreData.js: -------------------------------------------------------------------------------- 1 | const readMoreData = [ 2 | { 3 | id: 1, 4 | title: "React JS", 5 | desc: "React is a free and open-source front-end JavaScript library for building user interfaces based on UI components. The main concept of ReactJS is virtual DOM and reusable UI components." 6 | }, 7 | { 8 | id: 2, 9 | title: "Angular JS", 10 | desc: "AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and extend HTML's syntax to express your application's components clearly." 11 | }, 12 | { 13 | id: 3, 14 | title: "Vue JS", 15 | desc: "VueJS is a progressive JavaScript framework for building interactive web interfaces. It focusses on the view layer & can be easily integrated into big projects for front-end development." 16 | }, 17 | ] 18 | 19 | export default readMoreData; -------------------------------------------------------------------------------- /src/projects/search-filter/SearchFilter.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { SearchField } from './SearchFilterStyled'; 3 | import { GalleryWrapper } from '../filterable-gallery/FilterableGalleryStyled'; 4 | import galleryData from '../filterable-gallery/galleryData'; 5 | 6 | const SearchFilter = () => { 7 | 8 | const [searchData, setSearchData] = useState(galleryData); 9 | 10 | const handleChange = (e) => { 11 | 12 | const searchTerm = e.target.value.toLowerCase(); 13 | 14 | const filteredItem = galleryData.filter((currValue) => { 15 | return currValue.category.includes(searchTerm); 16 | }); 17 | 18 | setSearchData(filteredItem); 19 | }; 20 | 21 | 22 | return ( 23 | <> 24 |
    25 | 26 | 31 | 32 | 33 | { 34 | searchData.length === 0 && ( 35 |

    Sorry, no data found.

    36 | ) 37 | } 38 | 39 | 40 | { 41 | searchData.map((currValue) => { 42 | const { id, img } = currValue; 43 | return ( 44 |
    45 | gallery-img 46 |
    47 | ); 48 | }) 49 | } 50 |
    51 |
    52 | 53 | ); 54 | }; 55 | 56 | export default SearchFilter; -------------------------------------------------------------------------------- /src/projects/search-filter/SearchFilterStyled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const SearchField = styled.div` 4 | background-color: var(--color-2); 5 | box-shadow: 8px 8px 15px rgba(0,0,0,0.5); 6 | margin: 2.5rem 0 4rem; 7 | overflow: hidden; 8 | 9 | input { 10 | display: block; 11 | width: 100%; 12 | font-size: 1.4rem; 13 | padding: 1.5rem 2rem; 14 | 15 | @media (max-width: 576px) { 16 | font-size: 4vw; 17 | padding: 1.2rem; 18 | } 19 | } 20 | `; -------------------------------------------------------------------------------- /src/projects/sidebar/Sidebar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import { dropdownLinks, sidebarLinks } from './sidebarData'; 4 | import { SidebarToggler, SidebarWrapper } from './SidebarStyled'; 5 | 6 | const Sidebar = () => { 7 | 8 | const [isSidebarOpen, setIsSidebarOpen] = useState(false); 9 | const [isDropdownOpen, setIsDropdownOpen] = useState(false); 10 | 11 | 12 | // toggling the Sidebar 13 | const toggleSidebar = () => { 14 | setIsSidebarOpen(!isSidebarOpen); 15 | }; 16 | 17 | // toggling the Dropdown 18 | const toggleDropdown = () => { 19 | setIsDropdownOpen(!isDropdownOpen); 20 | }; 21 | 22 | 23 | // closing the Sidebar on clicking outside of it. 24 | window.addEventListener('click', (e) => { 25 | if (e.target.closest('.section')) { 26 | setIsSidebarOpen(false); 27 | } 28 | }); 29 | 30 | 31 | // disable the body-scroll when the Sidebar is open. 32 | const docBody = document.body; 33 | isSidebarOpen ? docBody.classList.add('overflow_hide') : docBody.classList.remove('overflow_hide'); 34 | 35 | 36 | return ( 37 | <> 38 |
    39 |

    React Sidebar

    40 |
    41 | 42 | {/*===== Sidebar =====*/} 43 | 44 |
    45 |

    ReactJs Sidebar

    46 |
    47 |
    48 |
      49 |
    • 50 |
      51 | All Products 52 | {isDropdownOpen ? '-' : '+'} 53 |
      54 | { 55 | isDropdownOpen && ( 56 |
        57 | { 58 | dropdownLinks.map((currValue) => { 59 | const { id, link, path } = currValue; 60 | return ( 61 |
      • 62 | {link} 63 |
      • 64 | ); 65 | }) 66 | } 67 |
      68 | ) 69 | } 70 |
    • 71 | { 72 | sidebarLinks.map((currValue) => { 73 | const { id, link, path } = currValue; 74 | return ( 75 |
    • 76 | {link} 77 |
    • 78 | ); 79 | }) 80 | } 81 |
    82 |
    83 |
    84 |

    85 | {new Date().getFullYear() + ' '} 86 | | ReactJs Sidebar. 87 |

    88 |
    89 |
    90 | 91 | {/*===== Sidebar-toggler =====*/} 92 | 96 | 97 | 98 | 99 | 100 | 101 | ); 102 | }; 103 | 104 | export default Sidebar; -------------------------------------------------------------------------------- /src/projects/sidebar/SidebarStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const SidebarWrapper = styled.div` 4 | position: fixed; 5 | top: 0; 6 | left: 0; 7 | z-index: 99; 8 | max-width: 300px; 9 | width: 80%; 10 | height: 100%; 11 | background-color: var(--color-2); 12 | box-shadow: 0px 10px 20px -3px #000; 13 | padding: 2rem; 14 | overflow-x: hidden; 15 | overflow-y: auto; 16 | user-select: none; 17 | pointer-events: none; 18 | opacity: 0; 19 | visibility: hidden; 20 | transform: translateX(-100%); 21 | transition: opacity 0.3s ease, visibility 0.2s ease, transform 0.3s ease; 22 | 23 | &.show { 24 | pointer-events: all; 25 | opacity: 1; 26 | visibility: visible; 27 | transform: translateX(0); 28 | } 29 | 30 | .sidebar_head, 31 | .sidebar_body, 32 | .sidebar_foot { 33 | padding: 2.8rem 0; 34 | } 35 | 36 | .sidebar_body { 37 | border-top: 1px dashed var(--color-3); 38 | border-bottom: 1px dashed var(--color-3); 39 | 40 | ul { 41 | display: grid; 42 | gap: 1.4rem; 43 | 44 | a { 45 | opacity: 0.8; 46 | 47 | &:hover { 48 | opacity: 1; 49 | } 50 | } 51 | } 52 | 53 | .dropdown { 54 | display: flex; 55 | justify-content: space-between; 56 | align-items: center; 57 | cursor: pointer; 58 | } 59 | 60 | .dropdown_list { 61 | list-style-type: disc; 62 | margin-top: 2rem; 63 | margin-bottom: 1.5rem; 64 | padding-left: 1rem; 65 | font-size: 0.95rem; 66 | } 67 | } 68 | `; 69 | 70 | 71 | export const SidebarToggler = styled.div` 72 | position: fixed; 73 | top: 4vh; 74 | right: 4vw; 75 | z-index: 99; 76 | width: 1.8rem; 77 | height: 1.3rem; 78 | display: flex; 79 | flex-direction: column; 80 | justify-content: space-between; 81 | cursor: pointer; 82 | overflow: hidden; 83 | 84 | span { 85 | width: 100%; 86 | height: 2.4px; 87 | background-color: var(--color-3); 88 | opacity: 0.875; 89 | transition: all 0.3s ease; 90 | } 91 | 92 | &:hover span { 93 | opacity: 1; 94 | } 95 | 96 | 97 | /* Referring to "SidebarWrapper styled-component" & when they have the 'show' class then their adjacent-sibling (i.e., SidebarToggler) will... */ 98 | 99 | ${SidebarWrapper}.show + & { 100 | justify-content: center; 101 | 102 | span { 103 | margin-top: -1.2px; 104 | margin-bottom: -1.2px; 105 | } 106 | 107 | span:first-child { 108 | transform: rotate(45deg); 109 | } 110 | 111 | span:nth-child(2) { 112 | opacity: 0; 113 | transform: translateX(-100%); 114 | } 115 | 116 | span:last-child { 117 | transform: rotate(-45deg); 118 | } 119 | } 120 | `; -------------------------------------------------------------------------------- /src/projects/sidebar/sidebarData.js: -------------------------------------------------------------------------------- 1 | export const sidebarLinks = [ 2 | { 3 | id: 1, 4 | link: "My Orders", 5 | path: "/", 6 | }, 7 | { 8 | id: 2, 9 | link: "My Account", 10 | path: "/", 11 | }, 12 | { 13 | id: 3, 14 | link: "Order Tracking", 15 | path: "/", 16 | }, 17 | { 18 | id: 4, 19 | link: "Help & Support", 20 | path: "/", 21 | }, 22 | ]; 23 | 24 | 25 | export const dropdownLinks = [ 26 | { 27 | id: 1, 28 | link: "Cameras", 29 | path: "/", 30 | }, 31 | { 32 | id: 2, 33 | link: "Mobiles", 34 | path: "/", 35 | }, 36 | { 37 | id: 3, 38 | link: "LEDs", 39 | path: "/", 40 | }, 41 | { 42 | id: 4, 43 | link: "Laptops", 44 | path: "/", 45 | }, 46 | ]; -------------------------------------------------------------------------------- /src/projects/sticky-header/StickyHeader.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { HeaderWrapper } from './StickyHeaderStyled'; 3 | import stickyHeaderData from './stickyHeaderData'; 4 | import { Link } from 'react-router-dom'; 5 | 6 | const StickyHeader = () => { 7 | 8 | const [isSticky, setIsSticky] = useState(false); 9 | 10 | // toggling the Sticky-Header functionality 11 | useEffect(() => { 12 | const handleSticky = () => { 13 | if (window.scrollY >= 100) { 14 | setIsSticky(true); 15 | } else { 16 | setIsSticky(false); 17 | } 18 | }; 19 | 20 | window.addEventListener('scroll', handleSticky); 21 | 22 | return () => { 23 | window.removeEventListener('scroll', handleSticky); 24 | }; 25 | }, []); 26 | 27 | 28 | return ( 29 | <> 30 | {/*===== Header =====*/} 31 | 32 |
    33 | 49 |
    50 |
    51 | 52 | {/*===== Sections =====*/} 53 |
    54 | { 55 | stickyHeaderData.map((currValue) => { 56 | const { id, title } = currValue; 57 | return ( 58 |
    59 |

    {title}

    60 |
    61 | ); 62 | }) 63 | } 64 |
    65 | 66 | ); 67 | }; 68 | 69 | export default StickyHeader; -------------------------------------------------------------------------------- /src/projects/sticky-header/StickyHeaderStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const HeaderWrapper = styled.header` 4 | position: fixed; 5 | top: 0; 6 | left: 0; 7 | width: 100%; 8 | padding-top: 2rem; 9 | padding-bottom: 2rem; 10 | transition: all 0.3s ease; 11 | 12 | &.sticked { 13 | background-color: var(--color-2); 14 | box-shadow: 0px 6px 24px -4px #000; 15 | } 16 | 17 | ul { 18 | display: flex; 19 | flex-wrap: wrap; 20 | justify-content: space-between; 21 | align-items: center; 22 | gap: 0.5rem; 23 | text-transform: capitalize; 24 | } 25 | 26 | & + main { 27 | section:nth-child(even) { 28 | background-color: var(--color-2); 29 | } 30 | } 31 | `; -------------------------------------------------------------------------------- /src/projects/sticky-header/stickyHeaderData.js: -------------------------------------------------------------------------------- 1 | const stickyHeaderData = [ 2 | { 3 | id: 1, 4 | title: "Home", 5 | path: "/" 6 | }, 7 | { 8 | id: 2, 9 | title: "About", 10 | path: "/" 11 | }, 12 | { 13 | id: 3, 14 | title: "Services", 15 | path: "/" 16 | }, 17 | { 18 | id: 4, 19 | title: "Contact", 20 | path: "/" 21 | } 22 | ]; 23 | 24 | export default stickyHeaderData; -------------------------------------------------------------------------------- /src/projects/tabs/Tabs.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import tabsData from './tabsData'; 3 | import TabsWrapper from './TabsStyled'; 4 | 5 | const Tabs = () => { 6 | 7 | const [activeTab, setActiveTab] = useState(1); 8 | 9 | return ( 10 | <> 11 |
    12 | 13 |
    14 | { 15 | tabsData.map((currValue) => { 16 | const { id, title } = currValue; 17 | return ( 18 | 27 | ); 28 | }) 29 | } 30 |
    31 |
    32 | { 33 | tabsData.map((currValue) => { 34 | const { id, content } = currValue; 35 | return ( 36 |

    37 | {activeTab === id && content} 38 |

    39 | ); 40 | }) 41 | } 42 |
    43 |
    44 |
    45 | 46 | ); 47 | }; 48 | 49 | export default Tabs; -------------------------------------------------------------------------------- /src/projects/tabs/TabsStyled.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const TabsWrapper = styled.div` 4 | background-color: var(--color-2); 5 | max-width: 800px; 6 | width: 100%; 7 | box-shadow: var(--shadow); 8 | padding: 1.6rem; 9 | 10 | @media (max-width: 576px) { 11 | padding: 1.2rem; 12 | } 13 | 14 | .tabs { 15 | display: flex; 16 | flex-wrap: wrap; 17 | justify-content: space-between; 18 | align-items: center; 19 | border-bottom: 1px solid #333; 20 | 21 | button { 22 | padding: 1rem 1.8rem; 23 | transition: all 0.3s ease; 24 | 25 | &[disabled] { 26 | cursor: not-allowed; 27 | } 28 | 29 | &.active { 30 | color: var(--color); 31 | border-bottom: 1px solid var(--color); 32 | } 33 | 34 | @media (max-width: 576px) { 35 | font-size: 0.9rem; 36 | padding: 0.8rem; 37 | } 38 | 39 | } 40 | } 41 | 42 | .tabs_panel { 43 | padding: 3rem 1rem 2rem; 44 | 45 | @media (max-width: 576px) { 46 | padding-top: 2rem; 47 | padding-bottom: 1rem; 48 | } 49 | 50 | p { 51 | letter-spacing: 0.6px; 52 | line-height: 2; 53 | } 54 | } 55 | `; 56 | 57 | export default TabsWrapper; 58 | -------------------------------------------------------------------------------- /src/projects/tabs/tabsData.js: -------------------------------------------------------------------------------- 1 | const tabsData = [ 2 | { 3 | id: 1, 4 | title: "HTML", 5 | content: "HTML (HyperText Markup Language) is the most basic building block of the Web. It defines the meaning and structure of web content. 'Hypertext' refers to links that connect web pages to one another, either within a single website or between websites.", 6 | }, 7 | { 8 | id: 2, 9 | title: "CSS", 10 | content: "Cascading Style Sheets (CSS) is a stylesheet language used to describe the presentation (style) of a document written in HTML or XML. CSS describes how elements should be rendered on screen, on paper, in speech, or on other media.", 11 | }, 12 | { 13 | id: 3, 14 | title: "JavaScript", 15 | content: "JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language. While it is most well-known as the scripting language for Web pages, many non-browser environments also use it, such as Node.js, Apache CouchDB.", 16 | }, 17 | ]; 18 | 19 | export default tabsData; -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | --------------------------------------------------------------------------------