colorTheme toggle done.

This commit is contained in:
yousifpa98
2024-12-22 00:19:37 +01:00
parent b6a5b5959d
commit 53c1b3c98a
7 changed files with 309 additions and 42 deletions

127
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.2",
"styled-components": "^6.1.13",
"vite-plugin-svgr": "^4.3.0"
},
"devDependencies": {
@@ -287,6 +288,24 @@
"node": ">=6.9.0"
}
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
},
"node_modules/@emotion/memoize": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
@@ -1413,6 +1432,11 @@
"@types/react": "^18.0.0"
}
},
"node_modules/@types/stylis": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
"integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw=="
},
"node_modules/@vitejs/plugin-react": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz",
@@ -1751,6 +1775,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/camelize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
"integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001690",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
@@ -1870,11 +1902,28 @@
"node": ">= 8"
}
},
"node_modules/css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
"integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
"engines": {
"node": ">=4"
}
},
"node_modules/css-to-react-native": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
"integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
"dependencies": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
"postcss-value-parser": "^4.0.2"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/data-view-buffer": {
"version": "1.0.1",
@@ -3678,6 +3727,11 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -3974,6 +4028,11 @@
"node": ">= 0.4"
}
},
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4188,6 +4247,70 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/styled-components": {
"version": "6.1.13",
"resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz",
"integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==",
"dependencies": {
"@emotion/is-prop-valid": "1.2.2",
"@emotion/unitless": "0.8.1",
"@types/stylis": "4.2.5",
"css-to-react-native": "3.2.0",
"csstype": "3.1.3",
"postcss": "8.4.38",
"shallowequal": "1.1.0",
"stylis": "4.3.2",
"tslib": "2.6.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/styled-components"
},
"peerDependencies": {
"react": ">= 16.8.0",
"react-dom": ">= 16.8.0"
}
},
"node_modules/styled-components/node_modules/postcss": {
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/styled-components/node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/stylis": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",

View File

@@ -15,6 +15,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.2",
"styled-components": "^6.1.13",
"vite-plugin-svgr": "^4.3.0"
},
"devDependencies": {

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M223.5 32C100 32 0 132.3 0 256S100 480 223.5 480c60.6 0 115.5-24.2 155.8-63.4c5-4.9 6.3-12.5 3.1-18.7s-10.1-9.7-17-8.5c-9.8 1.7-19.8 2.6-30.1 2.6c-96.9 0-175.5-78.8-175.5-176c0-65.8 36-123.1 89.3-153.3c6.1-3.5 9.2-10.5 7.7-17.3s-7.3-11.9-14.3-12.5c-6.3-.5-12.6-.8-19-.8z"/></svg>

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc. --><path d="M361.5 1.2c5 2.1 8.6 6.6 9.6 11.9L391 121l107.9 19.8c5.3 1 9.8 4.6 11.9 9.6s1.5 10.7-1.6 15.2L446.9 256l62.3 90.3c3.1 4.5 3.7 10.2 1.6 15.2s-6.6 8.6-11.9 9.6L391 391 371.1 498.9c-1 5.3-4.6 9.8-9.6 11.9s-10.7 1.5-15.2-1.6L256 446.9l-90.3 62.3c-4.5 3.1-10.2 3.7-15.2 1.6s-8.6-6.6-9.6-11.9L121 391 13.1 371.1c-5.3-1-9.8-4.6-11.9-9.6s-1.5-10.7 1.6-15.2L65.1 256 2.8 165.7c-3.1-4.5-3.7-10.2-1.6-15.2s6.6-8.6 11.9-9.6L121 121 140.9 13.1c1-5.3 4.6-9.8 9.6-11.9s10.7-1.5 15.2 1.6L256 65.1 346.3 2.8c4.5-3.1 10.2-3.7 15.2-1.6zM160 256a96 96 0 1 1 192 0 96 96 0 1 1 -192 0zm224 0a128 128 0 1 0 -256 0 128 128 0 1 0 256 0z"/></svg>

After

Width:  |  Height:  |  Size: 902 B

View File

@@ -1,17 +1,110 @@
import React from "react";
import React, { useState, useEffect } from "react";
import "../css/Switch.css";
import { useState } from "react";
import "animate.css";
import styled from "styled-components";
import SunIcon from "../assets/icons/colorModeToggle/sun.svg?react";
import MoonIcon from "../assets/icons/colorModeToggle/moon.svg?react";
const SwitchBtn = styled.button`
background-color: ${(props) =>
props.colormode === "dark" ? "#000767" : "#009d28"};
border: 1px solid
${(props) => (props.colormode === "dark" ? "#f6f1d5" : "#fff145")};
border-radius: 99px;
width: 50px;
height: 28px;
cursor: pointer;
transition: background-color 0.3s ease, border-color 0.3s ease;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.748);
position: relative;
`;
const SwitchContainer = styled.div`
transition: background-color 1s ease;
grid-area: 8 / 4 / 10 / 5;
background-color: ${(props) =>
props.colormode === "dark" ? "#131862" : "#69d0ff"};
display: flex;
align-items: flex-end;
justify-content: center;
border: 1px solid
${(props) => (props.colormode === "dark" ? "#1e2be0" : "#9bdfff")};
position: relative;
`;
const StyledSunIcon = styled(SunIcon)`
fill: #fff145;
`;
const StyledMoonIcon = styled(MoonIcon)`
fill: #f6f1d5;
`;
const PlanetsContainer = styled.div`
transition: transform 0.5s ease-in-out;
transform: ${(props) => `rotate(${props.rotation}deg)`};
`;
const Switch = ({ initialAnimation, onMouseEnter, onAnimationEnd }) => {
const [animation, setAnimation] = useState(initialAnimation);
const [colormode, setcolormode] = useState(() => {
// Retrieve initial color mode from localStorage or default to "dark"
return localStorage.getItem("colormode") || "dark";
});
const [rotation, setRotation] = useState(0);
useEffect(() => {
// Save the current color mode to localStorage whenever it changes
localStorage.setItem("colormode", colormode);
}, [colormode]);
const toggleColorMode = () => {
setcolormode((prevMode) => (prevMode === "dark" ? "light" : "dark"));
setRotation((prevRotation) => prevRotation + 90);
};
return (
<div
className={`switch container animate__animated ${animation}`}
<SwitchContainer
colormode={colormode}
className={`container animate__animated ${animation}`}
onAnimationEnd={() => onAnimationEnd(setAnimation)}
>
switch
<div className="wrapper">
<PlanetsContainer rotation={rotation} className="planets">
<StyledSunIcon
colormode={colormode}
className={`sun1 toggleIcon ${
colormode === "dark" ? "setting" : "rising"
}`}
/>
<StyledMoonIcon
colormode={colormode}
className={`moon1 toggleIcon ${
colormode === "dark" ? "rising" : "setting"
}`}
/>
<StyledSunIcon
colormode={colormode}
className={`sun2 toggleIcon ${
colormode === "dark" ? "setting" : "rising"
}`}
/>
<StyledMoonIcon
colormode={colormode}
className={`moon2 toggleIcon ${
colormode === "dark" ? "rising" : "setting"
}`}
/>
</PlanetsContainer>
</div>
<SwitchBtn
colormode={colormode}
className={`colormodeBtn ${colormode}Btn`}
onClick={toggleColorMode}
>
<div className={`colorToggleThumb ${colormode}`}></div>
</SwitchBtn>
</SwitchContainer>
);
};

View File

@@ -10,8 +10,24 @@
justify-content: center;
}
.imgs img:first-child {
border-radius: 8px 0 0 8px;
}
.imgs img:last-child {
border-radius: 0 8px 8px 0;
}
.imgs img {
height: 55%;
object-fit: contain;
}
.img img {
width: 100%;
border-radius: 8px;
height: 55%;
object-fit: contain;
}
.img img,

View File

@@ -1,38 +1,70 @@
.switch {
grid-area: 8 / 4 / 10 / 5;
}
.switch-container {
display: inline-block;
position: relative;
}
.switch-checkbox {
display: none;
}
.switch-label {
display: block;
width: 50px;
height: 24px;
border-radius: 34px;
position: relative;
cursor: pointer;
transition: background-color 0.2s;
}
.switch-label .switch-button {
display: block;
width: 20px;
height: 20px;
background: #fff;
border-radius: 50%;
.wrapper {
overflow: hidden;
height: 100%;
width: 100%;
position: absolute;
top: 2px;
left: 2px;
transition: transform 0.2s;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
.switch-checkbox:checked + .switch-label .switch-button {
transform: translateX(26px);
.toggleIcon {
position: absolute;
width: 2rem;
height: auto;
}
.colorToggleThumb {
height: 20px;
width: 20px;
background-color: #fff;
border-radius: 99px;
transform: translateX(0);
transition: left 0.3s ease;
position: absolute;
left: 3px;
top: 50%;
transform: translateY(-50%);
}
.colorToggleThumb.dark {
left: calc(50px - 25px);
}
.planets {
position: absolute;
/* border: 1px solid white; */
width: 300px;
height: 300px;
top: 0;
left: -80%;
}
/* Top corner */
.moon1 {
top: 10px;
left: 50%;
transform: translateX(-50%);
}
/* Right corner */
.sun2 {
top: 50%;
right: 10px;
transform: translateY(-50%);
fill: aqua;
}
/* Bottom corner */
.moon2 {
bottom: 10px;
left: 50%;
transform: translateX(-50%);
}
/* Left corner */
.sun1 {
top: 50%;
left: 10px;
transform: translateY(-50%);
}