I use vanilla extract like this
/** layout.tsx */
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const cookieStore = cookies();
const theme = cookieStore.get("theme");
return (
<html lang="ko-KR">
<link rel="icon" href="/favicon.ico" sizes="any" />
<body className={theme?.value === "light" ? ligthTheme : darkTheme}>
<Topbar />
<div className={styles.mainContentContainer}>
<main className={styles.mainContent}>
{children}
<Footer />
</main>
</div>
<BottomBar />
</body>
</html>
);
}
And dark and light theme code is like this
/** theme.css.ts */
import {
createGlobalTheme,
createThemeContract,
createTheme,
} from "@vanilla-extract/css";
import { white, grey } from "../colors.css";
const root = createGlobalTheme("#root", {});
const themeColor = createThemeContract({
fontColor: {
textColor: null,
accentColor: null,
subColor: null,
accentSubColor: null,
middleAccentColor: null,
},
buttonColor: {
notActiveColor: null,
activeColor: null,
},
backgroundColor: {
bodyColor: null,
accentColor: null,
navbarColor: null,
textBoxColor: null,
glassGradientColorTop: null,
glassGradientColorBottom: null,
},
boxColor: {
notHoverColor: null,
hoverColor: null,
},
borderColor: {
notHoverColor: null,
hoverColor: null,
},
});
export const ligthTheme = createTheme(themeColor, {
fontColor: {
textColor: grey[300],
subColor: white[500],
accentSubColor: white[500],
middleAccentColor: grey[200],
accentColor: "black",
},
buttonColor: {
notActiveColor: white[500],
activeColor: "black",
},
backgroundColor: {
bodyColor: white[100],
accentColor: white[200],
navbarColor: "rgba(" + white[100] + ", 0.8)",
glassGradientColorTop: `linear-gradient(to top, rgba(245,245,245,0) 0%, rgba(245,245,245,1) 100%)`,
glassGradientColorBottom: `linear-gradient(to top, rgba(245,245,245,1) 0%, rgba(245,245,245,0) 100%)`,
textBoxColor: white[300],
},
boxColor: {
notHoverColor: white[200],
hoverColor: white[300],
},
borderColor: {
notHoverColor: white[400],
hoverColor: grey[100],
},
});
export const darkTheme = createTheme(themeColor, {
fontColor: {
textColor: white[100],
subColor: grey[300],
accentColor: "white",
accentSubColor: grey[200],
middleAccentColor: white[200],
},
buttonColor: {
notActiveColor: grey[100],
activeColor: white[100],
},
backgroundColor: {
bodyColor: grey[500],
accentColor: grey[400],
navbarColor: "rgba(" + grey[500] + ", 0.8)",
glassGradientColorTop: `linear-gradient(to top, rgba(16,16,16,0) 0%, rgba(16,16,16, 1) 100%)`,
glassGradientColorBottom: `linear-gradient(to top, rgba(16,16,16,1) 0%, rgba(16,16,16,0) 100%)`,
textBoxColor: grey[300],
},
boxColor: {
notHoverColor: grey[400],
hoverColor: grey[100],
},
borderColor: {
notHoverColor: grey[200],
hoverColor: white[300],
},
});
import { keyframes } from "@vanilla-extract/css";
export const blink = keyframes({
"0%": {
opacity: 0,
},
"50%": {
opacity: 0.7,
},
"100%": {
opacity: 0,
},
});
export const vars = { ...root, themeColor, blink };
And I save the theme on cookie
/** ToggleBtn.tsx */
import { moon } from "../icon/moon";
import { sun } from "../icon/sun";
import { cookies } from "next/headers";
import { toggleBtn } from "./ToggleBtn.css";
import SVGmorph from "./SVGmorph";
export default function ToggleBtn() {
const theme = cookies().get("theme");
const handleTheme = async () => {
"use server";
if (theme?.value === "dark" || !theme?.value) {
cookies().set("theme", "light");
} else {
cookies().set("theme", "dark");
}
};
return (
<form action={handleTheme}>
<button className={toggleBtn}>
<svg
width="28"
height="28"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<SVGmorph paths={[sun, moon, sun]} theme={theme?.value || "dark"} />
</svg>
</button>
</form>
);
}
But it take 1.5 sec at least to change theme. And it is worse on the post page
Is the way I use it wrong?
What is the problem with my code?
github: https://github.com/22JH/blog published url : https://www.joo-dev.com/
I tried deleting svgMorph, but it's still slow...