feat: initial dark theme switch component

This commit is contained in:
Peter Carl Pardo
2024-12-15 23:11:50 +08:00
parent 1cf7df1ac6
commit 55225ad221
4 changed files with 222 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
import "./index.css";
const SunAndMoonIcon = () => {
return (
<svg
className="sun-and-moon"
aria-hidden="true"
width="24"
height="24"
viewBox="0 0 24 24"
>
<mask
className="moon"
id="moon-mask"
>
<rect
x="0"
y="0"
width="100%"
height="100%"
fill="white"
/>
<circle
cx="24"
cy="10"
r="6"
fill="black"
/>
</mask>
<circle
className="sun"
cx="12"
cy="12"
r="6"
fill="currentColor"
mask="url(#moon-mask)"
/>
<g
className="sun-beams"
stroke="currentColor"
>
<line
x1="12"
y1="1"
x2="12"
y2="3"
/>
<line
x1="12"
y1="21"
x2="12"
y2="23"
/>
<line
x1="4.22"
y1="4.22"
x2="5.64"
y2="5.64"
/>
<line
x1="18.36"
y1="18.36"
x2="19.78"
y2="19.78"
/>
<line
x1="1"
y1="12"
x2="3"
y2="12"
/>
<line
x1="21"
y1="12"
x2="23"
y2="12"
/>
<line
x1="4.22"
y1="19.78"
x2="5.64"
y2="18.36"
/>
<line
x1="18.36"
y1="5.64"
x2="19.78"
y2="4.22"
/>
</g>
</svg>
);
};
export default SunAndMoonIcon;

View File

@@ -0,0 +1,77 @@
.sun-and-moon > :is(.moon, .sun, .sun-beams) {
transform-origin: center;
}
.sun-and-moon > :is(.moon, .sun) {
fill: var(--icon-fill);
}
.theme-toggle:is(:hover, :focus-visible) > .sun-and-moon > :is(.moon, .sun) {
fill: var(--icon-fill-hover);
}
.sun-and-moon > .sun-beams {
stroke: var(--icon-fill);
stroke-width: 2px;
}
.theme-toggle:is(:hover, :focus-visible) .sun-and-moon > .sun-beams {
stroke: var(--icon-fill-hover);
}
[data-theme="dark"] .sun-and-moon > .sun {
transform: scale(1.75);
}
[data-theme="dark"] .sun-and-moon > .sun-beams {
opacity: 0;
}
[data-theme="dark"] .sun-and-moon > .moon > circle {
transform: translateX(-7px);
}
@supports (cx: 1) {
[data-theme="dark"] .sun-and-moon > .moon > circle {
cx: 17;
transform: translateX(0);
}
}
@media (prefers-reduced-motion: no-preference) {
.sun-and-moon > .sun {
transition: transform 0.5s var(--ease-elastic-3);
}
.sun-and-moon > .sun-beams {
transition:
transform 0.5s var(--ease-elastic-4),
opacity 0.5s var(--ease-3);
}
.sun-and-moon .moon > circle {
transition: transform 0.25s var(--ease-out-5);
}
@supports (cx: 1) {
.sun-and-moon .moon > circle {
transition: cx 0.25s var(--ease-out-5);
}
}
[data-theme="dark"] .sun-and-moon > .sun {
transition-timing-function: var(--ease-3);
transition-duration: 0.25s;
transform: scale(1.75);
}
[data-theme="dark"] .sun-and-moon > .sun-beams {
transition-duration: 0.15s;
transform: rotateZ(-25deg);
}
[data-theme="dark"] .sun-and-moon > .moon > circle {
transition-duration: 0.5s;
transition-delay: 0.25s;
}
}

View File

@@ -0,0 +1,49 @@
import React, { useEffect, useState } from "react";
// import "./index.css";
import { IconButton } from "@mui/material";
import SunAndMoonIcon from "./SunAndMoonIcon";
// import SunAndMoonIcon from "./SunAndMoonIcon";
const ThemeSwitch = () => {
const [currentTheme, setCurrentTheme] = useState("light");
const toggleTheme = () =>
setCurrentTheme((prevState) => (prevState === "light" ? "dark" : "light"));
useEffect(() => {
document.body.setAttribute("data-theme", currentTheme);
console.log(currentTheme);
}, [currentTheme]);
return (
<IconButton
id="theme-toggle"
title="Toggles light & dark"
aria-label="auto"
aria-live="polite"
onClick={toggleTheme}
sx={{
width: 48,
height: 48,
display: "flex",
alignItems: "center",
justifyContent: "center",
// "& .sun-and-moon": {
// transformOrigin: "center",
// },
// "& .sun": {
// fill: "var(--icon-fill)",
// transition: "transform 0.5s ease",
// ...(currentTheme === "dark" && { transform: "scale(1.75)" }),
// },
// "& .moon > circle": {
// transform: currentTheme === "dark" ? "translateX(-7px)" : "none",
// transition: "transform 0.25s ease",
// },
}}
>
<SunAndMoonIcon />
</IconButton>
);
};
export default ThemeSwitch;

View File

@@ -1,4 +1,5 @@
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");
@import "https://unpkg.com/open-props/easings.min.css";
* {
box-sizing: border-box;