diff --git a/website/src/app/layout.tsx b/website/src/app/layout.tsx index aa322c4..27b13e3 100644 --- a/website/src/app/layout.tsx +++ b/website/src/app/layout.tsx @@ -1,4 +1,3 @@ -import { CssBaseline } from "@mui/material"; import "../styles/globals.css"; import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter"; import localFont from "next/font/local"; @@ -26,7 +25,7 @@ export default function RootLayout({ children: React.ReactNode; }) { return ( - + {/* */} - + {/* */} {children} diff --git a/website/src/app/page.tsx b/website/src/app/page.tsx index 9760cf8..8f0fe2a 100644 --- a/website/src/app/page.tsx +++ b/website/src/app/page.tsx @@ -4,7 +4,7 @@ import { LandingPageLayout } from "@/components/layout"; import { FilterProvider } from "@/components/layout/filterContext"; import { SearchInput } from "@/components/searchInput"; import { Box, Typography, Link } from "@mui/material"; - +import type {} from "@mui/material/themeCssVarsAugmentation"; import localFont from "next/font/local"; import { Suspense } from "react"; @@ -35,7 +35,7 @@ export default function Home() { fontVariantLigatures: "normal", }} > - Noogλe :: 2024 + Noogλe diff --git a/website/src/components/ClientSideLayoutContext.tsx b/website/src/components/ClientSideLayoutContext.tsx index 2f2d850..4d3d937 100644 --- a/website/src/components/ClientSideLayoutContext.tsx +++ b/website/src/components/ClientSideLayoutContext.tsx @@ -1,28 +1,56 @@ "use client"; -import { - CssBaseline, - ThemeProvider, - createTheme, - useMediaQuery, -} from "@mui/material"; -import { darkThemeOptions, lightThemeOptions } from "@/styles/theme"; -import { ReactNode } from "react"; +import { CssBaseline, useMediaQuery } from "@mui/material"; +import { cssThemeOptions } from "@/styles/theme"; +import { ReactNode, useEffect, useState } from "react"; import { Toaster } from "react-hot-toast"; +import { + Experimental_CssVarsProvider as CssVarsProvider, + experimental_extendTheme as extendTheme, + getInitColorSchemeScript, + useColorScheme, +} from "@mui/material/styles"; + +const theme = extendTheme(cssThemeOptions); + +const ModeTracker = () => { + const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)"); + const { setMode } = useColorScheme(); + + const [mounted, setMounted] = useState(false); -const darkTheme = createTheme(darkThemeOptions); -const lightTheme = createTheme(lightThemeOptions); + useEffect( + () => { + setMounted(true); + + setMode(userPrefersDarkmode ? "dark" : "light"); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [userPrefersDarkmode] + ); + + if (!mounted) { + // for server-side rendering + // learn more at https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch + return null; + } + + return <>; +}; export const ClientSideLayoutContext = ({ children, }: { children: ReactNode; }) => { - const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)"); return ( - - - - {children} - + <> + {getInitColorSchemeScript()} + + + + + {children} + + ); }; diff --git a/website/src/components/HighlightBaseline.tsx b/website/src/components/HighlightBaseline.tsx index c79eeb9..8f2121d 100644 --- a/website/src/components/HighlightBaseline.tsx +++ b/website/src/components/HighlightBaseline.tsx @@ -1,17 +1,18 @@ "use client"; -import { useTheme } from "@mui/material"; +import { useColorScheme } from "@mui/material"; import { useEffect } from "react"; export const HighlightBaseline = () => { - const theme = useTheme(); + const { mode } = useColorScheme(); useEffect(() => { - if (theme.palette.mode === "dark") { - // @ts-ignore - don't check type of css module - import("highlight.js/styles/github-dark.css"); + console.log({ mode }); + // @ts-ignore - don't check type of css module + import("highlight.js/styles/github-dark.css"); + if (mode === "dark") { } else { // @ts-ignore - don't check type of css module - import("highlight.js/styles/github.css"); + // import("highlight.js/styles/github.css"); } - }, [theme]); + }, [mode]); return <>; }; diff --git a/website/src/components/functionOfTheDay/functionOfTheDay.tsx b/website/src/components/functionOfTheDay/functionOfTheDay.tsx index a542cf1..6691a30 100644 --- a/website/src/components/functionOfTheDay/functionOfTheDay.tsx +++ b/website/src/components/functionOfTheDay/functionOfTheDay.tsx @@ -6,7 +6,7 @@ import { CardContent, CardHeader, Divider, - useTheme, + styled, } from "@mui/material"; import { useMemo, useState } from "react"; import seedrandom from "seedrandom"; @@ -37,10 +37,20 @@ function getRandomIntInclusive(min: number, max: number, config?: Config) { return Math.floor(randomNumber * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive } +const FunctionCard = styled( + Card, + {} +)(({ theme }) => ({ + width: "100%", + borderImageSlice: 1, + borderImageSource: `linear-gradient(to left, ${theme.vars.palette.info.light},${theme.vars.palette.error.main})`, + // : `linear-gradient(to left, ${info.light},${info.dark})`, + borderWidth: 4, + borderStyle: "solid", +})); + export const FunctionOfTheDay = () => { - const { - palette: { info, error }, - } = useTheme(); + // const { mode } = useColorScheme(); const todaysIdx = useMemo( () => getRandomIntInclusive(0, data.length - 1), @@ -74,20 +84,7 @@ export const FunctionOfTheDay = () => { }; return ( - + { Next - + ); }; diff --git a/website/src/components/layout/Background.tsx b/website/src/components/layout/Background.tsx index b5ad893..81f812b 100644 --- a/website/src/components/layout/Background.tsx +++ b/website/src/components/layout/Background.tsx @@ -1,9 +1,8 @@ "use client"; -import { Box, useTheme } from "@mui/material"; +import { Box } from "@mui/material"; import { ReactNode } from "react"; export const Background = ({ children }: { children: ReactNode }) => { - const theme = useTheme(); return ( { flexDirection: "column", overflowX: "hidden", overflowY: "scroll", - bgcolor: - theme.palette.mode === "light" ? "rgb(242, 248, 253)" : "#070c16", + bgcolor: "background.paper", }} > {children} diff --git a/website/src/components/layout/header.tsx b/website/src/components/layout/header.tsx index 660751d..ac61e7b 100644 --- a/website/src/components/layout/header.tsx +++ b/website/src/components/layout/header.tsx @@ -1,5 +1,5 @@ "use client"; -import { Box, LinearProgress, Link, useTheme } from "@mui/material"; +import { Box, LinearProgress, Link } from "@mui/material"; import { SearchInput } from "../searchInput"; import { Filter } from "../filter"; import { Suspense } from "react"; @@ -13,8 +13,6 @@ const fira = localFont({ }); export const Header = () => { - const theme = useTheme(); - return ( <> { width: "100%", py: 1.2, zIndex: 1000, - backgroundColor: - theme.palette.mode === "light" ? "primary.main" : "#101010", + backgroundColor: "header.default", display: "grid", gridTemplateColumns: { xs: "1fr", diff --git a/website/src/components/layout/layout.tsx b/website/src/components/layout/layout.tsx index a4b9bca..2a9b912 100644 --- a/website/src/components/layout/layout.tsx +++ b/website/src/components/layout/layout.tsx @@ -8,6 +8,7 @@ import { } from "@mui/material"; import GitHubIcon from "@mui/icons-material/GitHub"; import { Background } from "./Background"; +import { ThemeSwitch } from "./themeSwitch"; export interface LayoutProps { children: React.ReactNode; @@ -38,6 +39,7 @@ export function LandingPageLayout(props: LayoutProps) { +
{ + const { mode, setMode } = useColorScheme(); + + return ( + <> + {mode === "dark" ? ( + + setMode("light")}> + + + + ) : ( + + setMode("dark")}> + + + + )} + + ); +}; diff --git a/website/src/components/markdownPreview/MarkdownPreview.tsx b/website/src/components/markdownPreview/MarkdownPreview.tsx index 305d6fd..e547710 100644 --- a/website/src/components/markdownPreview/MarkdownPreview.tsx +++ b/website/src/components/markdownPreview/MarkdownPreview.tsx @@ -1,5 +1,5 @@ "use client"; -import { useTheme } from "@mui/material"; +import { useColorScheme } from "@mui/material"; import nix from "highlight.js/lib/languages/nix"; import haskell from "highlight.js/lib/languages/haskell"; import bash from "highlight.js/lib/languages/bash"; @@ -23,16 +23,17 @@ interface MarkdownPreviewProps { } export const MarkdownPreview = (props: MarkdownPreviewProps) => { const { description } = props; - const theme = useTheme(); + const { mode } = useColorScheme(); useEffect(() => { - if (theme.palette.mode === "dark") { - // @ts-ignore - don't check type of css module - import("highlight.js/styles/github-dark.css"); + console.log({ mode }); + // @ts-ignore - don't check type of css module + import("highlight.js/styles/github-dark.css"); + if (mode === "dark") { } else { // @ts-ignore - don't check type of css module - import("highlight.js/styles/github.css"); + // import("highlight.js/styles/github.css"); } - }, [theme]); + }, [mode]); return ( <> diff --git a/website/src/components/themeRegistry.tsx b/website/src/components/themeRegistry.tsx deleted file mode 100644 index 4b4baf5..0000000 --- a/website/src/components/themeRegistry.tsx +++ /dev/null @@ -1,72 +0,0 @@ -"use client"; -import { darkThemeOptions, lightThemeOptions } from "@/styles/theme"; -import createCache from "@emotion/cache"; -import { CacheProvider } from "@emotion/react"; -import { useMediaQuery } from "@mui/material"; -import CssBaseline from "@mui/material/CssBaseline"; -import { ThemeProvider, createTheme } from "@mui/material/styles"; -import { useServerInsertedHTML } from "next/navigation"; -import React, { ReactNode } from "react"; - -const lightTheme = createTheme(lightThemeOptions); -const darkTheme = createTheme(darkThemeOptions); - -// This implementation is from emotion-js -// https://github.com/emotion-js/emotion/issues/2928#issuecomment-1319747902 -export default function ThemeRegistry(props: { - children: ReactNode; - options: any; -}) { - const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)"); - - const { options, children } = props; - - const [{ cache, flush }] = React.useState(() => { - const cache = createCache(options); - cache.compat = true; - const prevInsert = cache.insert; - let inserted: string[] = []; - cache.insert = (...args) => { - const serialized = args[1]; - if (cache.inserted[serialized.name] === undefined) { - inserted.push(serialized.name); - } - return prevInsert(...args); - }; - const flush = () => { - const prevInserted = inserted; - inserted = []; - return prevInserted; - }; - return { cache, flush }; - }); - - useServerInsertedHTML(() => { - const names = flush(); - if (names.length === 0) { - return null; - } - let styles = ""; - for (const name of names) { - styles += cache.inserted[name]; - } - return ( -