From 01b2471a70af14d1666262895e1886497f032e0a Mon Sep 17 00:00:00 2001 From: buddywinte Date: Mon, 15 Jun 2026 16:08:48 -0500 Subject: [PATCH 01/10] ThemeProvider --- package-lock.json | 11 +++++++++++ package.json | 1 + pages/_app.tsx | 48 ++++++++++++++++++++++++++--------------------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index a34ac799..8d0380a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "moment": "^2.30.1", "moment-timezone": "^0.6.1", "next": "^16.2.6", + "next-themes": "^0.4.6", "noblox.js": "^7.3.1", "node-cache": "^5.1.2", "node-cron": "^4.2.1", @@ -9710,6 +9711,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/package.json b/package.json index ab5110a5..bce1ab9c 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "moment": "^2.30.1", "moment-timezone": "^0.6.1", "next": "^16.2.6", + "next-themes": "^0.4.6", "noblox.js": "^7.3.1", "node-cache": "^5.1.2", "node-cron": "^4.2.1", diff --git a/pages/_app.tsx b/pages/_app.tsx index 67b96ebe..6e436489 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -26,6 +26,7 @@ import { loginState } from "@/state"; import { getRGBFromTailwindColor, DEFAULT_THEME_RGB } from "@/utils/themeColor"; import LoadingScreen from "@/components/loading"; import { Toaster } from "react-hot-toast"; +import { ThemeProvider } from "next-themes"; const POSTHOG_KEY = process.env.NEXT_PUBLIC_POSTHOG_KEY; const POSTHOG_HOST = @@ -127,27 +128,32 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) { return ( - - Orbit - - - - - - - - - - {showLoader && } - - {!showLoader && ( - -
- - -
-
- )} + + + Orbit + + + + + + + + + + {showLoader && } + + {!showLoader && ( + +
+ + +
+
+ )} +
); } From 35163a7b3f25fe715a227eae108c2fdac28a3078 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Mon, 15 Jun 2026 16:10:34 -0500 Subject: [PATCH 02/10] fix ColorThemeHandler to handle correctly --- pages/_app.tsx | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index 6e436489..f80f2f38 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -26,7 +26,8 @@ import { loginState } from "@/state"; import { getRGBFromTailwindColor, DEFAULT_THEME_RGB } from "@/utils/themeColor"; import LoadingScreen from "@/components/loading"; import { Toaster } from "react-hot-toast"; -import { ThemeProvider } from "next-themes"; +import { ThemeProvider, useTheme } from "next-themes"; + const POSTHOG_KEY = process.env.NEXT_PUBLIC_POSTHOG_KEY; const POSTHOG_HOST = @@ -47,24 +48,14 @@ ChartJS.register( LineElement, ); -function ThemeHandler() { - const theme = useRecoilValue(themeState); - - useEffect(() => { - if (!theme) return; - document.documentElement.classList.remove("light", "dark"); - document.documentElement.classList.add(theme as string); - }, [theme]); - - return null; -} - function ColorThemeHandler() { const [workspace] = useRecoilState(workspacestate); - const theme = useRecoilValue(themeState); + const { theme, setTheme, systemTheme } = useTheme(); useEffect(() => { - const isDark = theme === "dark"; + //const isDark = theme === "dark"; + const { resolvedTheme } = useTheme(); + const isDark = resolvedTheme === "dark"; const darkTheme = (workspace as any)?.groupDarkTheme; const lightTheme = workspace?.groupTheme; From de6c37bcb94f8ea93ab2907d67c97c8a6c53e590 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Mon, 15 Jun 2026 16:10:57 -0500 Subject: [PATCH 03/10] whoops - might be smart to remove the ThemeHandle --- pages/_app.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index f80f2f38..64b7bf03 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -131,7 +131,6 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) { - {showLoader && } From 3b1832e7e49428b343399abc553638c798c70bd0 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Mon, 15 Jun 2026 16:39:57 -0500 Subject: [PATCH 04/10] topbar patch; also forgot useTheme cannot be in effect --- components/topbar.tsx | 18 ++++++++---------- pages/_app.tsx | 2 +- state/theme.ts | 17 ----------------- 3 files changed, 9 insertions(+), 28 deletions(-) delete mode 100644 state/theme.ts diff --git a/components/topbar.tsx b/components/topbar.tsx index 989615c5..46774c67 100644 --- a/components/topbar.tsx +++ b/components/topbar.tsx @@ -4,6 +4,7 @@ import { loginState } from "@/state"; import { useRecoilState } from "recoil"; import { Menu } from "@headlessui/react"; import Router, { useRouter } from "next/router"; +import { useTheme } from "next-themes"; import { IconLogout, IconChevronDown, @@ -19,7 +20,6 @@ import { } from "@tabler/icons-react"; import axios from "axios"; import { Fragment, useEffect, useRef, useState } from "react"; -import { themeState } from "@/state/theme"; import toast from "react-hot-toast"; import { DiscordOAuthAvailable } from "@/hooks/useDiscordOAuth"; import { GoogleOAuthAvailable } from "@/hooks/useGoogleOAuth"; @@ -48,7 +48,7 @@ type Panel = "main" | "settings" | "sessions"; const Topbar: NextPage = () => { const [login, setLogin] = useRecoilState(loginState); - const [theme, setTheme] = useRecoilState(themeState); + const {theme, setTheme, resolvedTheme} = useTheme(); const { isAvailable: isDiscordOAuth } = DiscordOAuthAvailable(); const { isAvailable: isGoogleOAuth } = GoogleOAuthAvailable(); const [open, setOpen] = useState(false); @@ -58,6 +58,10 @@ const Topbar: NextPage = () => { const router = useRouter(); const errorToastShown = useRef(false); + const toggleTheme = () => { + setTheme(resolvedTheme === "dark" ? "light" : "dark"); + }; + const openPanel = (p: Panel) => setPanel(p); const handleOpen = () => { @@ -143,12 +147,6 @@ const Topbar: NextPage = () => { } } - const toggleTheme = () => { - const t = theme === "dark" ? "light" : "dark"; - setTheme(t); - if (typeof window !== "undefined") localStorage.setItem("theme", t); - }; - useEffect(() => { if (!Router.isReady || errorToastShown.current) return; const { action, ...rest } = Router.query; @@ -255,12 +253,12 @@ const Topbar: NextPage = () => { onClick={toggleTheme} className="w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-zinc-700/60 transition-colors text-left" > - {theme === "dark" ? ( + {resolvedTheme === "dark" ? ( ) : ( )} - {theme === "dark" ? "Light mode" : "Dark mode"} + {resolvedTheme === "dark" ? "Light mode" : "Dark mode"} )} From fa24ca393c8b71460ccbf1417d3103c7e797b244 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Mon, 15 Jun 2026 16:50:42 -0500 Subject: [PATCH 06/10] activityoverview page! --- components/ThemeToggle.tsx | 14 ++++++-------- components/profile/activityoverview.tsx | 7 +++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/components/ThemeToggle.tsx b/components/ThemeToggle.tsx index 3d57e030..ad9d3919 100644 --- a/components/ThemeToggle.tsx +++ b/components/ThemeToggle.tsx @@ -1,14 +1,12 @@ -import { useRecoilState } from "recoil"; -import { themeState } from "@/state/theme"; +import { useTheme } from "next-themes"; import { MoonIcon, SunIcon } from "@heroicons/react/24/outline"; const ThemeToggle = () => { - const [theme, setTheme] = useRecoilState(themeState); + const { theme, setTheme, resolvedTheme } = useTheme(); const toggleTheme = () => { - const newTheme = theme === "dark" ? "light" : "dark"; - setTheme(newTheme); - localStorage.setItem("theme", newTheme); + const current = resolvedTheme ?? theme; + setTheme(current === "dark" ? "light" : "dark"); }; return ( @@ -17,7 +15,7 @@ const ThemeToggle = () => { className="p-2 rounded-full bg-zinc-200 dark:bg-zinc-700 transition hover:scale-105" title="Toggle theme" > - {theme === "dark" ? ( + {(resolvedTheme ?? theme) === "dark" ? ( ) : ( @@ -26,4 +24,4 @@ const ThemeToggle = () => { ); }; -export default ThemeToggle; +export default ThemeToggle; \ No newline at end of file diff --git a/components/profile/activityoverview.tsx b/components/profile/activityoverview.tsx index 5deae478..cb894e1c 100644 --- a/components/profile/activityoverview.tsx +++ b/components/profile/activityoverview.tsx @@ -9,6 +9,7 @@ import { useRouter } from "next/router"; import axios from "axios"; import toast from "react-hot-toast"; import { Line } from "react-chartjs-2"; +import { useTheme } from "next-themes"; import { Chart as ChartJS, CategoryScale, @@ -28,8 +29,6 @@ import { IconClipboardList, IconClock, } from "@tabler/icons-react"; -import { useRecoilValue } from "recoil"; -import { themeState } from "@/state/theme"; import moment from "moment"; import type { ActivitySession, inactivityNotice } from "@prisma/client"; @@ -99,8 +98,8 @@ export function ActivityOverview({ const [loading, setLoading] = useState(true); const liveSessionTimerRef = useRef(null); - const theme = useRecoilValue(themeState); - const isDark = theme === "dark"; + const { resolvedTheme } = useTheme(); + const isDark = resolvedTheme === "dark"; const sortedTimeline = useMemo(() => { return [...timeline].sort((a, b) => { From 7a014defbd62b184b8fddbe4b8851c117b4ae2a5 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Tue, 16 Jun 2026 05:51:40 -0500 Subject: [PATCH 07/10] idk what to title this --- pages/api/workspace/[id]/activity/users.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/workspace/[id]/activity/users.ts b/pages/api/workspace/[id]/activity/users.ts index 9bba3017..ab6dc5ee 100644 --- a/pages/api/workspace/[id]/activity/users.ts +++ b/pages/api/workspace/[id]/activity/users.ts @@ -200,7 +200,7 @@ export async function handler(req: AuthenticatedRequest, res: NextApiResponse Date: Tue, 16 Jun 2026 05:51:49 -0500 Subject: [PATCH 08/10] no title --- pages/api/@me.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/api/@me.ts b/pages/api/@me.ts index 82b2c2ac..107d055b 100644 --- a/pages/api/@me.ts +++ b/pages/api/@me.ts @@ -1,7 +1,6 @@ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type { NextApiRequest, NextApiResponse } from 'next' import prisma from '@/utils/database'; -// import { withAuth } from '@/lib/withSession' import { getUsername, getThumbnail, getDisplayName } from '@/utils/userinfoEngine' import * as noblox from 'noblox.js' import { AuthenticatedRequest, withAuth } from '@/lib/withAuth'; From 0098090df2271c48e505f1dbf0a291009cbd9533 Mon Sep 17 00:00:00 2001 From: buddywinte Date: Tue, 16 Jun 2026 05:54:31 -0500 Subject: [PATCH 09/10] Fixed mobile to use resolvedTheme --- components/sidebar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/sidebar.tsx b/components/sidebar.tsx index 5aa62207..06d4343a 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -810,8 +810,8 @@ const Sidebar: NextPage = ({ isCollapsed, setIsCollapsed }) => { style={{ WebkitTapHighlightColor: "transparent" }} className="w-full flex items-center gap-3 px-4 py-3.5 text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-50 dark:hover:bg-zinc-800/60 transition-colors select-none outline-none" > - {theme === "dark" ? : } - {theme === "dark" ? "Light mode" : "Dark mode"} + {resolvedTheme === "dark" ? : } + {resolvedTheme === "dark" ? "Light mode" : "Dark mode"}