├── .env ├── image.png ├── favicon.ico ├── src ├── App.css ├── components │ ├── arrow.gif │ ├── ScrollToTop.jsx │ ├── CardsList.jsx │ ├── addNote.jsx │ ├── Search.jsx │ ├── LoginButton.jsx │ ├── AddNotePopup.jsx │ ├── Card.jsx │ ├── MainContent.jsx │ ├── Header.jsx │ └── BottomHeader.jsx ├── main.jsx ├── App.jsx └── index.css ├── postcss.config.js ├── vite.config.js ├── .prettierrc ├── tailwind.config.js ├── .gitignore ├── .github └── workflows │ ├── contribute.yml │ └── congrats.yml ├── index.html ├── manifest.json ├── package.json ├── LICENSE ├── CONTRIBUTING.md ├── contributors.md └── README.md /.env: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danishzayan/YourQuotes-App/HEAD/image.png -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danishzayan/YourQuotes-App/HEAD/favicon.ico -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | /* Project Name: YourQutoesApp 2 | Date: 07-08-2022 3 | Developer: Danish Kamal */ -------------------------------------------------------------------------------- /src/components/arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danishzayan/YourQuotes-App/HEAD/src/components/arrow.gif -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5", 6 | "printWidth": 80, 7 | "bracketSpacing": true, 8 | "arrowParens": "avoid" 9 | } 10 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,jsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | 13 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /src/components/ScrollToTop.jsx: -------------------------------------------------------------------------------- 1 | import Arrow from "./arrow.gif" 2 | 3 | const ScrollToTop = () => { 4 | return ( 5 |
6 |
7 | arrow 8 |
9 |
10 | ); 11 | } 12 | 13 | export default ScrollToTop; -------------------------------------------------------------------------------- /.github/workflows/contribute.yml: -------------------------------------------------------------------------------- 1 | name: Contribute List 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | contrib-readme-job: 10 | runs-on: ubuntu-latest 11 | name: A job to automate contrib in readme 12 | steps: 13 | - name: Contribute List 14 | uses: akhilmhdh/contributors-readme-action@v2.3.10 15 | with: 16 | readme_path: 'contributors.md' 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { GoogleOAuthProvider } from '@react-oauth/google'; 4 | import App from './App' 5 | import './index.css' 6 | const clientId = "537577681906-379ajvh68vgtnkrpd0am696qiuf72ulc.apps.googleusercontent.com"; 7 | ReactDOM.createRoot(document.getElementById('root')).render( 8 | 9 | {/* */} 10 | 11 | {/* */} 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | Your Quotes 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "YourQuotes", 3 | "name": "YourQuotes", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#fd5202", 14 | "background_color": "#ffffff", 15 | "description": "YourQuotes is a user friendly and an eye catching App. User can post your qutoes without login and that user can delete YourQuotes not from other user. User can share quotes with friend, copy to clipboard and do download gradient quotes image..", 16 | "dir": "ltr", 17 | "lang": "en-EN", 18 | "orientation": "any" 19 | } -------------------------------------------------------------------------------- /src/components/CardsList.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Card from "./Card"; 3 | // import AddNote from "./addNote"; 4 | 5 | const CardsList = ({ notes, handleAddNote, handleDeleteNote, searchText }) => { 6 | return ( 7 |
8 | {searchText !== "" &&

{notes.length} Results

} 9 |
10 | {[...notes].reverse().map((note) => ( 11 | 21 | ))} 22 | {/* */} 23 |
24 |
25 | ); 26 | }; 27 | 28 | export default CardsList; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "YourQuotes-App", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.13.0", 13 | "@emotion/styled": "^11.13.0", 14 | "@lottiefiles/react-lottie-player": "^3.4.7", 15 | "@mui/material": "^5.16.6", 16 | "@react-oauth/google": "^0.12.1", 17 | "axios": "^0.27.2", 18 | "dotenv": "^16.4.5", 19 | "html-to-image": "^1.10.8", 20 | "react": "^18.2.0", 21 | "react-dom": "^18.2.0", 22 | "react-icons": "^5.2.1", 23 | "react-toastify": "^9.0.8" 24 | }, 25 | "devDependencies": { 26 | "@types/react": "^18.0.17", 27 | "@types/react-dom": "^18.0.6", 28 | "@vitejs/plugin-react": "^2.1.0", 29 | "autoprefixer": "^10.4.19", 30 | "postcss": "^8.4.38", 31 | "prettier": "^3.3.3", 32 | "tailwindcss": "^3.4.3", 33 | "vite": "^3.1.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Danish Zayan 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 | -------------------------------------------------------------------------------- /src/components/addNote.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | const AddNote = ({ handleAddNote }) => { 4 | 5 | const [noteText, setNoteText] = useState(''); 6 | 7 | const characterLimit = 200; 8 | 9 | const handleChange = (event) => { 10 | if (characterLimit - event.target.value.length >= 0) { 11 | setNoteText(event.target.value); 12 | } 13 | } 14 | 15 | const handleSave = (e) => { 16 | e.preventDefault(); 17 | if (noteText.trim().length > 0) { 18 | handleAddNote(noteText); 19 | setNoteText(''); 20 | } 21 | } 22 | 23 | return ( 24 |
25 | 32 | 33 |
34 | {characterLimit - noteText.length} Remaining 35 | 36 |
37 |
38 | ); 39 | }; 40 | 41 | export default AddNote; 42 | -------------------------------------------------------------------------------- /src/components/Search.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Search = ({ handleSearchNote }) => { 4 | return ( 5 | <> 6 |
7 | 22 | Search icon 23 |
24 | handleSearchNote(event.target.value)} 26 | type="text" 27 | id="search-navbar" 28 | className="block w-full p-2 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" 29 | placeholder="Search..." 30 | /> 31 | 32 | ); 33 | }; 34 | 35 | export default Search; 36 | -------------------------------------------------------------------------------- /src/components/LoginButton.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useGoogleLogin } from "@react-oauth/google"; 3 | import axios from "axios"; 4 | 5 | export default function LoginButton({setUser,isLoggedIn}) { 6 | const login = useGoogleLogin({ 7 | onSuccess: async (tokenResponse) => { 8 | try { 9 | localStorage.setItem("token",tokenResponse.access_token); 10 | const res = await axios.get( 11 | "https://www.googleapis.com/oauth2/v3/userinfo", 12 | { 13 | headers: { 14 | Authorization: `Bearer ${tokenResponse.access_token}`, 15 | }, 16 | } 17 | ); 18 | setUser(res.data); 19 | // console.log(res); 20 | } catch (err) { 21 | console.log(err); 22 | } 23 | }, 24 | }); 25 | const logout = () =>{ 26 | setUser(null); 27 | localStorage.removeItem("token"); 28 | } 29 | return ( 30 |
31 | 44 |
45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/congrats.yml: -------------------------------------------------------------------------------- 1 | name: Congratulatory Message 2 | 3 | on: 4 | issues: 5 | types: [opened] 6 | push: 7 | branches: [main] # Change this to your default branch 8 | pull_request: 9 | types: [opened, closed] 10 | 11 | jobs: 12 | notify: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | 19 | - name: Send Congratulatory Message 20 | if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true 21 | run: | 22 | echo "Congratulations @${{ github.event.pull_request.user.login }}! Your PR has been merged! 🎉" 23 | # Optionally, you can call the OpenAI API to generate a unique message. 24 | 25 | # Install curl if it's not available 26 | sudo apt-get install curl 27 | 28 | # Set your OpenAI API Key in the repository secrets 29 | OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} 30 | 31 | # Call OpenAI API 32 | RESPONSE=$(curl https://api.openai.com/v1/chat/completions \ 33 | -s \ 34 | -H "Authorization: Bearer $OPENAI_API_KEY" \ 35 | -H "Content-Type: application/json" \ 36 | -d '{ 37 | "model": "gpt-3.5-turbo", 38 | "messages": [{"role": "user", "content": "Generate a unique congratulatory message for a GitHub contributor."}], 39 | "max_tokens": 50 40 | }') 41 | 42 | # Extract the content from the response 43 | MESSAGE=$(echo $RESPONSE | jq -r '.choices[0].message.content') 44 | 45 | # Print the message 46 | echo "Message from OpenAI: $MESSAGE" 47 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | //API Details 2 | // 20220912223415 3 | // https://6315b6ef33e540a6d38296a9.mockapi.io/notepad-app 4 | 5 | import React, { useState, useEffect } from "react"; 6 | import "./App.css"; 7 | import Header from "./components/Header"; 8 | import "react-toastify/dist/ReactToastify.css"; 9 | import MainContent from "./components/MainContent"; 10 | 11 | function App() { 12 | const [searchText, setSearchText] = useState(""); 13 | const [darkMode, setDarkMode] = useState(false); 14 | const [addNotePopupIsOpen, setAddNotePopupIsOpen] = useState(false); 15 | const handlePopupOpen = () => { 16 | setAddNotePopupIsOpen(true); 17 | // console.log("here"); 18 | }; 19 | /*Checks the localstorage to see if the dark mode was enabled during last visit*/ 20 | useEffect(() => { 21 | if (!localStorage.getItem("darkmode")) { 22 | return; 23 | } 24 | let darkmode = JSON.parse(localStorage.getItem("darkmode")); 25 | if (darkmode.isDark == true) { 26 | setDarkMode(true); 27 | } 28 | }, []); 29 | 30 | const checkIfClickedInside = (e) => { 31 | if ( 32 | e.target.dataset.target != "popup" && 33 | e.target.dataset.target != "add-btn" 34 | ) { 35 | setAddNotePopupIsOpen(false); 36 | } 37 | }; 38 | // console.log("rendering app"); 39 | return ( 40 | <> 41 |
45 |
50 | 57 |
58 | 59 | ); 60 | } 61 | 62 | export default App; 63 | -------------------------------------------------------------------------------- /src/components/AddNotePopup.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { toast, ToastContainer } from "react-toastify"; 3 | 4 | const AddNotePopup = ({ handleAddNote, setAddNotePopupIsOpen }) => { 5 | 6 | const [noteText, setNoteText] = useState(""); 7 | const [noteWriter, setNoteWriter] = useState(""); 8 | 9 | const characterLimit = 200; 10 | 11 | const handleChange = (event) => { 12 | if (characterLimit - event.target.value.length >= 0) { 13 | setNoteText(event.target.value); 14 | } 15 | }; 16 | 17 | const handleSave = (e) => { 18 | e.preventDefault(); 19 | if (noteText.trim().length > 0) { 20 | handleAddNote(noteText, noteWriter); 21 | setNoteText(""); 22 | setAddNotePopupIsOpen(false); 23 | } 24 | else { 25 | toast.error('Couldn\'t add an empty..', { 26 | position: "top-center", 27 | autoClose: 2000, 28 | hideProgressBar: false, 29 | closeOnClick: true, 30 | pauseOnHover: true, 31 | draggable: true, 32 | progress: undefined, 33 | }); 34 | } 35 | }; 36 | 37 | return ( 38 | <> 39 | 40 |
41 |

42 | Add a YourQuote 43 |

44 | 51 | { setNoteWriter(e.target.value) }} /> 52 |
53 | 54 | {characterLimit - noteText.length} Remaining 55 | 56 | 59 |
60 |
61 | 62 | ); 63 | }; 64 | 65 | export default AddNotePopup; 66 | -------------------------------------------------------------------------------- /src/components/Card.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { toast } from 'react-toastify'; 3 | import 'react-toastify/dist/ReactToastify.css'; 4 | import * as htmlToImage from 'html-to-image'; 5 | 6 | const Card = ({ id, color1, color2, text, date, handleDeleteNote, writer }) => { 7 | 8 | // code for listen text speech 9 | const msg = new SpeechSynthesisUtterance(); 10 | msg.text = text; 11 | const talk = () => { 12 | window.speechSynthesis.speak(msg); 13 | }; 14 | 15 | // code for clipboard and toastify 16 | const handleCopyText = () => { 17 | navigator.clipboard.writeText(text).then( 18 | (success) => 19 | toast('📋 Successfully Copied Text!', { 20 | position: 'top-center', 21 | autoClose: 2000, 22 | hideProgressBar: false, 23 | closeOnClick: true, 24 | pauseOnHover: true, 25 | draggable: true, 26 | progress: undefined, 27 | }), 28 | (err) => alert('Error copying text') 29 | ); 30 | }; 31 | 32 | // code for share button 33 | const handleShareText = () => { 34 | if (navigator.share) { 35 | navigator 36 | .share({ 37 | text: `${text}`, 38 | url: 'https://your-quotess.netlify.app/', 39 | }) 40 | .then(() => { 41 | console.log('Thanks for sharing!'); 42 | }) 43 | .catch((err) => { 44 | console.log('Error while using Web share API:' + err); 45 | }); 46 | } else { 47 | alert("Browser doesn't support this API !"); 48 | } 49 | }; 50 | 51 | 52 | // code for convert html to image 53 | const domEl = useRef(null); 54 | const downloadImage = async () => { 55 | const dataUrl = await htmlToImage.toPng(domEl.current); 56 | const link = document.createElement('a'); 57 | link.download = 'your-quotes.png'; 58 | link.href = dataUrl; 59 | link.click(); 60 | }; 61 | 62 | return ( 63 | <> 64 |
72 |
73 | 74 | {text} 75 | 76 |
77 |
78 | ~ By {writer ? writer : 'Danish'} 79 |
80 | 81 | 82 | {date} 83 | 84 |
85 | 86 | 87 | 88 | 89 | handleDeleteNote(id)} 92 | title="delete" > 93 |
94 |
95 |
96 |
97 | 98 | ); 99 | }; 100 | 101 | export default Card; 102 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines for YourQuotes App 👨‍💻 2 | 3 | ## 👨‍💻 Prerequisite Skills to Contribute 4 | 5 | - [Git](https://git-scm.com/) 6 | - [Basic JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 7 | - [NodeJS](https://nodejs.org/) 8 | 9 | ### Contribute in Documents 10 | 11 | - [Markdown](https://www.markdownguide.org/basic-syntax/) 12 | 13 | --- 14 | 15 | ## 💥 How to Contribute 16 | 17 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/danishzayan/YourQuotes-App/pulls) 18 | [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.png?v=103)](https://github.com/danishzayan/YourQuotes-App/) 19 | 20 | - Take a look at the existing [Issues](https://github.com/danishzayan/YourQuotes-App/issues) or [create a new issue](https://github.com/danishzayan/YourQuotes-App/issues/new/choose)! 21 | - [Fork the Repo](https://github.com/danishzayan/YourQuotes-App/fork). Then, create a branch for any issue that you are working on. Finally, commit your work. 22 | - Create a **[Pull Request](https://github.com/danishzayan/YourQuotes-App/compare)** (_PR_), which will be promptly reviewed and given suggestions for improvements by the community. 23 | - Add screenshots or screen captures to your Pull Request to help us understand the effects of the changes proposed in your PR. 24 | 25 | --- 26 | 27 | ## ⭐ HOW TO MAKE A PULL REQUEST: 28 | 29 | **1.** Start by making a Fork of the [**YourQuotes**](https://github.com/danishzayan/YourQuotes-App) repository. Click on the Fork symbol at the top right corner. 30 | 31 | **2.** Clone your new fork of the repository in the terminal/CLI on your computer with the following command: 32 | 33 | ```bash 34 | git clone https://github.com//YourQuotes 35 | ``` 36 | 37 | **3.** Navigate to the newly created LinkFree project directory: 38 | 39 | ```bash 40 | cd YourQuotes 41 | ``` 42 | 43 | **4.** Create a new branch: 44 | 45 | ```bash 46 | git checkout -b YourBranchName 47 | ``` 48 | 49 | ⚠️ **Make sure** not to commit `package.json` or `package-lock.json` file 50 | 51 | ⚠️ **Make sure** not to run the commands `git add .` or `git add *`. Instead, stage your changes for each file/folder 52 | 53 | **5.** Add those changes to the branch you just created using the git add command: 54 | 55 | ```bash 56 | git add . 57 | ``` 58 | 59 | - After git add command see status with git status command: 60 | 61 | ```bash 62 | git status 63 | ``` 64 | 65 | **6.** Now commit those changes using the git commit command:: 66 | 67 | ```bash 68 | git commit -m "" 69 | ``` 70 | 71 | **7.** Push your local commits to the remote repository: 72 | 73 | ```bash 74 | git push origin YourBranchName 75 | ``` 76 | 77 | **8.** Create a [Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)! 78 | 79 | **9.** **Congratulations!** You've made your first contribution to [**YourQuotes**](https://github.com/danishzayan/YourQuotes-App/graphs/contributors)! 🙌🏼 80 | 81 | **_:trophy: After this, the maintainers will review the PR and will merge it if it helps move the YourQuotes project forward. Otherwise, it will be given constructive feedback and suggestions for the changes needed to add the PR to the codebase._** 82 | 83 | --- 84 | 85 | ## Style Guide for Git Commit Messages :memo: 86 | 87 | **How you can add more value to your contribution logs:** 88 | 89 | - Use the present tense. (Example: "Add feature" instead of "Added feature") 90 | - Use the imperative mood. (Example: "Move item to...", instead of "Moves item to...") 91 | - Limit the first line (also called the Subject Line) to _50 characters or less_. 92 | - Capitalize the Subject Line. 93 | - Separate subject from body with a blank line. 94 | - Do not end the subject line with a period. 95 | - Wrap the body at _72 characters_. 96 | - Use the body to explain the _what_, _why_, _vs_, and _how_. 97 | - Reference [Issues](https://github.com/danishzayan/YourQuotes-App/issues) and [Pull Requests](https://github.com/danishzayan/YourQuotes-App/pulls) liberally after the first line. 98 | 99 | --- 100 | 101 | ## 💥 Issues 102 | 103 | In order to discuss changes, you are welcome to [open an issue](https://github.com/danishzayan/YourQuotes-App/issues/new/choose) about what you would like to contribute. Enhancements are always encouraged and appreciated. 104 | 105 | ## All the best! 🥇 106 | 107 | [![built with love](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/danishzayan/YourQuotes-App) 108 | -------------------------------------------------------------------------------- /contributors.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | **Awesome people who messed with the code in this repo** 4 | 5 | 6 | 7 | 8 | 15 | 22 | 29 | 36 | 43 | 50 | 51 | 58 | 65 | 72 | 79 | 86 | 93 | 94 | 101 | 108 | 115 | 122 |
9 | 10 | danishzayan 11 |
12 | Danish Kamal 13 |
14 |
16 | 17 | Neesh774 18 |
19 | Kanishq Kancharla 20 |
21 |
23 | 24 | mritul 25 |
26 | Mritul 27 |
28 |
30 | 31 | sourabh053 32 |
33 | Sourabh053 34 |
35 |
37 | 38 | Irjean 39 |
40 | ClémentS 41 |
42 |
44 | 45 | hafeez25 46 |
47 | Hafizur Rahman 48 |
49 |
52 | 53 | racky7 54 |
55 | Raj Chauhan 56 |
57 |
59 | 60 | neupanedipen 61 |
62 | Dipendra Neupane 63 |
64 |
66 | 67 | Eyesnatcher-coder 68 |
69 | Harsh Kanojia 70 |
71 |
73 | 74 | Saran-pariyar 75 |
76 | Saran Pariyar 77 |
78 |
80 | 81 | Satyabrat-Ojha 82 |
83 | Satyabrat Ojha 84 |
85 |
87 | 88 | prateek565 89 |
90 | Prateek565 91 |
92 |
95 | 96 | najeebkp 97 |
98 | Najeeb Thangal KP 99 |
100 |
102 | 103 | 0xPranjl 104 |
105 | Pranjal Maurya 106 |
107 |
109 | 110 | RohanTheProgrammer 111 |
112 | Rohan 113 |
114 |
116 | 117 | hs05june 118 |
119 | Harpreet Singh 120 |
121 |
123 | 124 | -------------------------------------------------------------------------------- /src/components/MainContent.jsx: -------------------------------------------------------------------------------- 1 | //API Details 2 | // 20220912223415 3 | // https://6315b6ef33e540a6d38296a9.mockapi.io/notepad-app 4 | 5 | import React, { useState, useEffect } from "react"; 6 | import { Player } from "@lottiefiles/react-lottie-player"; 7 | import AddNotePopup from "../components/AddNotePopup"; 8 | import CardsList from "../components/CardsList"; 9 | import { nanoid } from "nanoid"; 10 | import axios from "axios"; 11 | import { ToastContainer } from "react-toastify"; 12 | // import Search from "./components/Search"; 13 | import { toast } from "react-toastify"; 14 | import "react-toastify/dist/ReactToastify.css"; 15 | import ScrollToTop from "../components/ScrollToTop"; 16 | import BottomHeader from "../components/BottomHeader"; 17 | 18 | function MainContent({ 19 | addNotePopupIsOpen, 20 | setAddNotePopupIsOpen, 21 | searchText, 22 | darkMode, 23 | handlePopupOpen 24 | }) { 25 | const randomColor1 = Math.floor(Math.random() * 16777215).toString(16); 26 | const randomColor2 = Math.floor(Math.random() * 16777215).toString(16); 27 | const ID = nanoid(); 28 | // console.log("rendering main"); 29 | const [notes, setNotes] = useState([ 30 | { 31 | id: ID, 32 | color1: randomColor1, 33 | color2: randomColor2, 34 | text: "It's YourQuotes-App", 35 | writer: `Writer's name`, 36 | date: "15/06/2021", 37 | }, 38 | ]); 39 | 40 | const [loading, setLoading] = useState(true); 41 | 42 | // read operaton 43 | const getData = () => { 44 | setLoading(true); 45 | axios 46 | .get("https://6315b6ef33e540a6d38296a9.mockapi.io/notepad-app") 47 | .then((res) => { 48 | setLoading(false); 49 | // console.log(res.data); 50 | setNotes(res.data); 51 | }); 52 | }; 53 | 54 | useEffect(() => { 55 | getData(); 56 | }, []); 57 | 58 | const addNote = (text, writer) => { 59 | const date = new Date(); 60 | const newNote = { 61 | id: ID, 62 | color1: randomColor1, 63 | color2: randomColor2, 64 | text: text, 65 | writer: writer, 66 | date: date.toLocaleDateString(), 67 | }; 68 | const newNotes = [...notes, newNote]; 69 | setNotes(newNotes); 70 | // console.log(newNotes); 71 | 72 | //create operation 73 | axios.post( 74 | "https://6315b6ef33e540a6d38296a9.mockapi.io/notepad-app", 75 | newNote 76 | ); 77 | }; 78 | 79 | const deleteNote = (id) => { 80 | const newNotes = notes.filter((note) => note.id !== id); 81 | console.log(newNotes); 82 | console.log(id); 83 | //delete operation 84 | if (true) { 85 | axios.delete( 86 | `https://6315b6ef33e540a6d38296a9.mockapi.io/notepad-app/${id}` 87 | ); 88 | setNotes(newNotes); 89 | } else 90 | toast("📋 This is not YourQutoes", { 91 | position: "top-center", 92 | autoClose: 2000, 93 | hideProgressBar: false, 94 | closeOnClick: true, 95 | pauseOnHover: true, 96 | draggable: true, 97 | progress: undefined, 98 | }); 99 | }; 100 | 101 | 102 | return ( 103 | <> 104 | {loading ? ( 105 |
113 | 120 |
121 | ) : ( 122 |
123 |
124 | 126 | note.text.toUpperCase().includes(searchText.toLocaleUpperCase()) 127 | )} 128 | // we need this to see if the search input is empty 129 | searchText={searchText} 130 | handleAddNote={addNote} 131 | handleDeleteNote={deleteNote} 132 | /> 133 | 144 | 145 |
146 | 147 |
148 |
149 | )} 150 | {addNotePopupIsOpen && ( 151 | 155 | )} 156 | 157 | 158 | ); 159 | } 160 | 161 | export default MainContent; 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YourQuotes-App 📱 2 | 3 | "YourQuotes" is a visually stunning and user-friendly application built with Vite+React. It offers a seamless experience for users to post their favorite quotes, ensuring a streamlined process. Users can effortlessly share quotes with friends, copy them to the clipboard, or download them as gradient images. The app also includes essential features such as a Home feed, Notifications, Bookmarks, and Profile management. Additionally, users can interact with quotes using Like buttons and have the option to edit their own submissions. Exciting features like "Quotes of the Day" provide daily inspiration, while translation capabilities enhance accessibility for a global audience. With its intuitive interface and a myriad of features, YourQuotes is the ultimate destination for quote enthusiasts to engage, express, and inspire. Join us in the journey of sharing wisdom and inspiration with YourQuotes. 4 | 5 | [![Netlify Status](https://api.netlify.com/api/v1/badges/5dc02221-5e8b-406d-a59b-72c0a563baa6/deploy-status)](https://app.netlify.com/sites/your-quotess/deploys) 6 | Number of Visitors 7 | github stars 8 | [![GitHub contributors](https://img.shields.io/github/contributors/danishzayan/YourQuotes-App.svg)](https://GitHub.com/danishzayan/YourQuotes-App/graphs/contributors/) 9 | github forks 10 | [![GitHub commits](https://badgen.net/github/commits/danishzayan/YourQuotes-App)](https://github.com/danishzayan/YourQuotes-App/commit/) 11 | [![GitHub issues](https://img.shields.io/github/issues/danishzayan/YourQuotes-App.svg)](https://GitHub.com/danishzayan/YourQuotes-App/issues/) 12 | [![GitHub issues-closed](https://img.shields.io/github/issues-closed/danishzayan/YourQuotes-App.svg)](https://GitHub.com/danishzayan/YourQuotes-App/issues?q=is%3Aissue+is%3Aclosed) 13 | website up 14 | linkedin 15 | 16 | ## Screenshot of App 📷 17 | 18 | ![alt text](image.png) 19 | 20 | ## Run YourQuotes-App 21 | 22 | ```bash 23 | npm install 24 | ``` 25 | 26 | ```bash 27 | npm run dev 28 | ``` 29 | 30 | # 📜 Quotes Application UI Features 31 | 32 | This application allows users to post, search, listen to, share, copy, download, and manage quotes with ease. Below is a detailed list of features to help contributors understand the current functionality and areas that need further development. 33 | 34 | ## ✅ Completed Features 35 | 36 | - **Quotes Posting** ➕ 37 | - Users can post new quotes by clicking on the plus icon (`+`) at the bottom right corner. 38 | - **Search Functionality** 🔍 39 | - A search bar at the top allows users to search for quotes. 40 | - **Listening to Quotes** 🔊 41 | - Users can listen to quotes using the text-to-speech feature. 42 | - **Sharing Quotes** 📤 43 | - Users can share quotes via a share button. 44 | - **Copying Quotes** 📋 45 | - Users can copy quotes to the clipboard. 46 | - **Downloading Quotes** 📥 47 | - Users can download quotes. 48 | - **Dark Mode** 🌙 49 | - Users can toggle between dark mode and light mode. 50 | 51 | ## 🚧 Pending Features 52 | 53 | - **Pages** 📄 54 | - Home 55 | - Notification 56 | - Add 57 | - Bookmark 58 | - Profile 59 | - **Edit Quotes** ✏️ 60 | - Implement functionality for users to edit existing quotes. 61 | - **User Authentication** 🔐 62 | - Add user login and registration features to personalize the experience. 63 | - **Commenting on Quotes** 💬 64 | - Allow users to add comments on individual quotes. 65 | - **Like Button** 👍 66 | - Implement a feature to allow users to like quotes. 67 | - **Favorites/Bookmarks** 📑 68 | - Allow users to mark quotes as favorites or bookmark them for later reference. 69 | - **Profile Management** 👤 70 | - Add user profile management to track posted quotes and activities. 71 | - **Quote Categories/Tags** 🏷️ 72 | - Enable categorizing or tagging quotes for better organization and searchability. 73 | - **Quote Translations** 🌐 74 | - Provide a feature to translate quotes into different languages. 75 | - **Notification System** 🔔 76 | - Implement notifications for user activities and updates. 77 | - **Social Sharing** 🌐 78 | - Allow users to share quotes on social media platforms. 79 | - **Quote of the Day** 🌅 80 | - Feature a "Quote of the Day" on the homepage. 81 | 83 | - **Analytics Dashboard** 📊 84 | - Provide an analytics dashboard for users to see their quote interactions in profile. 85 | - **User Follow System** ➕👤 86 | - Allow users to follow other users and see their activity. 87 | - **Multimedia Quotes** 🎨 88 | - Enable users to add images or videos to quotes. 89 | - **Quote Collections** 📚 90 | - Allow users to create and share collections of quotes. 91 | - **Offline Mode** 📴 92 | - Provide an offline mode to access quotes without an internet connection. 93 | - **Localization** 🌍 94 | - Support multiple languages for the application interface. 95 | 96 | ## Contributing 👨‍💻 97 | 98 | [![Open Source Love svg1](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/) 99 | 100 | - Contributions make the open source community such an amazing place to learn, inspire, and create. 101 | - Any contributions you make are **greatly appreciated**. 102 | - Check out our [contribution guidelines](/CONTRIBUTING.md) for more information. 103 | 104 | ## License 🛡️ 105 | 106 | YourQuotes-App is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 107 | 108 | ## Contributor Over Time ⏳ 109 | 110 | [![Contributors over time](https://contributor-graph-api.apiseven.com/contributors-svg?chart=contributorOverTime&repo=danishzayan/YourQuotes-App)](https://www.apiseven.com/en/contributor-graph?chart=contributorOverTime&repo=danishzayan/YourQuotes-App) 111 |
112 | 113 | ## Project Contributors 🌟 114 | 115 | Thanks a lot for spending your time helping YourQuotes grow. Thanks a lot! Keep rocking 🎉


116 | 117 | 118 | 119 | 120 | 121 |
122 |

123 | Made in :heart: INDIA and ⭐ Staring the repo.. 124 |

125 | -------------------------------------------------------------------------------- /src/components/Header.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import Search from "../components/Search"; 3 | import LoginButton from "./LoginButton"; 4 | import { Tooltip } from "@mui/material"; 5 | import axios from "axios"; 6 | import { toast, ToastContainer } from "react-toastify"; 7 | 8 | const Header = ({ handleToggleDarkMode, setSearch, darkMode }) => { 9 | const [dark, setDark] = useState(false); 10 | const [user, setUser] = useState(null); 11 | const isLoggedIn = user ? true : false; 12 | useEffect(() => { 13 | if (darkMode) { 14 | setDark(true); 15 | } else { 16 | setDark(false); 17 | } 18 | }, [darkMode]); 19 | 20 | useEffect(()=>{ 21 | if(user){ 22 | toast(`Welcome ${user.name}`, { 23 | position: "top-center", 24 | autoClose: 2000, 25 | hideProgressBar: false, 26 | closeOnClick: true, 27 | pauseOnHover: true, 28 | draggable: true, 29 | progress: undefined, 30 | }); 31 | } 32 | },[isLoggedIn]); 33 | useEffect(() => { 34 | if (localStorage.getItem("token")) { 35 | const access_token = localStorage.getItem("token"); 36 | async function getUser() { 37 | try{ 38 | const res = await axios.get( 39 | "https://www.googleapis.com/oauth2/v3/userinfo", 40 | { 41 | headers: { 42 | Authorization: `Bearer ${access_token}`, 43 | }, 44 | } 45 | ); 46 | setUser(res.data); 47 | }catch(err){ 48 | console.log(err); 49 | } 50 | 51 | } 52 | getUser(); 53 | } 54 | }, []); 55 | 56 | const toggleDarkMode = () => { 57 | handleToggleDarkMode((previousDarkMode) => { 58 | const newDarkMode = !previousDarkMode; 59 | const darkmode = { isDark: newDarkMode }; 60 | localStorage.setItem("darkmode", JSON.stringify(darkmode)); 61 | setDark(newDarkMode); 62 | return newDarkMode; 63 | }); 64 | }; 65 | 66 | return ( 67 | 162 | ); 163 | }; 164 | 165 | export default Header; 166 | -------------------------------------------------------------------------------- /src/components/BottomHeader.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | 3 | const BottomHeader = ({darkMode,handlePopupOpen }) => { 4 | let darkmode = JSON.parse(localStorage.getItem("darkmode")); 5 | const [dark, setDark] = useState(false); 6 | // console.log("rendering bottom "); 7 | 8 | useEffect(() => { 9 | if (darkMode) { 10 | setDark(true); 11 | } else { 12 | setDark(false); 13 | } 14 | }, [darkmode]); 15 | 16 | return ( 17 |
22 |
23 | 39 | 47 | 63 | 71 |
72 | 98 |
99 | 107 | 123 | 131 | 147 | 155 |
156 |
157 | ); 158 | }; 159 | 160 | export default BottomHeader; 161 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | /* Project Name: YourQuotes-App 2 | Date: 07-08-2022 3 | Developer: Danish Kamal */ 4 | 5 | @import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;1,100;1,200;1,300&family=Roboto:ital,wght@0,100;0,300;0,400;1,300;1,400&display=swap"); 6 | @tailwind base; 7 | @tailwind components; 8 | @tailwind utilities; 9 | 10 | 11 | html { 12 | scroll-behavior: smooth; 13 | } 14 | 15 | * { 16 | margin: 0; 17 | padding: 0; 18 | box-sizing: border-box; 19 | font-family: "Poppins", sans-serif; 20 | } 21 | 22 | .body { 23 | background-color: rgb(248, 248, 248); 24 | /* background-image: url("../src/assets/images/background.jpg"); */ 25 | /* background:linear-gradient(rgba(6, 6, 6, 0.243), rgba(255, 255, 0, 0)), url("../src/assets/images/background.jpg"); */ 26 | /* background-image: url("https://www.transparenttextures.com/patterns/cubes.png"), linear-gradient(to right top, #cf4af3, #e73bd7, #f631bc, #fd31a2, #ff3a8b, #ff4b78, #ff5e68, #ff705c, #ff8c51, #ffaa49, #ffc848, #ffe652); */ 27 | /* background-repeat: no-repeat; */ 28 | /* background-size: cover; */ 29 | background-position: center; 30 | background-attachment: fixed; 31 | 32 | } 33 | 34 | .body-dark { 35 | background-color: #120f0f; 36 | /* background-image: url("https://www.transparenttextures.com/patterns/cubes.png"), linear-gradient(to right top, #000000, #000000, #000000, #000000, #000000, #000000, #000000, #000000, #000000, #000000, #000000, #000000); */ 37 | background-position: center; 38 | background-attachment: fixed; 39 | } 40 | 41 | .container { 42 | /* max-width: 960px; */ 43 | width: 100%; 44 | margin: 0 auto; 45 | padding: 25px 20px; 46 | min-height: 100vh; 47 | } 48 | 49 | .add-note-btn { 50 | background-color: tomato; 51 | border-radius: 50%; 52 | width: 50px; 53 | height: 50px; 54 | font-size: 2rem; 55 | border: none; 56 | color: white; 57 | position: fixed; 58 | bottom: 20px; 59 | right: 20px; 60 | cursor: pointer; 61 | } 62 | 63 | .cards-list { 64 | display: grid; 65 | grid-gap: 1rem; 66 | grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); 67 | padding-bottom: 1rem; 68 | } 69 | 70 | .card { 71 | background: linear-gradient(40deg, rgb(101, 48, 146) -200%, rgb(232, 230, 64) 150%); 72 | border-radius: 10px; 73 | border-bottom: 5px solid rgb(255 255 255 / 25%); 74 | padding: 1rem; 75 | min-height: 240px; 76 | display: flex; 77 | flex-direction: column; 78 | justify-content: space-between; 79 | white-space: pre-wrap; 80 | box-shadow: rgb(0 0 0 / 24%) 0px 3px 8px; 81 | } 82 | 83 | .card span { 84 | font-size: 14px; 85 | font-weight: 500; 86 | overflow: hidden; 87 | word-break: break-word; 88 | } 89 | 90 | .card .text { 91 | margin: 0 auto; 92 | } 93 | 94 | .text span { 95 | margin: 0 5px; 96 | text-transform: capitalize; 97 | } 98 | 99 | .card.new { 100 | background: #67e4d8; 101 | border: none; 102 | } 103 | 104 | .popup { 105 | position: fixed; 106 | top: 50%; 107 | left: 50%; 108 | transform: translate(-50%, -50%); 109 | width: 300px; 110 | box-shadow: 0 0 5px 1px #736a6ab5; 111 | z-index: 1; 112 | } 113 | 114 | .popup-title { 115 | font-size: 1.2rem; 116 | margin-bottom: 0.5rem; 117 | color: rgb(56, 56, 56); 118 | text-align: center; 119 | } 120 | 121 | .add-overlay { 122 | opacity: 0.5; 123 | } 124 | 125 | textarea { 126 | background: #67e4d8; 127 | border: none; 128 | resize: none; 129 | border: 1px solid #35c8bab8; 130 | border-radius: 8px; 131 | padding: 5px; 132 | margin-bottom: 0.3rem; 133 | } 134 | 135 | textarea:focus { 136 | outline: none; 137 | } 138 | 139 | .card.new input { 140 | outline: none; 141 | background: #67e4d8; 142 | border: none; 143 | border: 1px solid #35c8bab8; 144 | border-radius: 6px; 145 | padding: 4px; 146 | } 147 | 148 | .footer .save { 149 | color: #fff; 150 | border: none; 151 | padding: 0 15px; 152 | border-radius: 10px; 153 | background-color: #000000; 154 | outline: none; 155 | } 156 | 157 | .footer .save:hover { 158 | cursor: pointer; 159 | background-color: #141414e8; 160 | } 161 | 162 | .footer-writer span { 163 | font-size: 14px; 164 | font-style: italic; 165 | font-weight: 600; 166 | display: flex; 167 | justify-content: end; 168 | text-transform: capitalize; 169 | } 170 | 171 | .footer { 172 | display: flex; 173 | flex-direction: row; 174 | justify-content: space-between; 175 | align-items: center; 176 | background: #ffffff47; 177 | padding: 0 5px; 178 | border-radius: 5px; 179 | border: 1px solid #ffffff1f; 180 | margin-top: 1em; 181 | } 182 | 183 | .card.new .footer { 184 | background: none; 185 | border: none; 186 | } 187 | 188 | .footer small { 189 | font-size: 12px; 190 | font-weight: 500; 191 | } 192 | 193 | .footer .fa-calendar-day:before { 194 | font-size: 14px; 195 | color: black; 196 | margin-right: 5px; 197 | } 198 | 199 | .footer .fa-trash:before { 200 | font-size: 14px; 201 | color: #fb0000; 202 | cursor: pointer; 203 | } 204 | 205 | .footer .fa-copy:before { 206 | content: "\f0c5"; 207 | font-size: 14px; 208 | color: #000000; 209 | cursor: pointer; 210 | margin-right: 10px; 211 | } 212 | 213 | .footer .fa-share:before { 214 | content: "\f064"; 215 | margin-right: 10px; 216 | color: #000000; 217 | cursor: pointer; 218 | font-size: 15px; 219 | } 220 | 221 | .footer .fa-download:before { 222 | margin-right: 10px; 223 | color: #000000; 224 | cursor: pointer; 225 | font-size: 15px; 226 | } 227 | 228 | .footer .fa-volume-up:before { 229 | margin-right: 10px; 230 | color: #000000; 231 | cursor: pointer; 232 | font-size: 15px; 233 | } 234 | 235 | .search { 236 | display: flex; 237 | align-items: center; 238 | color: rgb(0, 0, 0); 239 | background-color: #ffffff; 240 | border: solid 2px #ffffff66; 241 | border-radius: 9px; 242 | padding: 5px 10px; 243 | gap: 0.4rem; 244 | width: 60%; 245 | transition: colors 0.3s ease, width 0.6s ease; 246 | } 247 | 248 | .search:focus-within { 249 | border: solid 2px #ffffff; 250 | caret-color: #ffffff; 251 | width: 75%; 252 | } 253 | 254 | .search input { 255 | border: none; 256 | background-color: white; 257 | width: 100%; 258 | } 259 | 260 | .search input::placeholder { 261 | color: #202020e4; 262 | transition: all 0.3s ease; 263 | } 264 | 265 | .search input:focus::placeholder { 266 | color: #000000; 267 | } 268 | 269 | .search input:focus { 270 | outline: none; 271 | } 272 | 273 | /* Style for header */ 274 | 275 | .header { 276 | display: flex; 277 | flex-direction: row; 278 | justify-content: space-between; 279 | align-items: center; 280 | 281 | background-image: linear-gradient(139deg, #ff4b01, #ee7703, #ff4b01, #ee7703); 282 | margin-bottom: 1em; 283 | padding: 9px 15px; 284 | box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; 285 | position: sticky; 286 | top: 0; 287 | z-index: 100; 288 | width: 100%; 289 | overflow: hidden; 290 | } 291 | 292 | .header-dark { 293 | display: flex; 294 | flex-direction: row; 295 | justify-content: space-between; 296 | align-items: center; 297 | background-image: linear-gradient(139deg, #000a1f, #000000, #060025, #0b0d1f); 298 | margin-bottom: 1em; 299 | padding: 9px 15px; 300 | box-shadow: rgba(202, 197, 197, 0.24) 0px 0px 8px; 301 | color: white; 302 | position: sticky; 303 | top: 0; 304 | z-index: 100; 305 | width: 100%; 306 | overflow: hidden; 307 | } 308 | 309 | .header>.header-top { 310 | display: flex; 311 | flex-direction: row; 312 | justify-content: space-between; 313 | align-items: center; 314 | width: 100%; 315 | } 316 | 317 | .header-dark>.header-top { 318 | display: flex; 319 | flex-direction: row; 320 | justify-content: space-between; 321 | align-items: center; 322 | width: 100%; 323 | } 324 | 325 | .header h1 { 326 | font-size: 25px; 327 | } 328 | 329 | .header-dark h1 { 330 | font-size: 25px; 331 | } 332 | 333 | /* The switch - the box around the slider */ 334 | .switch { 335 | position: relative; 336 | display: inline-block; 337 | width: 50px; 338 | height: 25px; 339 | } 340 | 341 | /* Hide default HTML checkbox */ 342 | .switch input { 343 | opacity: 0; 344 | width: 0; 345 | height: 0; 346 | } 347 | 348 | /* The slider */ 349 | .slider { 350 | position: absolute; 351 | cursor: pointer; 352 | top: 0; 353 | left: 0; 354 | right: 0; 355 | bottom: 0; 356 | background-color: #ccc; 357 | -webkit-transition: 0.4s; 358 | transition: 0.4s; 359 | } 360 | 361 | .slider:before { 362 | position: absolute; 363 | content: ""; 364 | height: 18px; 365 | width: 18px; 366 | left: 4px; 367 | bottom: 4px; 368 | background-color: white; 369 | -webkit-transition: 0.4s; 370 | transition: 0.4s; 371 | } 372 | 373 | input:checked+.slider { 374 | background-color: #2196f3; 375 | } 376 | 377 | input:focus+.slider { 378 | box-shadow: 0 0 1px #2196f3; 379 | } 380 | 381 | input:checked+.slider:before { 382 | -webkit-transform: translateX(26px); 383 | -ms-transform: translateX(26px); 384 | transform: translateX(26px); 385 | } 386 | 387 | /* Rounded sliders */ 388 | .slider.round { 389 | border-radius: 34px; 390 | } 391 | 392 | .slider.round:before { 393 | border-radius: 50%; 394 | } 395 | 396 | /* start style for dark mode */ 397 | /* .dark-mode { 398 | background-color: #000000; 399 | } */ 400 | 401 | .dark-mode h1 { 402 | color: #fff; 403 | } 404 | 405 | .dark-mode h3 { 406 | color: #fff; 407 | } 408 | 409 | /* end style for dark mode */ 410 | 411 | .header-left { 412 | display: flex; 413 | flex-direction: row; 414 | align-items: center; 415 | gap: 2rem; 416 | width: auto; 417 | } 418 | 419 | .header-right { 420 | display: flex; 421 | flex-direction: row; 422 | gap: 2rem; 423 | align-items: center; 424 | justify-content: flex-end; 425 | width: 40%; 426 | } 427 | 428 | .sm-show { 429 | display: none; 430 | } 431 | 432 | /* Start style for responsive */ 433 | @media screen and (max-width: 768px) { 434 | .header { 435 | display: flex; 436 | flex-direction: column; 437 | gap: 0.5rem; 438 | padding-top: 0; 439 | } 440 | 441 | .header-dark { 442 | display: flex; 443 | flex-direction: column; 444 | gap: 0.5rem; 445 | padding-top: 0; 446 | } 447 | 448 | .header>.header-top { 449 | display: flex; 450 | flex-direction: row; 451 | justify-content: space-between; 452 | align-items: center; 453 | width: 100%; 454 | } 455 | 456 | .header-dark>.header-top { 457 | display: flex; 458 | flex-direction: row; 459 | justify-content: space-between; 460 | align-items: center; 461 | width: 100%; 462 | } 463 | 464 | .search { 465 | width: 80%; 466 | } 467 | 468 | .search:focus-within { 469 | width: 100%; 470 | } 471 | 472 | .sm-hide { 473 | display: none; 474 | } 475 | 476 | .sm-show { 477 | display: flex; 478 | } 479 | } 480 | 481 | /* End style for responsive */ 482 | 483 | ::-webkit-scrollbar { 484 | width: 3px; 485 | } 486 | 487 | ::-webkit-scrollbar-thumb { 488 | border-radius: 1px; 489 | -webkit-box-shadow: inset 12px 0 16px #f36b03; 490 | } 491 | 492 | ::-webkit-scrollbar-track { 493 | -webkit-box-shadow: initial 0 0 6px #8e8e8e; 494 | border-radius: 1px; 495 | } --------------------------------------------------------------------------------