├── .gitignore ├── LICENSE ├── README.md ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public └── react.svg ├── src ├── App.jsx ├── Author.jsx ├── Hero.jsx ├── Hero.module.css ├── components │ ├── VictorEZCodes │ │ ├── FormValidator.jsx │ │ ├── FormValidator.module.css │ │ ├── ProgressBar.jsx │ │ ├── ProgressBar.module.css │ │ ├── SearchFilter.jsx │ │ ├── SearchFilter.module.css │ │ ├── ThemeSwitcher.jsx │ │ ├── ThemeSwitcher.module.css │ │ ├── Toast.jsx │ │ └── Toast.module.css │ ├── kelixirr │ │ ├── AccordionItems.jsx │ │ ├── AccordionItems.module.css │ │ ├── Details.jsx │ │ ├── Details.module.css │ │ ├── Header.jsx │ │ ├── Header.module.css │ │ ├── PopUpModal.jsx │ │ ├── PopUpModal.module.css │ │ ├── SliderCards.jsx │ │ └── SliderCards.module.css │ ├── mektefaie │ │ ├── FlashCards.jsx │ │ └── FlashCards.module.css │ ├── rrusyaidii │ │ ├── Login.jsx │ │ └── Login.module.css │ └── sushantpokhrel │ │ ├── Modal.jsx │ │ └── Modal.module.css ├── index.css └── main.jsx └── vite.config.js /.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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Amritesh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Contribute to the ReactDevs - A Playground for react learners 2 | 3 | Welcome to the **ReactDevs** project! This repository allows beginners to contribute one or more React components of their choice. This guide will walk you through every step of the process to ensure you can easily contribute to the project. Follow these steps carefully to add your own component, including a small credit section that links to your name and GitHub profile. 4 | 5 | ### Why Be Part Of This Project? 6 | - **Git**: Learn version control and collaboration using Git. 7 | - **GitHub**: Gain experience with GitHub for managing and contributing to open-source projects. Earn Github badges. 8 | - **Collaboration**: Work together with developers of all skill levels to build something meaningful. 9 | - **Project Building**: Contribute to a real-world project, gaining hands-on experience. 10 | - **Learn to Contribute to Open Source**: Understand the process of contributing to open-source projects. 11 | - **Learn from Others**: Discover new techniques and approaches from fellow contributors. 12 | - **Practice React Skills**: Hone your React skills by building components and working with others. 13 | - **Networking**: Connect with other developers and expand your professional network. 14 | - **Build a Portfolio**: Showcase your contributions in your personal portfolio to attract future opportunities. 15 | 16 | --- 17 | 18 | ## **1. Prerequisites** 19 | 20 | Before you begin contributing to the project, you'll need a few things installed on your local machine: 21 | 22 | - **Node.js**: This project uses Node.js for running JavaScript code. You can download and install it from [here](https://nodejs.org/). 23 | - **Git**: Git is necessary for version control and contributing to the project. Install it from [here](https://git-scm.com/). 24 | - **Text Editor (VS Code recommended)**: You'll need a code editor to edit the project's files. [Visual Studio Code](https://code.visualstudio.com/) is highly recommended. 25 | - **GitHub Account**: You need a GitHub account to fork and submit pull requests to the project. If you don’t have one, create one at [GitHub](https://github.com/). 26 | 27 | --- 28 | 29 | ### Rules - Don't Forget The Rules 30 | 1. Star the repository so that more people can discover it and join. 31 | 2. Create a folder name based on your github username for the component as explained below.Use unqiue component names. 32 | 3. Code on your own. Make it unique. You can contribute multiple components. 33 | 4. Don't touch or change anything that is already there without discussing. Raise an issue here on GitHub first. 34 | 5. Use the colors and root variables defined in the index.css file to maintain the design consistency. Don't add any color on your own. 35 | 6. Use rem for font-size, borders etc. You are free to adjust sizes except for border radius. 36 | 7. Help others and engage with project community. Don't forget to invite more people to this project. 37 | 8. Don't hesistate to ask if you are stuck somewhere. 38 | 39 | ## **2. Fork the Repository** 40 | 41 | ### **Step 1: Fork the Repository** 42 | - Go to the [ReactDevs repository](https://github.com/kelixirr/ReactDevs) on GitHub. 43 | - In the top-right corner of the page, click the **Fork** button. This creates a personal copy of the repository under your GitHub account. 44 | 45 | ### **Step 2: Clone the Forked Repository** 46 | Once you’ve forked the repository, you need to clone it to your local machine so you can start working on it. 47 | 48 | - On your forked repository page, click the **Code** button and copy the URL (either HTTPS or SSH). 49 | - Open your terminal or command prompt and run the following command to clone the repository: 50 | 51 | ```bash 52 | git clone 53 | ``` 54 | 55 | This will create a copy of the repository on your machine. 56 | 57 | ### **Step 3: Navigate to the Project Folder** 58 | Once you have cloned the repository, navigate to the project directory: 59 | 60 | ```bash 61 | cd 62 | ``` 63 | 64 | --- 65 | 66 | ## **3. Set Up the Project Locally** 67 | 68 | Now that you have the repository on your local machine, it's time to set it up. 69 | 70 | ### **Step 1: Install Dependencies** 71 | 72 | This project uses `npm` (Node Package Manager) to manage dependencies. To install all the necessary packages and libraries, run: 73 | 74 | ```bash 75 | npm install 76 | ``` 77 | 78 | This will read the `package.json` file and install all the dependencies specified. 79 | 80 | ### **Step 2: Start the Development Server** 81 | 82 | To see the project in action, you need to start the development server. Run the following command: 83 | 84 | ```bash 85 | npm run dev 86 | ``` 87 | 88 | This will launch the project in your default web browser (usually at `http://localhost:5173/` since we are using Vite). 89 | 90 | --- 91 | 92 | ## **4. Creating Your Own Component** 93 | 94 | ### **Step 1: Create a Folder for Your Component** 95 | 96 | Inside the `src/components` folder, create a new folder using your name(use a unique name or your github username) as the folder name. This will help us identify your component and give you credit. For example, if your github username is `johndoe`, create a folder called `johndoe`. 97 | 98 | ```bash 99 | src/components/johndoe/ 100 | ``` 101 | 102 | ### **Step 2: Create the Component File** 103 | 104 | Inside your folder, create a new file for your component, named something descriptive. For example, if you want to contribute a `Button` component, create a file called `Button.jsx`. 105 | 106 | ```bash 107 | src/components/johndoe/Button.jsx 108 | ``` 109 | 110 | In this file, create your React component as you normally would. Here's an example `Button.jsx`: 111 | 112 | ```javascript 113 | // Create a simple button component 114 | export default function Button() { 115 | return ; 116 | } 117 | ``` 118 | Don't forget to use Button.module.css and styles.classname approach. This is important because we want to keep the design consistent. 119 | 120 | ### **Step 3: Add Your Credit** 121 | 122 | At the bottom of your component file, add the author component with your name and GitHub link. This is important so everyone knows who contributed the component. A component name Author is alreay created for you all you have to do is do this: 123 | 124 | Example: 125 | 126 | ```javascript 127 | // Add this component with your name and github link. Place this component at the very end. 128 | 129 | ``` 130 | 131 | This ensures you get credit for your work! 132 | 133 | ### **Step 4: Style Your Component (Optional)** 134 | 135 | If your component requires custom styling, you can create a separate CSS file or use inline styles. 136 | 137 | For example, if you want to add styles for the button: 138 | 139 | 1. Create a new CSS file inside your component folder: 140 | 141 | ```bash 142 | src/components/jane-doe/Button.module.css 143 | ``` 144 | 145 | 2. Add the following CSS code in `Button.module.css`: 146 | 147 | ```css 148 | .btn { 149 | padding: var(--spacing-sm) var(--spacing-md); 150 | border: none; 151 | border-radius: var(--border-radius-md); 152 | cursor: pointer; 153 | background-color: var(--primary-color); 154 | } 155 | 156 | ``` 157 | 158 | 3. Then, import the CSS file into your `Button.jsx` file: 159 | 160 | ```javascript 161 | import styles from './Button.module.css'; 162 | ``` 163 | 164 | Don't forget to use our global root varibales for consistent styling across the site. We have all the roots variables in Index.css file. 165 | 166 | ## **5. Testing Your Component** 167 | 168 | ### **Step 1: Test the Component Locally** 169 | 170 | Before submitting your component, you should test it to make sure it works. Open the main `App.jsx` file (located in `src/App.jsx`) and import your component. 171 | 172 | For example: 173 | 174 | ```javascript 175 | import React from 'react'; 176 | import Button from './components/johndoe/Button'; // Adjust path to your component 177 | import Details from './components/kelixirr/Details'; 178 | import Hero from './Hero' 179 | 180 | function App() { 181 | return ( 182 | <> 183 | 184 |
185 | {/* Place your component after this for example Button below, and so on. One after another */} 186 | 187 | 188 | ); 189 | } 190 | 191 | export default App 192 | ``` 193 | 194 | Run `npm run dev` to ensure your component is correctly rendered on the page. If it is already running do check for consistent output. 195 | 196 | ### **Step 2: Check for Errors** 197 | 198 | Ensure that there are no console errors in your browser’s developer tools. If there are any errors, fix them before proceeding. 199 | 200 | ## **6. Commit Your Changes** 201 | 202 | Once you're happy with your component, commit your changes to your local Git repository. 203 | 204 | ### **Step 1: Stage Your Changes** 205 | 206 | In your terminal, run the following command to stage all the changes you made: 207 | 208 | ```bash 209 | git add . 210 | ``` 211 | 212 | ### **Step 2: Commit Your Changes** 213 | 214 | Now, commit your changes with a meaningful message: 215 | 216 | ```bash 217 | git commit -m "Added Button component by Jane Doe" 218 | ``` 219 | 220 | ### **Step 3: Push Changes to Your Fork** 221 | 222 | Push your changes to your forked repository: 223 | 224 | ```bash 225 | git push origin main 226 | ``` 227 | 228 | ## **7. Create a Pull Request** 229 | 230 | Now that your changes are pushed to your forked repository, you need to create a pull request to contribute your component to the main project. 231 | 232 | ### **Step 1: Go to the Original Repository** 233 | 234 | Visit the original repository (not your forked version) on GitHub. 235 | 236 | ### **Step 2: Create a Pull Request** 237 | 238 | Click the **New Pull Request** button. 239 | 240 | - In the **Compare** section, make sure you are comparing your branch (usually `main`) with the original `main` branch of the repository. 241 | - Write a title and description for your pull request explaining what component you added and how it works. 242 | 243 | Example: 244 | ``` 245 | Title: Added Button component by John Doe 246 | 247 | Description: This pull request adds a simple button component to the collection. It includes styling for the button etc.. The component is created by John Doe (GitHub: https://github.com/your username). 248 | ``` 249 | 250 | ### **Step 3: Submit the Pull Request** 251 | 252 | Click the **Create Pull Request** button to submit your changes. 253 | 254 | ## **8. Review and Merge** 255 | 256 | Once you submit your pull request, project maintainers will review it. If everything looks good, they will merge it into the main project. 257 | 258 | 259 | ## **9. Congratulations! 🎉** 260 | 261 | You've successfully contributed to the project! Thank you for your time and effort. 262 | 263 | ## **10. Helpful Links** 264 | 265 | - [GitHub Documentation](https://docs.github.com/en/github) 266 | - [React Documentation](https://reactjs.org/docs/getting-started.html) 267 | - [Node.js Documentation](https://nodejs.org/en/docs/) 268 | 269 | --- 270 | 271 | Feel free to reach out if you have any questions or need assistance during the process! 272 | 273 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import react from 'eslint-plugin-react' 4 | import reactHooks from 'eslint-plugin-react-hooks' 5 | import reactRefresh from 'eslint-plugin-react-refresh' 6 | 7 | export default [ 8 | { ignores: ['dist'] }, 9 | { 10 | files: ['**/*.{js,jsx}'], 11 | languageOptions: { 12 | ecmaVersion: 2020, 13 | globals: globals.browser, 14 | parserOptions: { 15 | ecmaVersion: 'latest', 16 | ecmaFeatures: { jsx: true }, 17 | sourceType: 'module', 18 | }, 19 | }, 20 | settings: { react: { version: '18.3' } }, 21 | plugins: { 22 | react, 23 | 'react-hooks': reactHooks, 24 | 'react-refresh': reactRefresh, 25 | }, 26 | rules: { 27 | ...js.configs.recommended.rules, 28 | ...react.configs.recommended.rules, 29 | ...react.configs['jsx-runtime'].rules, 30 | ...reactHooks.configs.recommended.rules, 31 | 'react/jsx-no-target-blank': 'off', 32 | 'react-refresh/only-export-components': [ 33 | 'warn', 34 | { allowConstantExport: true }, 35 | ], 36 | }, 37 | }, 38 | ] 39 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ReactDevs - A playground for react learners 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-react-component", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "react": "^18.3.1", 14 | "react-dom": "^18.3.1", 15 | "react-icons": "^5.4.0" 16 | }, 17 | "devDependencies": { 18 | "@eslint/js": "^9.17.0", 19 | "@types/react": "^18.3.18", 20 | "@types/react-dom": "^18.3.5", 21 | "@vitejs/plugin-react": "^4.3.4", 22 | "eslint": "^9.17.0", 23 | "eslint-plugin-react": "^7.37.2", 24 | "eslint-plugin-react-hooks": "^5.0.0", 25 | "eslint-plugin-react-refresh": "^0.4.16", 26 | "globals": "^15.14.0", 27 | "vite": "^6.0.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /public/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import Hero from "./Hero"; 3 | import Details from "./components/kelixirr/Details"; 4 | import Toast from "./components/VictorEZCodes/Toast"; 5 | import ProgressBar from "./components/VictorEZCodes/ProgressBar"; 6 | import ThemeSwitcher from "./components/VictorEZCodes/ThemeSwitcher"; 7 | import SearchFilter from "./components/VictorEZCodes/SearchFilter"; 8 | import FormValidator from "./components/VictorEZCodes/FormValidator"; 9 | import AccordionItems from "./components/kelixirr/AccordionItems"; 10 | import FlashCards from "./components/mektefaie/FlashCards"; 11 | import SliderCards from "./components/kelixirr/SliderCards"; 12 | import Modal from "./components/sushantpokhrel/Modal"; 13 | import Header from "./components/kelixirr/Header"; 14 | import Login from "./components/rrusyaidii/Login"; 15 | 16 | function App() { 17 | const [showToast, setShowToast] = useState(false); 18 | const [progress] = useState(0); 19 | 20 | return ( 21 | <> 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 35 | {/* Please Add Your Component Above This Line. Don't Add Div inside App, just component. Keep It Clean*/} 36 |
42 |

Toast Notifications Demo

43 | 49 | {showToast && ( 50 | setShowToast(false)} 54 | /> 55 | )} 56 |
57 | 58 | ); 59 | } 60 | 61 | export default App; 62 | -------------------------------------------------------------------------------- /src/Author.jsx: -------------------------------------------------------------------------------- 1 | import { FaGithub } from 'react-icons/fa' 2 | 3 | export default function Author({ name, githubLink }) { 4 | return ( 5 | 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /src/Hero.jsx: -------------------------------------------------------------------------------- 1 | import styles from "./Hero.module.css"; 2 | import { FaGithub, FaStar, FaQuestionCircle } from "react-icons/fa"; 3 | 4 | export default function Hero() { 5 | return ( 6 |
7 |
8 | 32 |
33 |
34 |

🌟 Welcome to the ReactDevs Project! 🌟

35 |

36 | A community-driven React project where beginners can contribute their 37 | own components and showcase their skills! This project will help you 38 | understand how to collaborate in an open source project, use git and 39 | github, and help you gain a solid understanding of React. If you are a 40 | beginner, click on contribute now button to get started. 41 |

42 | 52 |
53 |
54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /src/Hero.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | top: 0; 3 | width: 100%; 4 | z-index: 50; 5 | padding: var(--spacing-md) var(--spacing-md); 6 | border-bottom: 1px solid var(--border-color); 7 | } 8 | 9 | .nav { 10 | margin: 0 auto; 11 | display: flex; 12 | justify-content: space-between; 13 | align-items: center; 14 | } 15 | 16 | .logo { 17 | display: flex; 18 | align-items: center; 19 | gap: 0.8rem; 20 | font-weight: 600; 21 | font-size: 2.4rem; 22 | } 23 | 24 | .logo img { 25 | animation: rotateImage 5s linear infinite; 26 | } 27 | 28 | @keyframes rotateImage { 29 | from { 30 | transform: rotate(0deg); 31 | } 32 | to { 33 | transform: rotate(360deg); 34 | } 35 | } 36 | 37 | .navLinks { 38 | display: flex; 39 | gap: 2rem; 40 | } 41 | 42 | .navLinks a { 43 | text-decoration: none; 44 | color: var(--text-color-dark); 45 | transition: color var(--transition-base, 0.3s ease); 46 | font-size: 2rem; 47 | } 48 | 49 | .navLinks a:hover { 50 | color: var(--primary-color-hover); 51 | } 52 | 53 | .hero { 54 | color: var(--text-color-dark); 55 | padding: var(--spacing-lg) var(--spacing-md); 56 | text-align: center; 57 | margin: var(--spacing-md) auto; 58 | min-height: 85dvh; 59 | display: flex; 60 | flex-direction: column; 61 | justify-content: center; 62 | align-items: center; 63 | } 64 | 65 | .hero h1 { 66 | font-size: var(--font-size-heading-hero); 67 | margin-bottom: var(--spacing-md); 68 | } 69 | 70 | .hero p { 71 | font-size: var(--font-size-subheading); 72 | margin-bottom: var(--spacing-xl); 73 | max-width: 800px; 74 | } 75 | 76 | @media(max-width: 48rem) { 77 | .hero h1 { 78 | font-size: var(--font-size-heading-lg); 79 | } 80 | 81 | .hero p { 82 | font-size: var(--font-size-base); 83 | } 84 | } 85 | 86 | .hero-buttons { 87 | display: flex; 88 | justify-content: center; 89 | gap: var(--spacing-sm); 90 | } 91 | 92 | 93 | .contribute-button { 94 | background-color: var(--primary-color); 95 | color: var(--background-color); 96 | padding: var(--spacing-sm, 1.2rem) var(--spacing-md, 2rem); 97 | border: none; 98 | border-radius: var(--border-radius-sm, 0.4rem); 99 | font-size: var(--font-size-base, 1.1rem); 100 | cursor: pointer; 101 | text-decoration: none; 102 | text-align: center; 103 | display: inline-flex; 104 | align-items: center; 105 | gap: 0.5rem; 106 | transition: background-color var(--transition-base, 0.3s ease); 107 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/FormValidator.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import styles from "./FormValidator.module.css"; 3 | import { FaEye, FaEyeSlash } from "react-icons/fa"; 4 | import Author from "../../Author"; 5 | 6 | export default function FormValidator() { 7 | const [formData, setFormData] = useState({ 8 | username: "", 9 | email: "", 10 | password: "", 11 | confirmPassword: "" 12 | }); 13 | const [showPassword, setShowPassword] = useState(false); 14 | const [errors, setErrors] = useState({}); 15 | const [touched, setTouched] = useState({}); 16 | 17 | const PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d).{8,}$/; 18 | 19 | const validateField = (name, value) => { 20 | switch (name) { 21 | case "username": 22 | return value.length < 3 ? "Username must be at least 3 characters" : ""; 23 | case "email": 24 | return !/\S+@\S+\.\S+/.test(value) ? "Invalid email address" : ""; 25 | case "password": 26 | return !PASSWORD_REGEX.test(value) 27 | ? "Password must be 8+ characters with at least one letter and one number" 28 | : ""; 29 | case "confirmPassword": 30 | return value !== formData.password ? "Passwords do not match" : ""; 31 | default: 32 | return ""; 33 | } 34 | }; 35 | 36 | const handleChange = (e) => { 37 | const { name, value } = e.target; 38 | setFormData(prev => ({ ...prev, [name]: value })); 39 | setErrors(prev => ({ ...prev, [name]: validateField(name, value) })); 40 | }; 41 | 42 | const handleBlur = (e) => { 43 | const { name } = e.target; 44 | setTouched(prev => ({ ...prev, [name]: true })); 45 | }; 46 | 47 | const handleSubmit = (e) => { 48 | e.preventDefault(); 49 | const newErrors = {}; 50 | Object.keys(formData).forEach(key => { 51 | newErrors[key] = validateField(key, formData[key]); 52 | }); 53 | setErrors(newErrors); 54 | setTouched(Object.keys(formData).reduce((acc, key) => ({ ...acc, [key]: true }), {})); 55 | 56 | if (Object.values(newErrors).every(error => !error)) { 57 | alert("Form submitted successfully!"); 58 | } 59 | }; 60 | 61 | return ( 62 |
63 |

Form Validator

64 |

65 | Real-time form validation with detailed feedback 66 |

67 | 68 |
69 |
70 | 71 | 79 | {touched.username && errors.username && ( 80 | {errors.username} 81 | )} 82 |
83 | 84 |
85 | 86 |
87 | 95 | 102 |
103 | {touched.password && errors.password && ( 104 | {errors.password} 105 | )} 106 |
107 | 108 | 111 |
112 | 113 | 114 |
115 | ); 116 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/FormValidator.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | padding: var(--spacing-lg); 5 | } 6 | 7 | .description { 8 | margin-bottom: var(--spacing-xl); 9 | text-align: center; 10 | color: var(--text-color); 11 | } 12 | 13 | .form { 14 | max-width: 500px; 15 | margin: 0 auto; 16 | padding: var(--spacing-xl); 17 | background: var(--background-color); 18 | border: 1px solid var(--border-color); 19 | border-radius: var(--border-radius-lg); 20 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 21 | } 22 | 23 | .formGroup { 24 | margin-bottom: var(--spacing-lg); 25 | } 26 | 27 | .formGroup label { 28 | display: block; 29 | margin-bottom: var(--spacing-sm); 30 | color: var(--text-color); 31 | font-weight: 500; 32 | } 33 | 34 | .formGroup input { 35 | width: 100%; 36 | padding: var(--spacing-md); 37 | border: 2px solid var(--border-color); 38 | border-radius: var(--border-radius-md); 39 | font-size: var(--font-size-base); 40 | transition: border-color var(--transition-base); 41 | } 42 | 43 | .formGroup input.error { 44 | border-color: #f44336; 45 | } 46 | 47 | .formGroup input.valid { 48 | border-color: #4caf50; 49 | } 50 | 51 | .errorMessage { 52 | color: #f44336; 53 | font-size: var(--font-size-sm); 54 | margin-top: var(--spacing-xs); 55 | display: block; 56 | } 57 | 58 | .passwordInput { 59 | position: relative; 60 | } 61 | 62 | .togglePassword { 63 | position: absolute; 64 | right: var(--spacing-md); 65 | top: 50%; 66 | transform: translateY(-50%); 67 | background: none; 68 | border: none; 69 | color: var(--text-color); 70 | cursor: pointer; 71 | padding: var(--spacing-xs); 72 | } 73 | 74 | .submitButton { 75 | width: 100%; 76 | padding: var(--spacing-md); 77 | background: var(--primary-color); 78 | color: white; 79 | border: none; 80 | border-radius: var(--border-radius-md); 81 | font-size: var(--font-size-base); 82 | cursor: pointer; 83 | transition: transform var(--transition-base); 84 | } 85 | 86 | .submitButton:hover { 87 | transform: translateY(-2px); 88 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 89 | } 90 | 91 | .strengthIndicator { 92 | display: flex; 93 | gap: var(--spacing-xs); 94 | margin-top: var(--spacing-sm); 95 | } 96 | 97 | .strengthBar { 98 | height: 4px; 99 | flex: 1; 100 | background: var(--border-color); 101 | border-radius: var(--border-radius-sm); 102 | } 103 | 104 | .strengthBar.weak { background: #f44336; } 105 | .strengthBar.medium { background: #ff9800; } 106 | .strengthBar.strong { background: #4caf50; } 107 | 108 | @media (max-width: 48rem) { 109 | .form { 110 | padding: var(--spacing-md); 111 | } 112 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/ProgressBar.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import styles from "./ProgressBar.module.css"; 3 | import { FaChartLine } from "react-icons/fa"; 4 | import Author from "../../Author"; 5 | 6 | export default function ProgressBar() { 7 | const [progress, setProgress] = useState(0); 8 | 9 | const handleProgress = (amount) => { 10 | setProgress(prev => { 11 | const newValue = prev + amount; 12 | return Math.min(100, Math.max(0, newValue)); 13 | }); 14 | }; 15 | 16 | const getProgressMessage = () => { 17 | if (progress === 100) return "Complete!"; 18 | if (progress >= 75) return "Almost there!"; 19 | if (progress >= 50) return "Halfway there!"; 20 | if (progress > 0) return "Keep going!"; 21 | return "Let's start!"; 22 | }; 23 | 24 | return ( 25 | <> 26 |
27 |

Progress Bar Component

28 |

29 | An interactive progress bar with animations and status messages. 30 | Use the buttons below to control the progress: 31 |

32 | 33 |
34 |
35 |
39 | 40 | {progress}% 41 | 42 |
43 |
44 | 45 |

46 | 47 | {getProgressMessage()} 48 |

49 | 50 |
51 | 58 | 65 | 72 |
73 |
74 | 75 | 76 |
77 | 78 | ); 79 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/ProgressBar.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | line-height: var(--line-height-base); 5 | } 6 | 7 | .section h2 { 8 | font-size: var(--font-size-heading-lg); 9 | text-align: center; 10 | margin-bottom: var(--spacing-xl-2); 11 | } 12 | 13 | .section p { 14 | font-size: var(--font-size-base); 15 | color: var(--text-color); 16 | text-align: center; 17 | } 18 | 19 | .progressContainer { 20 | border-radius: var(--border-radius-md); 21 | padding: var(--spacing-md); 22 | border: 1px solid var(--border-color); 23 | margin: var(--spacing-xl) 0; 24 | } 25 | 26 | .progressBar { 27 | width: 100%; 28 | height: 2rem; 29 | background-color: var(--border-color); 30 | border-radius: var(--border-radius-sm); 31 | overflow: hidden; 32 | } 33 | 34 | .progressFill { 35 | height: 100%; 36 | background-color: var(--primary-color); 37 | transition: width var(--transition-base); 38 | display: flex; 39 | align-items: center; 40 | justify-content: center; 41 | } 42 | 43 | .progressText { 44 | color: white; 45 | font-weight: bold; 46 | font-size: var(--font-size-base); 47 | } 48 | 49 | .progressMessage { 50 | display: flex; 51 | align-items: center; 52 | justify-content: center; 53 | gap: var(--spacing-sm); 54 | margin: var(--spacing-md) 0; 55 | color: var(--text-color); 56 | } 57 | 58 | .progressIcon { 59 | color: var(--primary-color); 60 | } 61 | 62 | .buttonContainer { 63 | display: flex; 64 | gap: var(--spacing-md); 65 | justify-content: center; 66 | margin-top: var(--spacing-md); 67 | } 68 | 69 | .progressButton { 70 | padding: var(--spacing-sm) var(--spacing-lg); 71 | border: none; 72 | border-radius: var(--border-radius-sm); 73 | background-color: var(--primary-color); 74 | color: white; 75 | cursor: pointer; 76 | transition: transform var(--transition-base); 77 | } 78 | 79 | .progressButton:hover:not(:disabled) { 80 | transform: translateY(-2px); 81 | } 82 | 83 | .progressButton:disabled { 84 | opacity: 0.5; 85 | cursor: not-allowed; 86 | } 87 | 88 | @media (max-width: 48rem) { 89 | .buttonContainer { 90 | flex-direction: column; 91 | align-items: center; 92 | } 93 | 94 | .section { 95 | padding: var(--spacing-lg); 96 | } 97 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/SearchFilter.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useMemo } from "react"; 2 | import styles from "./SearchFilter.module.css"; 3 | import { FaSearch } from "react-icons/fa"; 4 | import Author from "../../Author"; 5 | 6 | export default function SearchFilter() { 7 | const [searchTerm, setSearchTerm] = useState(""); 8 | const [category, setCategory] = useState("all"); 9 | const [sortBy, setSortBy] = useState("name"); 10 | 11 | const items = [ 12 | { id: 1, name: "React Basics", category: "frontend", difficulty: "beginner" }, 13 | { id: 2, name: "Node.js API", category: "backend", difficulty: "intermediate" }, 14 | { id: 3, name: "CSS Animation", category: "frontend", difficulty: "beginner" }, 15 | { id: 4, name: "Database Design", category: "backend", difficulty: "advanced" }, 16 | ]; 17 | 18 | const filteredItems = useMemo(() => { 19 | return items 20 | .filter(item => 21 | item.name.toLowerCase().includes(searchTerm.toLowerCase()) && 22 | (category === "all" || item.category === category) 23 | ) 24 | .sort((a, b) => { 25 | if (sortBy === "name") return a.name.localeCompare(b.name); 26 | return a.difficulty.localeCompare(b.difficulty); 27 | }); 28 | }, [searchTerm, category, sortBy]); 29 | 30 | return ( 31 |
32 |

Search and Filter Component

33 |

Search, filter, and sort items with real-time updates

34 | 35 |
36 |
37 | 38 | setSearchTerm(e.target.value)} 43 | /> 44 |
45 | 46 |
47 | 55 | 56 | 63 |
64 |
65 | 66 |
67 | {filteredItems.map(item => ( 68 |
69 |

{item.name}

70 | {item.category} 71 | {item.difficulty} 72 |
73 | ))} 74 |
75 | 76 | 77 |
78 | ); 79 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/SearchFilter.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | padding: var(--spacing-lg); 5 | } 6 | 7 | .controls { 8 | margin-bottom: var(--spacing-xl); 9 | } 10 | 11 | .searchBox { 12 | position: relative; 13 | margin-bottom: var(--spacing-lg); 14 | } 15 | 16 | .searchBox input { 17 | width: 100%; 18 | padding: var(--spacing-md) var(--spacing-xl); 19 | padding-left: calc(var(--spacing-xl) * 2); 20 | border: 2px solid var(--border-color); 21 | border-radius: var(--border-radius-md); 22 | font-size: var(--font-size-base); 23 | } 24 | 25 | .searchIcon { 26 | position: absolute; 27 | left: var(--spacing-lg); 28 | top: 50%; 29 | transform: translateY(-50%); 30 | color: var(--text-color); 31 | opacity: 0.5; 32 | } 33 | 34 | .filters { 35 | display: flex; 36 | gap: var(--spacing-md); 37 | justify-content: center; 38 | } 39 | 40 | .filters select { 41 | padding: var(--spacing-sm) var(--spacing-lg); 42 | border: 2px solid var(--border-color); 43 | border-radius: var(--border-radius-md); 44 | background: var(--background-color); 45 | color: var(--text-color); 46 | cursor: pointer; 47 | } 48 | 49 | .results { 50 | display: grid; 51 | grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); 52 | gap: var(--spacing-lg); 53 | padding: var(--spacing-lg) 0; 54 | } 55 | 56 | .item { 57 | background: var(--background-color); 58 | border: 1px solid var(--border-color); 59 | border-radius: var(--border-radius-md); 60 | padding: var(--spacing-lg); 61 | transition: transform var(--transition-base); 62 | } 63 | 64 | .item:hover { 65 | transform: translateY(-2px); 66 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 67 | } 68 | 69 | .item h3 { 70 | margin-bottom: var(--spacing-md); 71 | color: var(--text-color); 72 | } 73 | 74 | .badge { 75 | display: inline-block; 76 | padding: var(--spacing-xs) var(--spacing-sm); 77 | background: var(--primary-color); 78 | color: white; 79 | border-radius: var(--border-radius-sm); 80 | font-size: var(--font-size-sm); 81 | margin-right: var(--spacing-sm); 82 | } 83 | 84 | @media (max-width: 48rem) { 85 | .filters { 86 | flex-direction: column; 87 | } 88 | 89 | .filters select { 90 | width: 100%; 91 | } 92 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/ThemeSwitcher.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import styles from "./ThemeSwitcher.module.css"; 3 | import { FaSun, FaMoon, FaDesktop } from "react-icons/fa"; 4 | import Author from "../../Author"; 5 | 6 | export default function ThemeSwitcher() { 7 | const [theme, setTheme] = useState('system'); 8 | 9 | const getSystemTheme = () => { 10 | return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 11 | }; 12 | 13 | const getCurrentTheme = () => { 14 | return theme === 'system' ? getSystemTheme() : theme; 15 | }; 16 | 17 | return ( 18 |
19 |

Theme Switcher

20 |

21 | Switch between light, dark, and system theme preferences 22 |

23 | 24 |
25 | 31 | 37 | 43 |
44 | 45 |
46 |

Theme Preview

47 |
48 |

Sample Card

49 |

This card will update based on the selected theme.

50 | 51 |
52 |
53 | 54 | 55 |
56 | ); 57 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/ThemeSwitcher.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | padding: var(--spacing-lg); 5 | } 6 | 7 | .section h2 { 8 | font-size: var(--font-size-heading-lg); 9 | text-align: center; 10 | margin-bottom: var(--spacing-xl-2); 11 | } 12 | 13 | .description { 14 | text-align: center; 15 | color: var(--text-color); 16 | margin-bottom: var(--spacing-xl); 17 | } 18 | 19 | .themeContainer { 20 | display: flex; 21 | gap: var(--spacing-md); 22 | justify-content: center; 23 | margin-bottom: var(--spacing-xl); 24 | } 25 | 26 | .themeButton { 27 | display: flex; 28 | align-items: center; 29 | gap: var(--spacing-sm); 30 | padding: var(--spacing-md) var(--spacing-lg); 31 | border: 2px solid var(--border-color); 32 | border-radius: var(--border-radius-md); 33 | background: var(--background-color); 34 | color: var(--text-color); 35 | cursor: pointer; 36 | transition: all var(--transition-base); 37 | } 38 | 39 | .themeButton:hover { 40 | transform: translateY(-2px); 41 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 42 | } 43 | 44 | .themeButton.active { 45 | background: var(--primary-color); 46 | color: white; 47 | border-color: var(--primary-color); 48 | } 49 | 50 | .preview { 51 | max-width: 600px; 52 | margin: 0 auto; 53 | } 54 | 55 | .preview h3 { 56 | text-align: center; 57 | margin-bottom: var(--spacing-lg); 58 | color: var(--text-color); 59 | } 60 | 61 | .card { 62 | border-radius: var(--border-radius-lg); 63 | padding: var(--spacing-xl); 64 | margin-top: var(--spacing-lg); 65 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 66 | transition: all var(--transition-base); 67 | } 68 | 69 | .card.light { 70 | background-color: #ffffff; 71 | border: 1px solid #e0e0e0; 72 | } 73 | 74 | .card.light h4 { 75 | color: #333333; 76 | margin-bottom: var(--spacing-md); 77 | } 78 | 79 | .card.light p { 80 | color: #666666; 81 | margin-bottom: var(--spacing-lg); 82 | } 83 | 84 | .card.light .previewButton { 85 | background-color: #2196F3; 86 | color: white; 87 | } 88 | 89 | .card.dark { 90 | background-color: #1a1a1a; 91 | border: 1px solid #333333; 92 | } 93 | 94 | .card.dark h4 { 95 | color: #ffffff; 96 | margin-bottom: var(--spacing-md); 97 | } 98 | 99 | .card.dark p { 100 | color: #cccccc; 101 | margin-bottom: var(--spacing-lg); 102 | } 103 | 104 | .card.dark .previewButton { 105 | background-color: #4CAF50; 106 | color: white; 107 | } 108 | 109 | .previewButton { 110 | padding: var(--spacing-sm) var(--spacing-lg); 111 | border: none; 112 | border-radius: var(--border-radius-sm); 113 | cursor: pointer; 114 | transition: transform var(--transition-base); 115 | font-size: var(--font-size-base); 116 | } 117 | 118 | .previewButton:hover { 119 | transform: translateY(-2px); 120 | opacity: 0.9; 121 | } 122 | 123 | .card.system { 124 | background-color: var(--background-color); 125 | border: 1px solid var(--border-color); 126 | } 127 | 128 | .card.system h4 { 129 | color: var(--text-color); 130 | margin-bottom: var(--spacing-md); 131 | } 132 | 133 | .card.system p { 134 | color: var(--text-color); 135 | margin-bottom: var(--spacing-lg); 136 | } 137 | 138 | .card.system .previewButton { 139 | background-color: var(--primary-color); 140 | color: white; 141 | } 142 | 143 | @media (max-width: 48rem) { 144 | .themeContainer { 145 | flex-direction: column; 146 | align-items: center; 147 | } 148 | 149 | .themeButton { 150 | width: 100%; 151 | justify-content: center; 152 | } 153 | 154 | .preview { 155 | padding: 0 var(--spacing-md); 156 | } 157 | 158 | .card { 159 | padding: var(--spacing-lg); 160 | } 161 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/Toast.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import styles from "./Toast.module.css"; 3 | import { FaBell } from "react-icons/fa"; 4 | import Author from "../../Author"; 5 | 6 | export default function Toast() { 7 | const [showToast, setShowToast] = useState(false); 8 | const [toastType, setToastType] = useState('success'); 9 | 10 | const showNotification = (type) => { 11 | setToastType(type); 12 | setShowToast(true); 13 | setTimeout(() => setShowToast(false), 3000); 14 | }; 15 | 16 | const getToastMessage = () => { 17 | switch(toastType) { 18 | case 'success': return 'Operation completed successfully!'; 19 | case 'error': return 'An error has occurred!'; 20 | case 'warning': return 'Warning: Please be careful!'; 21 | default: return 'Notification message'; 22 | } 23 | }; 24 | 25 | return ( 26 | <> 27 |
28 |

Toast Notification Component

29 |

30 | A reusable toast notification component with different types and animations. 31 | Click the buttons below to see different toast types: 32 |

33 | 34 |
35 | 41 | 42 | 48 | 49 | 55 |
56 | 57 | {showToast && ( 58 |
59 | 60 |

{getToastMessage()}

61 |
62 | )} 63 | 64 | 65 |
66 | 67 | ); 68 | } -------------------------------------------------------------------------------- /src/components/VictorEZCodes/Toast.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | line-height: var(--line-height-base); 5 | } 6 | 7 | .section h2 { 8 | font-size: var(--font-size-heading-lg); 9 | text-align: center; 10 | margin-bottom: var(--spacing-xl-2); 11 | } 12 | 13 | .section p { 14 | font-size: var(--font-size-base); 15 | color: var(--text-color); 16 | text-align: center; 17 | } 18 | 19 | .toastContainer { 20 | display: flex; 21 | gap: var(--spacing-md); 22 | justify-content: center; 23 | margin: var(--spacing-xl) 0; 24 | } 25 | 26 | .toastButton { 27 | padding: var(--spacing-sm) var(--spacing-lg); 28 | border: none; 29 | border-radius: var(--border-radius-sm); 30 | cursor: pointer; 31 | font-size: var(--font-size-base); 32 | transition: transform var(--transition-base); 33 | } 34 | 35 | .toastButton:hover { 36 | transform: translateY(-2px); 37 | } 38 | 39 | .toastButton.success { 40 | background-color: #4caf50; 41 | color: white; 42 | } 43 | 44 | .toastButton.error { 45 | background-color: #f44336; 46 | color: white; 47 | } 48 | 49 | .toastButton.warning { 50 | background-color: #ff9800; 51 | color: white; 52 | } 53 | 54 | .toast { 55 | position: fixed; 56 | top: 20px; 57 | right: 20px; 58 | padding: var(--spacing-md) var(--spacing-lg); 59 | border-radius: var(--border-radius-md); 60 | display: flex; 61 | align-items: center; 62 | gap: var(--spacing-sm); 63 | animation: slideIn var(--transition-base); 64 | z-index: 1000; 65 | } 66 | 67 | .toast.success { 68 | background-color: #4caf50; 69 | color: white; 70 | } 71 | 72 | .toast.error { 73 | background-color: #f44336; 74 | color: white; 75 | } 76 | 77 | .toast.warning { 78 | background-color: #ff9800; 79 | color: white; 80 | } 81 | 82 | .toastIcon { 83 | font-size: 1.2rem; 84 | } 85 | 86 | @keyframes slideIn { 87 | from { 88 | transform: translateX(100%); 89 | opacity: 0; 90 | } 91 | to { 92 | transform: translateX(0); 93 | opacity: 1; 94 | } 95 | } 96 | 97 | @media (max-width: 48rem) { 98 | .toastContainer { 99 | flex-direction: column; 100 | align-items: center; 101 | } 102 | 103 | .section { 104 | padding: var(--spacing-lg); 105 | } 106 | } -------------------------------------------------------------------------------- /src/components/kelixirr/AccordionItems.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { IoMdArrowDropdownCircle, IoMdArrowDropupCircle } from "react-icons/io"; 3 | import styles from "./../kelixirr/AccordionItems.module.css"; 4 | import { WiStars } from "react-icons/wi"; 5 | import Author from "../../Author"; 6 | 7 | export default function AccordionItems() { 8 | const accs = [ 9 | { 10 | id: 1, 11 | title: "Who can contribute?", 12 | content: 13 | "This project is open to anyone, regardless of experience. Whether you are just starting with React or have basic knowledge of front-end development, you can contribute. The goal is to create a collaborative learning environment where people of all skill levels can participate and grow.", 14 | }, 15 | { 16 | id: 2, 17 | title: "How do I contribute a component?", 18 | content: 19 | "To contribute a component, first, fork the repository and create a new branch for your changes. Then, you can start building the component of your choice. Once you've completed your component, ensure that it follows the project's guidelines, such as naming conventions and structure, and then submit a pull request. Don’t worry if you're unsure — there is a documentation to help you through each step.", 20 | }, 21 | { 22 | id: 3, 23 | title: "What kind of components can I contribute?", 24 | content: 25 | "You can contribute any React component that you feel comfortable building. It can be anything from a simple button, input form, or card to more complex components like modals, sliders, games, or navigation bars. Just make sure they follow our design guidelines", 26 | }, 27 | { 28 | id: 4, 29 | title: "Will my contributions be reviewed?", 30 | content: 31 | "Yes, all contributions will be reviewed by the maintainers of the project. They will check the code for correctness, ensure it meets the project's standards, and provide constructive feedback. If your contribution is accepted, it will be merged into the main codebase, and you’ll get credit for your work.", 32 | }, 33 | { 34 | id: 5, 35 | title: "Can I ask for help if I get stuck?", 36 | content: 37 | "Absolutely! This project is all about learning, so feel free to ask for help. You can open an issue in the repository", 38 | }, 39 | { 40 | id: 6, 41 | title: "How will this project help me improve my skills?", 42 | content: 43 | "Contributing to this project will help you practice key front-end skills like React, component-based architecture, and JavaScript. You'll also gain experience with version control (Git), collaboration tools, and code review processes. Plus, working on real-world projects is a great way to build your portfolio and showcase your skills to potential employers or collaborators.", 44 | }, 45 | { 46 | id: 7, 47 | title: "Will I receive credit for my contribution?", 48 | content: 49 | "Yes, all contributors will be credited for their work. Each accepted pull request will be attributed to you, and we will include your GitHub profile in the project’s contributor list. If you’re building components as part of your portfolio, this is a great way to demonstrate your involvement in an open-source project. Above all don't forget to add our Author component below your component so that people can know who created it.", 50 | }, 51 | ]; 52 | 53 | const initialState = accs.reduce((state, item) => { 54 | if (item.id === 1) { 55 | state[item.id] = true; 56 | } else { 57 | state[item.id] = false; 58 | } 59 | return state; 60 | }, {}); 61 | 62 | const [accstate, setAccState] = useState(initialState); 63 | 64 | const handleAcc = (id) => { 65 | setAccState((state) => ({ 66 | ...Object.fromEntries(Object.keys(state).map((key) => [key, false])), 67 | [id]: !state[id], 68 | })); 69 | }; 70 | 71 | return ( 72 | <> 73 |
74 |
75 |

76 | 77 | FAQs: In Case! 78 |

79 |
    80 | {accs.map((acc) => ( 81 |
  • handleAcc(acc.id)} 84 | className={`${styles.AccordionUlLi} ${ 85 | accstate[acc.id] ? styles.activeLi : "" 86 | }`} 87 | > 88 |
    89 |

    {acc.title}

    90 | {accstate[acc.id] ? ( 91 | 92 | ) : ( 93 | 94 | )} 95 |
    96 | {accstate[acc.id] &&

    {acc.content}

    } 97 |
  • 98 | ))} 99 |
100 |
101 |
102 | 103 | 104 | ); 105 | } 106 | -------------------------------------------------------------------------------- /src/components/kelixirr/AccordionItems.module.css: -------------------------------------------------------------------------------- 1 | .AccordionContainer { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | margin-bottom: var(--spacing-xl-2); 6 | } 7 | 8 | .AccordionH3 { 9 | font-size: var(--font-size-heading-hero); 10 | text-align: left; 11 | margin-left: var(--spacing-lg); 12 | color: var(--primary-color); 13 | margin-bottom: var(--spacing-xl-4); 14 | } 15 | 16 | .AccordionH3 svg { 17 | color: var(--primary-color-hover); 18 | } 19 | 20 | .Accordion { 21 | width: var(--max-width-container); 22 | padding: var(--spacing-xl); 23 | } 24 | 25 | .AccordionUl { 26 | margin: var(--spacing-xl) var(--spacing-xl); 27 | } 28 | 29 | .AccordionUlLi { 30 | list-style: none; 31 | margin-bottom: var(--spacing-xl); 32 | border-radius: var(--border-radius-md); 33 | border: 1px solid var(--border-color); 34 | padding: var(--spacing-lg); 35 | background-color: #f7fbff; 36 | transition: transform var(--transition-base); 37 | cursor: pointer; 38 | } 39 | 40 | .AccordionUlLi svg { 41 | color: var(--text-light-color); 42 | font-size: 3.2rem; 43 | flex-shrink: 0; 44 | width: 2.4rem; 45 | height: 2.4rem; 46 | min-width: 2.4rem; 47 | } 48 | 49 | .AccordionUlLi:hover { 50 | border-top: 2px solid var(--primary-color); 51 | background-color: #e9f4ff; 52 | transform: translateY(-5px); 53 | } 54 | 55 | .AccordionUlLiDiv { 56 | display: flex; 57 | justify-content: space-between; 58 | gap: 1.5rem; 59 | } 60 | 61 | .AccordionUlLiDiv h3 { 62 | margin-bottom: var(--spacing-md); 63 | font-size: var(--font-size-heading); 64 | color: var(--text-light-color); 65 | flex: 1; 66 | min-width: 0; 67 | } 68 | 69 | .activeLi { 70 | border-top: 2px solid var(--primary-color); 71 | } 72 | 73 | .activeLi, 74 | .activeLi h3, 75 | .activeLi svg { 76 | color: var(--primary-color); 77 | } 78 | 79 | .AccordionUlLi p { 80 | font-size: var(--font-size-base); 81 | line-height: var(--line-height-base); 82 | color: var(--text-color); 83 | } 84 | 85 | .AccordionUlLi p { 86 | width: 90%; 87 | font-size: 1.8rem; 88 | line-height: 1.8; 89 | color: #272727; 90 | } 91 | 92 | 93 | @media (max-width: 76.8rem) { 94 | .AccordionUlLi svg { 95 | width: 2rem; 96 | height: 2rem; 97 | min-width: 2rem; 98 | } 99 | 100 | .AccordionUlLiDiv h3 { 101 | font-size: 2rem; 102 | } 103 | 104 | .AccordionUl { 105 | margin: 0; 106 | } 107 | } 108 | 109 | @media (max-width: 45rem) { 110 | .AccordionUlLi svg { 111 | width: 1.6rem; 112 | height: 1.6rem; 113 | min-width: 1.6rem; 114 | } 115 | 116 | .AccordionUlLiDiv h3 { 117 | font-size: 1.8rem; 118 | } 119 | } -------------------------------------------------------------------------------- /src/components/kelixirr/Details.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import styles from "../kelixirr/Details.module.css"; 3 | import { FaCartShopping } from "react-icons/fa6"; 4 | import Author from "../../Author"; 5 | 6 | export default function Details() { 7 | const [count, setCount] = useState(0); 8 | 9 | const handleCount = type => { 10 | setCount(prev => { 11 | if (type === "increase" && prev < 20) { 12 | return prev + 1; 13 | } else if (type === "decrease" && prev > 0) { 14 | return prev - 1; 15 | } 16 | return prev; 17 | }); 18 | }; 19 | 20 | const getCartMessage = () => { 21 | if (count === 20) return `${count} - Maximum limit reached`; 22 | if (count > 0) return `${count} - items in your cart`; 23 | return `${count} - Your cart is empty`; 24 | }; 25 | 26 | return ( 27 | <> 28 |
29 |

An Example:

30 |

31 | Welcome to the ReactDevs project! This project allows 32 | contributors to add React components that are simple yet creative. 33 | It's a great way to practice, collaborate, and learn React in an 34 | open source environment. Here is an example: 35 |

36 | 37 |
38 | 46 | 47 |

48 | 49 | {getCartMessage()} 50 |

51 | 52 | 60 |
61 | 62 |

63 | Once you have created your component, add the Author component as 64 | shown above to get the credit. Here is the example code: 65 |

66 |
 67 |           
 68 |             {`import { useState } from "react";
 69 | import styles from "../your_username/Cart.module.css";
 70 | import { FaCartShopping } from "react-icons/fa6";
 71 | import { FiMinus, FiPlus } from "react-icons/fi";
 72 | import Author from "../../Author";
 73 | 
 74 | export default function Cart() {
 75 |   const [count, setCount] = useState(0);
 76 | 
 77 |   const handleCount = (type) => {
 78 |     setCount((prev) => {
 79 |       if (type === "increase" && prev < 20) {
 80 |         return prev + 1;
 81 |       } else if (type === "decrease" && prev > 0) {
 82 |         return prev - 1;
 83 |       }
 84 |       return prev;
 85 |     });
 86 |   };
 87 | 
 88 |   return (
 89 |     <>
 90 |       
91 | 98 |

99 | 100 | {count === 20 101 | ? \`\${count} - Maximum limit reached\` 102 | : count > 0 103 | ? \`\${count} - items in your cart\` 104 | : \`\${count} - Your cart is empty\`} 105 |

106 | 113 |
114 | 115 | 116 | ); 117 | }`} 118 |
119 |
120 |

121 | Good Luck! We can' wait to see you being part of this project!{" "} 122 | 132 | Start Now! 133 | 134 |

135 |
136 | 137 | ); 138 | } 139 | -------------------------------------------------------------------------------- /src/components/kelixirr/Details.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | line-height: var(--line-height-base); 5 | } 6 | 7 | .section h2 { 8 | font-size: var(--font-size-heading-lg); 9 | text-align: center; 10 | margin-bottom: var(--spacing-xl-2); 11 | } 12 | 13 | .section p { 14 | font-size: var(--font-size-base); 15 | color: var(--text-color); 16 | } 17 | 18 | @media(max-width: 48rem){ 19 | .section p { 20 | text-align: center; 21 | } 22 | } 23 | 24 | .cartContainer { 25 | border-radius: var(--border-radius-md); 26 | padding: var(--spacing-md); 27 | border: 1px solid var(--border-color); 28 | margin: var(--spacing-xl) 0; 29 | display: flex; 30 | align-items: center; 31 | gap: var(--spacing-md); 32 | justify-content: center; 33 | } 34 | 35 | .cartButton { 36 | width: 2.625rem; 37 | height: 2.625rem; 38 | border: none; 39 | font-size: var(--font-size-base); 40 | cursor: pointer; 41 | display: flex; 42 | align-items: center; 43 | justify-content: center; 44 | } 45 | 46 | .cartButton:hover:not(:disabled) { 47 | transform: translateY(-0.125rem); 48 | } 49 | 50 | .cartButton:disabled { 51 | opacity: 0.5; 52 | cursor: not-allowed; 53 | } 54 | 55 | .cartInfo { 56 | display: flex; 57 | align-items: center; 58 | gap: var(--spacing-sm); 59 | font-size: var(--font-size-base); 60 | color: var(--text-color); 61 | } 62 | 63 | .cartIcon { 64 | color: var(--primary-color); 65 | } 66 | 67 | 68 | .codeBlock { 69 | background: var(--text-color); 70 | border-radius: var(--border-radius-sm); 71 | padding: var(--spacing-md); 72 | margin: var(--spacing-md) 0; 73 | overflow-x: auto; 74 | max-height: 400px; 75 | } 76 | 77 | .codeBlock code { 78 | color: var(--background-color); 79 | font-family: monospace; 80 | font-size: calc(var(--font-size-base) * 0.575); 81 | display: block; 82 | white-space: pre; 83 | } 84 | 85 | 86 | @keyframes fadeIn { 87 | from { 88 | opacity: 0; 89 | transform: translateY(0.625rem); 90 | } 91 | 92 | to { 93 | opacity: 1; 94 | transform: translateY(0); 95 | } 96 | } 97 | 98 | .section { 99 | animation: fadeIn var(--transition-base); 100 | } 101 | 102 | 103 | @media (max-width: 48rem) { 104 | .section { 105 | padding: var(--spacing-lg); 106 | } 107 | } -------------------------------------------------------------------------------- /src/components/kelixirr/Header.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from "react"; 2 | import styles from "../kelixirr/Header.module.css"; 3 | import Author from "../../Author"; 4 | import PopUpModal from "./PopUpModal"; 5 | 6 | export default function Header() { 7 | const [submenus, setSubmenus] = useState({}); 8 | const menuRefs = useRef({}); 9 | const mobileMenuRef = useRef(null); 10 | 11 | const [mobile, setMobile] = useState(false); 12 | const [mobileOpen, setMobileOpen] = useState(false); 13 | 14 | // for preventing overfiring of events like resize 15 | function debounce(func, delay) { 16 | let timeout; 17 | return (...args) => { 18 | clearTimeout(timeout); 19 | timeout = setTimeout(() => func(...args), delay); 20 | }; 21 | } 22 | 23 | // closing the mobile menu 24 | useEffect(() => { 25 | const closeMobileMenu = (e) => { 26 | if ( 27 | mobileOpen && 28 | mobileMenuRef.current && 29 | !mobileMenuRef.current?.contains(e.target) 30 | ) { 31 | setMobileOpen(false); 32 | } 33 | }; 34 | 35 | document.addEventListener("click", closeMobileMenu); 36 | return () => document.removeEventListener("click", closeMobileMenu); 37 | }, [mobileOpen]); 38 | 39 | // Showing the mobile menu 40 | useEffect(() => { 41 | const debouncedUpdateMobileView = debounce(() => { 42 | if (window.innerWidth <= 768) { 43 | setMobile(true); 44 | } else { 45 | setMobile(false); 46 | } 47 | }, 200); 48 | 49 | debouncedUpdateMobileView(); 50 | 51 | window.addEventListener("resize", debouncedUpdateMobileView); 52 | 53 | return () => { 54 | window.removeEventListener("resize", debouncedUpdateMobileView); 55 | }; 56 | }, []); 57 | 58 | // chaning menu state 59 | const handleClick = (menuKey) => { 60 | setSubmenus((prev) => ({ 61 | ...prev, 62 | [menuKey]: !prev[menuKey], 63 | })); 64 | }; 65 | 66 | // for handling sub menus 67 | useEffect(() => { 68 | const handleSubMenu = (e) => { 69 | Object.keys(menuRefs.current).forEach((key) => { 70 | if ( 71 | menuRefs.current[key] && 72 | !menuRefs.current[key]?.contains(e.target) 73 | ) { 74 | setSubmenus((prev) => ({ 75 | ...prev, 76 | [key]: false, 77 | })); 78 | } 79 | }); 80 | }; 81 | 82 | document.addEventListener("mousedown", handleSubMenu); 83 | return () => { 84 | document.removeEventListener("mousedown", handleSubMenu); 85 | }; 86 | }, []); 87 | 88 | const menuItems = [ 89 | { 90 | key: "m1", 91 | label: "Menu1", 92 | subItems: ["Submenu 1", "Submenu 2", "Submenu 3"], 93 | }, 94 | { 95 | key: "m2", 96 | label: "Menu2", 97 | subItems: ["Submenu 1", "Submenu 2", "Submenu 3"], 98 | }, 99 | ]; 100 | 101 | return ( 102 |
103 |

Menu With Submenu Styles & Modal

104 | 105 |
106 |
    107 |
  • Logo
  • 108 |
109 | {!mobile && ( 110 |
    111 | {menuItems.map((menu) => ( 112 |
  • handleClick(menu.key)} 118 | ref={(el) => (menuRefs.current[menu.key] = el)} 119 | onMouseEnter={() => 120 | setSubmenus((prev) => { 121 | const newState = Object.keys(prev).reduce((acc, key) => { 122 | acc[key] = false; 123 | return acc; 124 | }, {}); 125 | newState[menu.key] = true; 126 | return newState; 127 | }) 128 | } 129 | > 130 |

    {menu.label}

    131 | {submenus[menu.key] && ( 132 |
    133 |
      134 | {menu.subItems.map((subItem, index) => ( 135 |
    • 136 | {subItem} 137 |
    • 138 | ))} 139 |
    140 |
    141 | )} 142 |
  • 143 | ))} 144 |
  • 145 | 146 |
  • 147 |
148 | )} 149 | 150 | {mobile && ( 151 |
152 |
setMobileOpen(!mobileOpen)} 155 | tabIndex="0" 156 | > 157 | {mobileOpen ? "X" : "="} 158 |
159 | 160 | {mobileOpen && ( 161 | 191 | )} 192 |
193 | )} 194 |
195 | 196 |
197 | ); 198 | } 199 | -------------------------------------------------------------------------------- /src/components/kelixirr/Header.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | flex-direction: column; 6 | margin: var(--spacing-xl-3); 7 | } 8 | 9 | .container h3 { 10 | font-size: var(--font-size-heading); 11 | font-weight: var(--font-weight-bold); 12 | color: var(--text-color); 13 | } 14 | 15 | .header { 16 | margin: var(--spacing-xl-4); 17 | border: 0.1rem solid var(--border-color); 18 | box-shadow: var(--shadow-md); 19 | padding: var(--spacing-lg); 20 | border-radius: var(--border-radius-md); 21 | display: flex; 22 | width: 80%; 23 | justify-content: space-between; 24 | position: relative; 25 | } 26 | 27 | @media (max-width: 900px) { 28 | .container { 29 | margin: var(--spacing-xl-2) var(--spacing-md); 30 | text-align: center; 31 | } 32 | 33 | .header { 34 | margin: var(--spacing-xl-2) 0; 35 | width: 100%; 36 | } 37 | } 38 | 39 | .headerLeft, 40 | .headerRight { 41 | display: flex; 42 | list-style: none; 43 | align-items: center; 44 | gap: var(--spacing-md); 45 | } 46 | 47 | .headerRight { 48 | cursor: pointer; 49 | } 50 | 51 | .headerLeft>li, 52 | .headerRight>li { 53 | padding-bottom: 0.2rem; 54 | } 55 | 56 | .headerRight>li { 57 | position: relative; 58 | } 59 | 60 | 61 | .submenu { 62 | position: absolute; 63 | top: var(--spacing-xl); 64 | left: -15rem; 65 | width: max-content; 66 | border-radius: var(--border-radius-md); 67 | width: 200px; 68 | z-index: 2; 69 | opacity: 0; 70 | visibility: hidden; 71 | transition: opacity var(--transition-base), visibility var(--transition-base); 72 | } 73 | 74 | .submenu::after { 75 | content: ""; 76 | position: absolute; 77 | top: -10px; 78 | right: 4%; 79 | border-left: 10px solid transparent; 80 | border-right: 10px solid transparent; 81 | border-bottom: 10px solid var(--text-light-color); 82 | } 83 | 84 | .submenu ul { 85 | list-style: none; 86 | display: flex; 87 | flex-direction: column; 88 | align-items: center; 89 | border: 0.1rem solid var(--text-light-color); 90 | } 91 | 92 | .submenu li { 93 | padding: var(--spacing-md) var(--spacing-md); 94 | transition: transform var(--transition-base), background-color var(--transition-base), color var(--transition-base); 95 | } 96 | 97 | .headerRight>li:hover .submenu, 98 | .headerRight>li:focus-within .submenu { 99 | opacity: 1; 100 | visibility: visible; 101 | } 102 | 103 | .submenu li:not(:last-child) { 104 | border-bottom: 1px solid var(--border-color); 105 | } 106 | 107 | .submenu li:hover { 108 | cursor: pointer; 109 | } 110 | 111 | .submenu li span, 112 | .mobileSubmenuUl li span { 113 | display: inline-block; 114 | padding: 0.2rem 1rem; 115 | transition: transform var(--transition-base), color var(--transition-base); 116 | } 117 | 118 | .submenu li:hover span, 119 | .mobileSubmenuUl li:hover span { 120 | transform: translateX(10px); 121 | background-color: var(--primary-color); 122 | color: #fff; 123 | } 124 | 125 | 126 | .mobileMenu { 127 | position: relative; 128 | } 129 | 130 | .hamburger { 131 | cursor: pointer; 132 | font-size: var(--font-size-heading-lg); 133 | } 134 | 135 | .mobileNav { 136 | position: absolute; 137 | top: 100%; 138 | right: 1px; 139 | background: var(--background-color); 140 | width: 200px; 141 | box-shadow: var(--shadow-sm); 142 | } 143 | 144 | .mobileNavUl { 145 | padding: var(--spacing-md) 0; 146 | } 147 | 148 | .mobileNavUl, 149 | .mobileSubmenuUl { 150 | list-style: none; 151 | display: flex; 152 | align-items: center; 153 | justify-content: center; 154 | gap: var(--spacing-md); 155 | flex-direction: column; 156 | cursor: pointer; 157 | text-align: center; 158 | } 159 | 160 | .mobileSubmenuUl { 161 | margin: var(--spacing-md) 0; 162 | padding: var(--spacing-lg); 163 | background-color: #f1f0ff; 164 | } -------------------------------------------------------------------------------- /src/components/kelixirr/PopUpModal.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from "react"; 2 | import styles from "../kelixirr/PopUpModal.module.css"; 3 | 4 | export default function PopUpModal() { 5 | const [modalState, setModalState] = useState(false); 6 | const modalOpenRef = useRef(null); 7 | const modalRef = useRef(null); 8 | 9 | useEffect(() => { 10 | if (modalState) { 11 | modalRef.current?.focus(); 12 | } 13 | }, [modalState]); 14 | 15 | useEffect(() => { 16 | const handleKeyDown = (e) => { 17 | if (e.key === "Escape") { 18 | setModalState(false); 19 | } 20 | }; 21 | 22 | document.addEventListener("keydown", handleKeyDown); 23 | return () => { 24 | document.removeEventListener("keydown", handleKeyDown); 25 | }; 26 | }, []); 27 | 28 | const handleTabKey = (e) => { 29 | if (!modalRef.current) return; 30 | 31 | const focusableElements = modalRef.current.querySelectorAll( 32 | 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' 33 | ); 34 | 35 | const firstElement = focusableElements[0]; 36 | const lastElement = focusableElements[focusableElements.length - 1]; 37 | 38 | if (e.key === "Tab") { 39 | if (e.shiftKey) { 40 | if (document.activeElement === firstElement) { 41 | lastElement.focus(); 42 | e.preventDefault(); 43 | } 44 | } else { 45 | if (document.activeElement === lastElement) { 46 | firstElement.focus(); 47 | e.preventDefault(); 48 | } 49 | } 50 | } 51 | }; 52 | 53 | return ( 54 |
55 | 63 | {modalState && ( 64 |
setModalState(false)} 67 | > 68 |
e.stopPropagation()} 71 | ref={modalRef} 72 | onKeyDown={handleTabKey} 73 | aria-modal="true" 74 | aria-labelledby="modal-ttile" 75 | role="dialog" 76 | tabIndex={-1} 77 | > 78 |
79 | 80 | 86 |
87 |
88 |
89 | )} 90 |
91 | ); 92 | } 93 | -------------------------------------------------------------------------------- /src/components/kelixirr/PopUpModal.module.css: -------------------------------------------------------------------------------- 1 | .modalContainer { 2 | max-width: var(--max-width-content); 3 | margin: 0 auto; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | } 8 | 9 | .modalBtn { 10 | margin: var(--spacing-xl-3); 11 | } 12 | 13 | .ModalOverlay { 14 | position: fixed; 15 | top: 0; 16 | left: 0; 17 | background-color: rgba(12, 12, 12, 0.247); 18 | height: 100vh; 19 | width: 100vw; 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | z-index: 1000; 24 | } 25 | 26 | .Modal { 27 | background-color: var(--background-color); 28 | padding: var(--spacing-lg); 29 | width: 40%; 30 | border-radius: var(--border-radius-md); 31 | } 32 | 33 | .ModalDiv { 34 | display: flex; 35 | justify-content: center; 36 | gap: var(--spacing-lg); 37 | } -------------------------------------------------------------------------------- /src/components/kelixirr/SliderCards.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | HiOutlineArrowCircleLeft, 3 | HiOutlineArrowCircleRight, 4 | } from "react-icons/hi"; 5 | import styles from "./../kelixirr/SliderCards.module.css"; 6 | import { GoDot } from "react-icons/go"; 7 | import { useCallback, useEffect, useState } from "react"; 8 | import { MdAlternateEmail, MdOutlineLocationCity } from "react-icons/md"; 9 | import { RiQuillPenAiFill } from "react-icons/ri"; 10 | import Author from "../../Author"; 11 | 12 | export default function SliderCards() { 13 | const [activeSlider, setActiveSlider] = useState(1); 14 | 15 | const sliders = [ 16 | { 17 | id: 1, 18 | name: "John Doe", 19 | title: "Full-Stack Developer", 20 | content: "Passionate about building scalable web applications.", 21 | image: "https://i.pravatar.cc/150?img=59", 22 | location: "San Francisco, USA", 23 | contact: "johndoe@example.com", 24 | }, 25 | { 26 | id: 2, 27 | name: "Jane Smith", 28 | title: "UI/UX Designer", 29 | content: "Creating intuitive and visually appealing designs.", 30 | image: "https://i.pravatar.cc/150?img=47", 31 | location: "New York, USA", 32 | contact: "janesmith@example.com", 33 | }, 34 | { 35 | id: 3, 36 | name: "Michael Brown", 37 | title: "Data Scientist", 38 | content: "Turning data into actionable insights.", 39 | image: "https://randomuser.me/api/portraits/men/3.jpg", 40 | location: "Toronto, Canada", 41 | contact: "michaelbrown@example.com", 42 | }, 43 | { 44 | id: 4, 45 | name: "Emily Johnson", 46 | title: "Digital Marketer", 47 | content: "Helping brands grow with data-driven strategies.", 48 | image: "https://randomuser.me/api/portraits/women/4.jpg", 49 | location: "London, UK", 50 | contact: "emilyjohnson@example.com", 51 | }, 52 | { 53 | id: 5, 54 | name: "Chris Evans", 55 | title: "Machine Learning Engineer", 56 | content: "Building intelligent systems for modern applications.", 57 | image: "https://randomuser.me/api/portraits/men/5.jpg", 58 | location: "Berlin, Germany", 59 | contact: "chrisevans@example.com", 60 | }, 61 | { 62 | id: 6, 63 | name: "Sophia Martinez", 64 | title: "Content Creator", 65 | content: "Crafting compelling stories for a digital audience.", 66 | image: "https://i.pravatar.cc/150?img=35", 67 | location: "Madrid, Spain", 68 | contact: "sophiamartinez@example.com", 69 | }, 70 | ]; 71 | 72 | const handleSlide = useCallback( 73 | (side) => { 74 | if (side === "left") { 75 | setActiveSlider((prev) => (prev > 1 ? prev - 1 : sliders.length)); 76 | } 77 | if (side === "right") { 78 | setActiveSlider((prev) => (prev < sliders.length ? prev + 1 : 1)); 79 | } 80 | }, 81 | [sliders.length] 82 | ); 83 | 84 | const handleKeyPress = useCallback( 85 | (e) => { 86 | if (e.key === "ArrowLeft") handleSlide("left"); 87 | if (e.key === "ArrowRight") handleSlide("right"); 88 | }, 89 | [handleSlide] 90 | ); 91 | 92 | useEffect(() => { 93 | window.addEventListener("keydown", handleKeyPress); 94 | return () => window.removeEventListener("keydown", handleKeyPress); 95 | }, [handleKeyPress]); 96 | 97 | const renderArrow = (direction) => { 98 | const Icon = 99 | direction === "left" 100 | ? HiOutlineArrowCircleLeft 101 | : HiOutlineArrowCircleRight; 102 | 103 | return handleSlide(direction)} />; 104 | }; 105 | 106 | return ( 107 | <> 108 |
109 |
110 | {renderArrow("left")} 111 |
112 |
118 | {sliders.map((slider) => ( 119 |
120 | {`${slider.name}'s 125 |
126 |
127 |

{slider.name}

128 |

{slider.title}

129 |
130 |
131 |

132 | {slider.location} 133 |

134 |

135 | {slider.contact} 136 |

137 |

138 | 139 | {slider.content} 140 |

141 |
142 |
143 |
144 | ))} 145 |
146 |
147 | {renderArrow("right")} 148 |
149 |
150 | {sliders.map((slider) => ( 151 | setActiveSlider(slider.id)} 154 | className={`${ 155 | activeSlider === slider.id ? styles.activeDot : "" 156 | }`} 157 | /> 158 | ))} 159 |
160 |
161 | 162 | 163 | ); 164 | } 165 | -------------------------------------------------------------------------------- /src/components/kelixirr/SliderCards.module.css: -------------------------------------------------------------------------------- 1 | .sliderContainer { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | max-width: 800px; 7 | margin: 0 auto; 8 | } 9 | 10 | .sliderMain { 11 | display: flex; 12 | width: 50%; 13 | align-items: center; 14 | justify-content: center; 15 | flex-direction: column; 16 | } 17 | 18 | 19 | .sliderMain svg { 20 | font-size: 2.8rem; 21 | color: var(--primary-color); 22 | cursor: pointer; 23 | z-index: 2; 24 | } 25 | 26 | 27 | .sliderDiv { 28 | width: 100%; 29 | overflow: hidden; 30 | border-radius: var(--border-radius-md); 31 | } 32 | 33 | @media (max-width: 48em) { 34 | .sliderMain svg { 35 | font-size: 2.4rem; 36 | } 37 | 38 | .sliderMain { 39 | width: 90%; 40 | } 41 | } 42 | 43 | .sliderTrack { 44 | width: 100%; 45 | display: flex; 46 | transition: transform var(--transition-base); 47 | } 48 | 49 | .slider { 50 | min-width: 100%; 51 | display: flex; 52 | flex-direction: column; 53 | gap: var(--spacing-lg); 54 | border: 1px solid var(--border-color); 55 | border-radius: var(--border-radius-sm); 56 | box-shadow: var(--shadow-sm); 57 | margin: var(--spacing-lg) 0; 58 | transition: transform 0.3s ease, box-shadow 0.3s ease; 59 | background-color: var(--background-color); 60 | } 61 | 62 | .slider img { 63 | height: 65%; 64 | width: 100%; 65 | object-fit: cover; 66 | } 67 | 68 | .sliderDetails { 69 | display: flex; 70 | flex-direction: column; 71 | width: 85%; 72 | margin: 0 auto; 73 | gap: var(--spacing-md); 74 | } 75 | 76 | .sliderDetailsHead { 77 | display: flex; 78 | gap: var(--spacing-lg); 79 | align-items: center; 80 | justify-content: space-between; 81 | } 82 | 83 | .sliderName { 84 | font-size: 2.4rem; 85 | font-weight: var(--font-weight-bold); 86 | color: var(--primary-color); 87 | } 88 | 89 | .sliderTitle { 90 | font-size: 1rem; 91 | font-weight: var(--font-weight-bold); 92 | color: var(--background-color); 93 | background-color: var(--primary-color); 94 | padding: var(--spacing-xs) var(--spacing-sm); 95 | border-radius: var(--border-radius-sm); 96 | } 97 | 98 | .sliderDetailsBox { 99 | display: flex; 100 | flex-direction: column; 101 | gap: var(--spacing-sm); 102 | } 103 | 104 | .sliderLocation, 105 | .sliderContact, 106 | .sliderContent { 107 | font-size: var(--font-size-base); 108 | color: var(--text-color); 109 | display: flex; 110 | align-items: center; 111 | gap: var(--spacing-md); 112 | } 113 | 114 | .sliderDetails svg { 115 | font-size: 2rem; 116 | color: var(--primary-color); 117 | transition: color 0.3s ease; 118 | } 119 | 120 | .sliderDots { 121 | display: flex; 122 | gap: var(--spacing-sm); 123 | justify-content: center; 124 | padding: var(--spacing-md) 0; 125 | margin-top: var(--spacing-lg); 126 | } 127 | 128 | .sliderDots svg { 129 | width: 2rem; 130 | height: 2rem; 131 | opacity: 0.6; 132 | cursor: pointer; 133 | transition: all 0.3s ease; 134 | } 135 | 136 | .sliderDots svg:hover { 137 | opacity: 0.9; 138 | transform: scale(1.5); 139 | } 140 | 141 | .activeDot { 142 | opacity: 1; 143 | transform: scale(1.4); 144 | color: var(--primary-color); 145 | } 146 | 147 | .slider .slider:hover { 148 | box-shadow: var(--shadow-md); 149 | } -------------------------------------------------------------------------------- /src/components/mektefaie/FlashCards.jsx: -------------------------------------------------------------------------------- 1 | import styles from "../mektefaie/FlashCards.module.css"; 2 | import Author from "../../Author"; 3 | import { useState } from "react"; 4 | 5 | const cards = [ 6 | { 7 | id: 1, 8 | question: "The creator of ReactDevs project?", 9 | answer: "Amritesh Kumar", 10 | }, 11 | { 12 | id: 2, 13 | question: "When was ReactDevs project created?", 14 | answer: "2024", 15 | }, 16 | { 17 | id: 3, 18 | question: "The first contributor to ReactDevs project?", 19 | answer: "Victor Ezeanyika", 20 | }, 21 | { 22 | id: 4, 23 | question: "Best React course?", 24 | answer: "Jonas Schmedtmann's Ultimate React course on Udemy", 25 | }, 26 | { 27 | id: 5, 28 | question: "Best Frontend bootcamp?", 29 | answer: "Scrimba.com", 30 | }, 31 | { 32 | id: 6, 33 | question: "Best Backend bootcamp?", 34 | answer: "Boot.dev", 35 | }, 36 | ]; 37 | 38 | export default function FlashCards() { 39 | const [selectedId, setSelectedID] = useState(null); 40 | 41 | function handleClick(id) { 42 | setSelectedID(id === selectedId ? null : id); 43 | } 44 | 45 | return ( 46 |
47 |

Flashcards

48 |

49 | Interactive Flashcards: click on each card to reveal the answer. 50 |

51 |
52 | {cards.map((question) => ( 53 |
handleClick(question.id)} 57 | > 58 | {question.id === selectedId ? question.answer : question.question} 59 |
60 | ))} 61 |
62 | 66 |
67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /src/components/mektefaie/FlashCards.module.css: -------------------------------------------------------------------------------- 1 | .section { 2 | max-width: var(--max-width-content); 3 | margin: var(--spacing-xl-5) auto; 4 | padding: var(--spacing-lg); 5 | } 6 | 7 | .description { 8 | margin-bottom: var(--spacing-xl); 9 | text-align: center; 10 | color: var(--text-color); 11 | } 12 | 13 | .flashcards { 14 | display: grid; 15 | grid-template-columns: 1fr 1fr 1fr; 16 | gap: 20px; 17 | } 18 | 19 | .flashcards div { 20 | border: 1px solid var(--border-color); 21 | background-color: var(--border-color); 22 | border-radius: var(--border-radius-md); 23 | aspect-ratio: 2 / 1; 24 | display: flex; 25 | align-items: center; 26 | justify-content: center; 27 | text-align: center; 28 | padding: 20px; 29 | cursor: pointer; 30 | } 31 | 32 | .selected { 33 | border: 1px solid var(--primary-color) !important; 34 | background-color: var(--primary-color) !important; 35 | color: #fff; 36 | font-weight: var(--font-weight-regular); 37 | } 38 | 39 | /* medium breakpoint */ 40 | @media (max-width: 767px) { 41 | .flashcards { 42 | grid-template-columns: 1fr 1fr; 43 | } 44 | } 45 | 46 | /* small breakpoint */ 47 | @media (max-width: 639px) { 48 | .flashcards { 49 | grid-template-columns: 1fr; 50 | } 51 | } -------------------------------------------------------------------------------- /src/components/rrusyaidii/Login.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./Login.module.css"; 3 | import Author from "../../Author"; 4 | 5 | const Login = () => { 6 | return ( 7 | <> 8 |
9 |
10 |

Login

11 | 12 | 17 | 18 |
19 |
20 | 21 | 22 | ); 23 | }; 24 | 25 | export default Login; 26 | -------------------------------------------------------------------------------- /src/components/rrusyaidii/Login.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | height: 100vh; 6 | background-color: #f4f4f4; 7 | } 8 | 9 | .form { 10 | background: white; 11 | padding: 2rem; 12 | border-radius: 8px; 13 | box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 14 | width: 320px; 15 | text-align: center; 16 | } 17 | 18 | .input { 19 | width: 100%; 20 | padding: 10px; 21 | margin: 10px 0; 22 | border: 1px solid #ccc; 23 | border-radius: 4px; 24 | } 25 | 26 | .button { 27 | width: 100%; 28 | padding: 10px; 29 | background-color: #007bff; 30 | color: white; 31 | border: none; 32 | border-radius: 4px; 33 | cursor: pointer; 34 | } 35 | 36 | .button:hover { 37 | background-color: #0056b3; 38 | } 39 | -------------------------------------------------------------------------------- /src/components/sushantpokhrel/Modal.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "../sushantpokhrel/Modal.module.css"; 3 | import Author from "../../Author"; 4 | function Modal() { 5 | const [show, setShow] = React.useState(false); 6 | function handleOutsideClick(e) { 7 | console.log(e.target.id); 8 | if (e.target.id === "overlay-close") setShow(false); 9 | } 10 | return ( 11 |
12 |
13 |

Modal Component

14 | 15 |
16 |
handleOutsideClick(e)} 20 | > 21 |
22 |
23 |

Modal title

{" "} 24 | 25 |
26 |

Lorem ipsum dolor sit amet consectetur adipisicing elit.

27 |
28 |
29 | 33 |
34 | ); 35 | } 36 | 37 | export default Modal; 38 | -------------------------------------------------------------------------------- /src/components/sushantpokhrel/Modal.module.css: -------------------------------------------------------------------------------- 1 | .modal_container { 2 | padding: var(--spacing-lg); 3 | margin: var(--spacing-xl-5) 0; 4 | } 5 | .modal_open { 6 | max-width: var(--max-width-content); 7 | margin: var(--spacing-sm) auto; 8 | text-align: center; 9 | } 10 | .modal_open button { 11 | margin: var(--spacing-sm) 0; 12 | } 13 | .overlay { 14 | visibility: hidden; 15 | position: fixed; 16 | top: 0; 17 | left: 0; 18 | bottom: 0; 19 | right: 0; 20 | background-color: rgba(0, 0, 0, 0.2); 21 | z-index: 9; 22 | } 23 | .overlay.open { 24 | visibility: visible; 25 | } 26 | .modal { 27 | max-width: var(--max-width-content); 28 | position: fixed; 29 | top: 40%; 30 | left: 30%; 31 | box-shadow: var(--shadow-md); 32 | padding: var(--spacing-lg); 33 | z-index: 10; 34 | background-color: white; 35 | border-radius: var(--border-radius-sm); 36 | transform: scale(0.5); 37 | transition: var(--transition-base); 38 | } 39 | .overlay.open { 40 | & .modal { 41 | transform: scale(1); 42 | } 43 | } 44 | 45 | .title_flex { 46 | display: flex; 47 | justify-content: space-between; 48 | } 49 | .modal p { 50 | margin-top: var(--spacing-sm); 51 | } 52 | @media (max-width: 750px) { 53 | .modal { 54 | left: 20%; 55 | padding: var(--spacing-md); 56 | right: 15%; 57 | } 58 | } 59 | @media (max-width: 425px) { 60 | .modal { 61 | font-size: 1.1rem; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | /* global.css */ 2 | 3 | /* 4 | :root variables for consistent styling across the project. 5 | Contributors: Please use these variables wherever applicable 6 | to maintain uniformity in the design. 7 | 8 | - Use the defined variables in your components for styling. 9 | - Don't overriding global styles. 10 | - Pro-Tip: if you need to add your size please rem values divisible by 4 11 | 12 | */ 13 | 14 | :root { 15 | /* Color Palette */ 16 | --primary-color: #1e90ff; 17 | /* Primary blue for buttons, links, etc. */ 18 | --primary-color-hover: #0c7cd5; 19 | /* Darker blue for hover states */ 20 | --secondary-color: #ffd700; 21 | /* Secondary yellow for accents */ 22 | --background-color: #ffffff; 23 | /* Default background */ 24 | --text-color: #333333; 25 | /* Default text color */ 26 | --text-light-color: #666666; 27 | /* Subdued text for secondary information */ 28 | --border-color: #eee; 29 | /* Neutral border color */ 30 | --shadow-color: rgba(0, 0, 0, 0.1); 31 | /* Light shadow for cards, modals */ 32 | 33 | /* Typography */ 34 | --font-family: sans-serif; 35 | /* Default font family */ 36 | --font-size-base: 1.6rem; 37 | /* Base font size (default text) */ 38 | --font-size-heading: 2.4rem; 39 | --font-size-heading-lg: 3.2rem; 40 | --font-size-heading-hero: 4.8rem; 41 | /* Size for headings */ 42 | --font-size-subheading: 2rem; 43 | /* Subheadings */ 44 | --line-height-base: 1.6; 45 | /* Line height for readable text */ 46 | --font-weight-regular: 400; 47 | /* Regular font weight */ 48 | --font-weight-bold: 600; 49 | /* Bold font weight */ 50 | 51 | /* Spacing */ 52 | --spacing-xs: 0.4rem; 53 | /* Extra small spacing */ 54 | --spacing-sm: 0.8rem; 55 | /* Small spacing */ 56 | --spacing-md: 1.6rem; 57 | /* Medium spacing */ 58 | --spacing-lg: 2.4rem; 59 | /* Large spacing */ 60 | --spacing-xl: 3.2rem; 61 | /* Extra large spacing */ 62 | --spacing-xl-2: 4.8rem; 63 | --spacing-xl-3: 6.4rem; 64 | --spacing-xl-4: 8rem; 65 | --spacing-xl-5: 9.6rem; 66 | 67 | /* Border Radius */ 68 | --border-radius-sm: 0.4rem; 69 | --border-radius-md: 0.8rem; 70 | --border-radius-lg: 1.2rem; 71 | 72 | /* Shadows */ 73 | --shadow-sm: 0 2px 4px var(--shadow-color); 74 | --shadow-md: 0 4px 8px var(--shadow-color); 75 | --shadow-lg: 0 8px 16px var(--shadow-color); 76 | --focus-color: #ffe8dc; 77 | 78 | /* Transitions */ 79 | --transition-base: 0.3s ease; 80 | /* Default smooth transition */ 81 | 82 | /* Max Widths */ 83 | --max-width-container: 1200px; 84 | /* Maximum width for containers */ 85 | --max-width-content: 800px; 86 | /* Maximum width for content sections */ 87 | } 88 | 89 | /* Base Reset */ 90 | * { 91 | margin: 0; 92 | padding: 0; 93 | box-sizing: border-box; 94 | } 95 | 96 | 97 | /* Webkit browsers (Chrome, Safari, Edge, Opera) */ 98 | ::-webkit-scrollbar { 99 | width: 2px; 100 | height: 2px; 101 | } 102 | 103 | *:focus { 104 | outline: none; 105 | -webkit-tap-highlight-color: transparent; 106 | } 107 | 108 | *:focus-visible { 109 | outline: 2px solid var(--focus-color); 110 | outline-offset: 2px; 111 | } 112 | 113 | 114 | /* Body and Default Layout */ 115 | html { 116 | font-size: 62.5%; 117 | /* 1rem = 10px for easier calculations */ 118 | overflow-x: hidden; 119 | } 120 | 121 | body { 122 | font-family: var(--font-family); 123 | font-size: var(--font-size-base); 124 | color: var(--text-color); 125 | line-height: var(--line-height-base); 126 | background-color: var(--background-color); 127 | margin: 0 auto; 128 | } 129 | 130 | /* Links */ 131 | a { 132 | color: var(--primary-color); 133 | text-decoration: none; 134 | transition: color var(--transition-base); 135 | } 136 | 137 | /* a:focus { 138 | color: var(--primary-color-hover); 139 | } */ 140 | 141 | /* Buttons */ 142 | button { 143 | font-family: inherit; 144 | font-size: var(--font-size-base); 145 | padding: var(--spacing-sm) var(--spacing-md); 146 | border: none; 147 | border-radius: var(--border-radius-md); 148 | cursor: pointer; 149 | background-color: var(--primary-color); 150 | color: #fff; 151 | box-shadow: var(--shadow-sm); 152 | transition: background-color var(--transition-base), box-shadow var(--transition-base); 153 | } 154 | 155 | 156 | /* Inputs */ 157 | input, 158 | textarea { 159 | width: 100%; 160 | padding: var(--spacing-sm); 161 | border: 1px solid var(--border-color); 162 | border-radius: var(--border-radius-sm); 163 | font-family: inherit; 164 | font-size: var(--font-size-base); 165 | color: var(--text-color); 166 | transition: border-color var(--transition-base); 167 | } 168 | 169 | input:focus, 170 | textarea:focus { 171 | border-color: var(--primary-color); 172 | outline: none; 173 | } 174 | 175 | /* Tables */ 176 | table { 177 | width: 100%; 178 | border-collapse: collapse; 179 | } 180 | 181 | th, 182 | td { 183 | padding: var(--spacing-sm); 184 | border: 1px solid var(--border-color); 185 | } 186 | 187 | th { 188 | background-color: var(--primary-color); 189 | color: #fff; 190 | font-weight: var(--font-weight-bold); 191 | } -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import './index.css' 4 | import App from './App.jsx' 5 | 6 | createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | --------------------------------------------------------------------------------