diff --git a/package.json b/package.json
index f6879be7..3722dc3c 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"eslint-config-next": "13.2.4",
"eventsource-parser": "^1.0.0",
"next": "13.2.4",
+ "next-themes": "^0.2.1",
"openai": "^3.2.1",
"parse-numeric-range": "^1.3.0",
"react": "18.2.0",
diff --git a/src/components/chat/sidebar/buttons/ThemeButton.tsx b/src/components/chat/sidebar/buttons/ThemeButton.tsx
index be5b5329..9e988b6d 100644
--- a/src/components/chat/sidebar/buttons/ThemeButton.tsx
+++ b/src/components/chat/sidebar/buttons/ThemeButton.tsx
@@ -1,30 +1,30 @@
import React from "react";
import { MdColorLens } from "react-icons/md";
import ButtonContainer from "./ButtonContainer";
+import { useTheme } from "next-themes";
type Props = {};
export default function ThemeButton({}: Props) {
- const [dark, setDark] = React.useState(false);
+ const { theme, setTheme } = useTheme();
+ const [mounted, setMounted] = React.useState(false);
- React.useEffect(() => {
- if (localStorage.theme === "dark") {
- setDark(true);
- } else {
- setDark(false);
- }
- }, []);
+ React.useEffect(() => setMounted(true), []);
const handleThemeChange = () => {
- document.documentElement.classList.toggle("dark");
- localStorage.theme = localStorage.theme === "dark" ? "light" : "dark";
- setDark(!dark);
+ if (theme === "dark") {
+ setTheme("light");
+ } else {
+ setTheme("dark");
+ }
};
+ if (!mounted) return null;
+
return (
- {dark ? "Light" : "Dark"} mode
+ {`${theme === "dark" ? "Light" : "Dark"} mode`}
);
}
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 987a0eb9..31741559 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -3,30 +3,19 @@ import OpenAIProvider from "@/context/OpenAIProvider";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { Analytics } from "@vercel/analytics/react";
+import { ThemeProvider } from "next-themes";
export default function App({ Component, pageProps }: AppProps) {
- if (typeof window !== "undefined") {
- const isDarkSet = localStorage.theme === "dark";
- const isThemeStored = "theme" in localStorage;
- const isDarkPrefered = window.matchMedia(
- "(prefers-color-scheme: dark)"
- ).matches;
-
- if (isDarkSet || (!isThemeStored && isDarkPrefered)) {
- document.documentElement.classList.add("dark");
- } else {
- document.documentElement.classList.remove("dark");
- }
- }
-
return (
<>
-
-
-
-
-
-
+
+
+
+
+
+
+
+
>
);
}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index ac3ad5dc..663601ee 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -10,7 +10,7 @@
--bg-tertiary: 209, 213, 219;
}
- .dark {
+ .dark, [data-theme="dark"] {
--text-primary: 255, 255, 255;
--bg-primary: 17, 24, 39;
--bg-secondary: 31, 41, 55;
diff --git a/yarn.lock b/yarn.lock
index e0f96d6d..e43ed3cf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2292,6 +2292,11 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+next-themes@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45"
+ integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==
+
next@13.2.4:
version "13.2.4"
resolved "https://registry.yarnpkg.com/next/-/next-13.2.4.tgz#2363330392b0f7da02ab41301f60857ffa7f67d6"