From 941c2f2cfa7c92dbb3854dfc41fba27551a40e9c Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Mon, 21 Aug 2023 00:05:11 -0500 Subject: [PATCH 01/16] feat: add dark mode --- context/ColorContext.tsx | 35 +++++++++++++++++ package.json | 5 ++- pages/_app.tsx | 17 +++++---- pages/_document.tsx | 17 ++++----- src/components/NavBar.tsx | 22 ++++++++++- src/theme.ts | 52 +++++++++++++++++-------- yarn.lock | 80 +++++++++++++++++++++++---------------- 7 files changed, 161 insertions(+), 67 deletions(-) create mode 100644 context/ColorContext.tsx diff --git a/context/ColorContext.tsx b/context/ColorContext.tsx new file mode 100644 index 00000000..3354ae01 --- /dev/null +++ b/context/ColorContext.tsx @@ -0,0 +1,35 @@ +import { TContextProviderProps } from '@context/types'; +import { PaletteMode, useMediaQuery } from '@mui/material'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; +import { deepmerge } from '@mui/utils'; +import { getDesignTokens, getThemeComponents } from '@src/theme'; +import { createContext, useContext, useMemo, useState } from 'react'; + +const ColorContext = createContext('light'); + +export const useColorMode = () => useContext(ColorContext); + +export const ColorProvider = ({ children }: TContextProviderProps) => { + + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); + const [mode, setMode] = useState('light'); + const theme = useMemo(()=>createTheme(deepmerge(getDesignTokens(mode),getThemeComponents(mode))),[mode]) + const colorMode = useMemo( + () => ({ + // The dark mode switch would invoke this method + toggleColorMode: () => { + setMode((prevMode: PaletteMode) => + prevMode === 'light' ? 'dark' : 'light', + ); + }, + }), + [], + ); + return ( + + + {children} + + + ); +}; diff --git a/package.json b/package.json index 76cba203..bcdab42d 100644 --- a/package.json +++ b/package.json @@ -33,9 +33,10 @@ "@emotion/cache": "^11.10.5", "@emotion/react": "^11.11.1", "@emotion/server": "^11.4.0", - "@emotion/styled": "^11.10.5", + "@emotion/styled": "^11.11.0", + "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.11.11", - "@mui/material": "^5.14.2", + "@mui/material": "^5.14.5", "@mui/x-data-grid": "^6.6.0", "@toast-ui/react-editor": "^3.2.2", "firebase": "^9.15.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index f4d45f42..7bd1f3b4 100755 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,16 +1,14 @@ import { AlertBar } from '@components/AlertBar'; import { AlertContextProvider } from '@context/AlertContext'; import { AuthContextProvider } from '@context/AuthContext'; +import { ColorProvider } from '@context/ColorContext'; import { MenuContextProvider } from '@context/MenuContext'; import { CacheProvider, EmotionCache } from '@emotion/react'; import CssBaseline from '@mui/material/CssBaseline'; -import { ThemeProvider } from '@mui/material/styles'; import { NavBar } from '@src/components/NavBar'; import createEmotionCache from '@src/createEmotionCache'; -import theme from '@src/theme'; import { AppProps } from 'next/app'; import Head from 'next/head'; - // Client-side cache, shared for the whole session of the user in the browser. const clientSideEmotionCache = createEmotionCache(); @@ -23,26 +21,31 @@ const MyApp = ({ Component, emotionCache = clientSideEmotionCache, pageProps, -}: MyAppProps) => ( +}: MyAppProps) => { + + + + + return ( + OMSHub - - {/* */} + -); +)}; export default MyApp; diff --git a/pages/_document.tsx b/pages/_document.tsx index ce1eac64..60ba9f48 100755 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; -import Document, { Html, Head, Main, NextScript } from 'next/document'; import createEmotionServer from '@emotion/server/create-instance'; -import theme from '@src/theme'; +import { useTheme } from '@mui/material/styles'; import createEmotionCache from '@src/createEmotionCache'; +import Document, { Head, Html, Main, NextScript } from 'next/document'; -export default class MyDocument extends Document { - render() { +export default function MyDocument(props:any){ + + const theme = useTheme() return ( @@ -17,7 +17,7 @@ export default class MyDocument extends Document { href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap' /> {/* Inject MUI styles first to match with the prepend: true configuration. */} - {(this.props as any).emotionStyleTags} + {(props as any).emotionStyleTags}
@@ -25,12 +25,11 @@ export default class MyDocument extends Document { ); - } } // `getInitialProps` belongs to `_document` (instead of `_app`), // it's compatible with static-site generation (SSG). -MyDocument.getInitialProps = async (ctx) => { +MyDocument.getInitialProps = async (ctx:any) => { // Resolution order // // On the server: @@ -63,7 +62,7 @@ MyDocument.getInitialProps = async (ctx) => { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App: any) => - function EnhanceApp(props) { + function EnhanceApp(props:any) { return ; }, }); diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index 3f78a1a5..e586a4ae 100755 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -2,17 +2,21 @@ import Login from '@components/LoginContent'; import MobileMenu from '@components/MobileMenu'; import ProfileMenu from '@components/ProfileMenu'; import { useAuth } from '@context/AuthContext'; +import { useColorMode } from '@context/ColorContext'; import { useMenu } from '@context/MenuContext'; import { FirebaseAuthUser } from '@context/types'; +import Brightness4Icon from '@mui/icons-material/Brightness4'; +import Brightness7Icon from '@mui/icons-material/Brightness7'; import GitHubIcon from '@mui/icons-material/GitHub'; -import { Tooltip } from '@mui/material'; +import { IconButton, Tooltip } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; -import { grey } from '@mui/material/colors'; import Dialog from '@mui/material/Dialog'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; +import { grey } from '@mui/material/colors'; +import { useTheme } from '@mui/material/styles'; import Link from '@src/Link'; interface NavBarProps {} @@ -45,6 +49,9 @@ export const NavBar = ({ ...props }: NavBarProps) => { 'My Reviews': '/user/reviews', }; + const theme = useTheme(); + const { colorMode } = useColorMode(); + return ( { ), )} + + {theme.palette.mode === 'dark' ? ( + + ) : ( + + )} + ({ + palette :{ + mode, + ...(mode == 'light')? + { + primary: { + main: navyBlue, + }, + secondary: { + main: techGold, + }, + error: { + main: red.A400, + } + }: + { + primary: { + main: navyBlue, + }, + secondary: { + main: techGold, + }, + error: { + main: red.A400, + } + } + } +}) // Create a theme instance. -const theme = createTheme({ - palette: { - primary: { - main: navyBlue, - }, - secondary: { - main: techGold, - }, - error: { - main: red.A400, - }, - }, -}); -export default theme; +export const getThemeComponents = (mode : PaletteMode ) =>({ + mode, + ...(mode == 'light')? + {}: + {} +}) diff --git a/yarn.lock b/yarn.lock index 15d6be2d..cc3a1aaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1105,7 +1105,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== @@ -1424,7 +1424,7 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/styled@^11.10.5": +"@emotion/styled@^11.11.0": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== @@ -2002,6 +2002,11 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.1.tgz#1a5b1959a528e374e8037c4396c3e825d6cf4a83" integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw== +"@fontsource/roboto@^5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@fontsource/roboto/-/roboto-5.0.8.tgz#613b477a56f21b5705db1a67e995c033ef317f76" + integrity sha512-XxPltXs5R31D6UZeLIV1td3wTXU3jzd3f2DLsXI8tytMGBkIsGcc9sIyiupRtA8y73HAhuSCeweOoBqf6DbWCA== + "@grpc/grpc-js@~1.7.0": version "1.7.3" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.7.3.tgz#f2ea79f65e31622d7f86d4b4c9ae38f13ccab99a" @@ -2353,24 +2358,24 @@ "@types/mdx" "^2.0.0" "@types/react" ">=16" -"@mui/base@5.0.0-beta.9": - version "5.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.9.tgz#e88d7052aa6d97c1e57d5ce2a4e2edf898db90ec" - integrity sha512-gm6gnPnc/lS5Z3neH0iuOrK7IbS02+oh6KsMtXYLhI6bJpHs+PNWFsBmISx7x4FSPVJZvZkb8Bw6pEXpIMFt7Q== +"@mui/base@5.0.0-beta.11": + version "5.0.0-beta.11" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.11.tgz#0124d336f1931c6cd5f0008d015df5bd8fafd3a8" + integrity sha512-FdKZGPd8qmC3ZNke7CNhzcEgToc02M6WYZc9hcBsNQ17bgAd3s9F//1bDDYgMVBYxDM71V0sv/hBHlOY4I1ZVA== dependencies: "@babel/runtime" "^7.22.6" "@emotion/is-prop-valid" "^1.2.1" "@mui/types" "^7.2.4" - "@mui/utils" "^5.14.3" + "@mui/utils" "^5.14.5" "@popperjs/core" "^2.11.8" clsx "^2.0.0" prop-types "^15.8.1" react-is "^18.2.0" -"@mui/core-downloads-tracker@^5.14.3": - version "5.14.3" - resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.3.tgz#474689f4d691993376e8a1ca07e08d4545275082" - integrity sha512-QxvrcDqphZoXRjsAmCaQylmWjC/8/qKWwIde1MJMna5YIst3R9O0qhKRPu36/OE2d8AeTbCVjRcRvNqhhW8jyg== +"@mui/core-downloads-tracker@^5.14.5": + version "5.14.5" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.5.tgz#c5854b89d57520c77253a79b20b784d5c2903fb6" + integrity sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA== "@mui/icons-material@^5.11.11": version "5.14.3" @@ -2379,17 +2384,17 @@ dependencies: "@babel/runtime" "^7.22.6" -"@mui/material@^5.14.2": - version "5.14.3" - resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.3.tgz#c88dbc270c4ebde32f9956b9b3cbf8a5d1dc7aef" - integrity sha512-dlu4SOcCp9Cy+wkcfZ/ns9ZkP40nr/WPgqxX0HmrE0o+dkE1ropY9BbHsLrTlYJCko8yzcC8bLghrD4xqZG1og== +"@mui/material@^5.14.5": + version "5.14.5" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.5.tgz#4610b381fd159cd208c28e1d1f29c303ea24a518" + integrity sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA== dependencies: "@babel/runtime" "^7.22.6" - "@mui/base" "5.0.0-beta.9" - "@mui/core-downloads-tracker" "^5.14.3" - "@mui/system" "^5.14.3" + "@mui/base" "5.0.0-beta.11" + "@mui/core-downloads-tracker" "^5.14.5" + "@mui/system" "^5.14.5" "@mui/types" "^7.2.4" - "@mui/utils" "^5.14.3" + "@mui/utils" "^5.14.5" "@types/react-transition-group" "^4.4.6" clsx "^2.0.0" csstype "^3.1.2" @@ -2397,13 +2402,13 @@ react-is "^18.2.0" react-transition-group "^4.4.5" -"@mui/private-theming@^5.13.7": - version "5.13.7" - resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.13.7.tgz#2f8ef5da066f3c6c6423bd4260d003a28d10b099" - integrity sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA== +"@mui/private-theming@^5.14.5": + version "5.14.5" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.14.5.tgz#834e1569c31e2644665f98d902def79014053017" + integrity sha512-cC4C5RrpXpDaaZyH9QwmPhRLgz+f2SYbOty3cPkk4qPSOSfif2ZEcDD9HTENKDDd9deB+xkPKzzZhi8cxIx8Ig== dependencies: - "@babel/runtime" "^7.22.5" - "@mui/utils" "^5.13.7" + "@babel/runtime" "^7.22.6" + "@mui/utils" "^5.14.5" prop-types "^15.8.1" "@mui/styled-engine@^5.13.2": @@ -2416,16 +2421,16 @@ csstype "^3.1.2" prop-types "^15.8.1" -"@mui/system@^5.14.3": - version "5.14.3" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.3.tgz#71aa88433649a23dfa5c102cef8a3c5b1ac40ac6" - integrity sha512-b+C+j9+75+/iIYSa+1S4eCMc9MDNrj9hzWfExJqS2GffuNocRagjBZFyjtMqsLWLxMxQIX8Cg6j0hAioiw+WfQ== +"@mui/system@^5.14.5": + version "5.14.5" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.5.tgz#614394c4183d90df82c540e0e736ba72c1f95f8e" + integrity sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w== dependencies: "@babel/runtime" "^7.22.6" - "@mui/private-theming" "^5.13.7" + "@mui/private-theming" "^5.14.5" "@mui/styled-engine" "^5.13.2" "@mui/types" "^7.2.4" - "@mui/utils" "^5.14.3" + "@mui/utils" "^5.14.5" clsx "^2.0.0" csstype "^3.1.2" prop-types "^15.8.1" @@ -2435,7 +2440,7 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328" integrity sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA== -"@mui/utils@^5.13.7", "@mui/utils@^5.14.3": +"@mui/utils@^5.13.7": version "5.14.3" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.14.3.tgz#76d8151c23d2c2a871e98b90add57a8fd01d5d80" integrity sha512-gZ6Etw+ppO43GYc1HFZSLjwd4DoZoa+RrYTD25wQLfzcSoPjVoC/zZqA2Lkq0zjgwGBQOSxKZI6jfp9uXR+kgw== @@ -2446,6 +2451,17 @@ prop-types "^15.8.1" react-is "^18.2.0" +"@mui/utils@^5.14.5": + version "5.14.5" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.14.5.tgz#98fb6060610b793a8478e70ffe5e4ed5bd922dba" + integrity sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA== + dependencies: + "@babel/runtime" "^7.22.6" + "@types/prop-types" "^15.7.5" + "@types/react-is" "^18.2.1" + prop-types "^15.8.1" + react-is "^18.2.0" + "@mui/x-data-grid@^6.6.0": version "6.10.2" resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-6.10.2.tgz#9aff72f550c4b96269debbfccaeb0a94e5677d77" From aff6ed71fabc60e82e34418fc3afc5c9a2407ca1 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Mon, 21 Aug 2023 22:05:52 -0500 Subject: [PATCH 02/16] feat(darkmode): minor styling update for darkmode --- src/components/NavBar.tsx | 21 +++++++++++++-------- src/theme.ts | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index e586a4ae..63ba2b28 100755 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -15,7 +15,6 @@ import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; -import { grey } from '@mui/material/colors'; import { useTheme } from '@mui/material/styles'; import Link from '@src/Link'; interface NavBarProps {} @@ -56,11 +55,11 @@ export const NavBar = ({ ...props }: NavBarProps) => { `${theme.palette.common.white}`, - boxShadow: `0 5px 15px 0 ${grey[200]}`, + background: (theme) => `${theme.palette.primary.contrastText}`, + color: (theme) => `${theme.palette.primary.main}`, + boxShadow: `0 5px 15px 0 ${theme.palette.primary.contrastText}`, }} {...props} > @@ -68,7 +67,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { { > { ), )} + {theme.palette.mode === 'dark' ? ( ) : ( )} + ({ ...(mode == 'light')? { primary: { - main: navyBlue, + main: '#000', + contrastText: grey[200], }, secondary: { main: techGold, @@ -21,7 +23,8 @@ export const getDesignTokens = (mode: PaletteMode ) => ({ }: { primary: { - main: navyBlue, + main: white, + contrastText: '#000', }, secondary: { main: techGold, @@ -36,7 +39,11 @@ export const getDesignTokens = (mode: PaletteMode ) => ({ export const getThemeComponents = (mode : PaletteMode ) =>({ mode, - ...(mode == 'light')? - {}: + components: { + ...(mode == 'light')? + { + + }: {} + } }) From 6ed07144e484c9ea157a7e34285f3a3e9b2f8a77 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Wed, 23 Aug 2023 18:20:24 -0500 Subject: [PATCH 03/16] feat(darkmode): added working light and dark mode with persistent state, defaulted to system --- context/ColorContext.tsx | 46 +++++++++++++----------------- next.config.js | 7 +++-- package.json | 1 + pages/_app.tsx | 12 ++++++-- pages/_document.tsx | 10 +++++-- pages/course/[courseid].tsx | 23 ++++++++------- pages/index.tsx | 11 ++++--- src/components/FormEditor.tsx | 39 ++++++++++++------------- src/components/NavBar.tsx | 13 +++------ src/components/ProfileMenu.tsx | 2 +- src/components/ReviewCard.tsx | 8 +++--- src/components/ReviewForm.tsx | 9 +++--- src/theme.ts | 52 ++++++++++++++++++++++++---------- yarn.lock | 5 ++++ 14 files changed, 136 insertions(+), 102 deletions(-) diff --git a/context/ColorContext.tsx b/context/ColorContext.tsx index 3354ae01..acb51f16 100644 --- a/context/ColorContext.tsx +++ b/context/ColorContext.tsx @@ -1,35 +1,27 @@ import { TContextProviderProps } from '@context/types'; -import { PaletteMode, useMediaQuery } from '@mui/material'; -import { ThemeProvider, createTheme } from '@mui/material/styles'; -import { deepmerge } from '@mui/utils'; -import { getDesignTokens, getThemeComponents } from '@src/theme'; -import { createContext, useContext, useMemo, useState } from 'react'; +import { Experimental_CssVarsProvider as CssVarsProvider, experimental_extendTheme as extendTheme } from '@mui/material/styles'; +import { getDesignTokens } from '@src/theme'; -const ColorContext = createContext('light'); - -export const useColorMode = () => useContext(ColorContext); +const { palette: lightPalette } = getDesignTokens('light'); +const { palette: darkPalette } = getDesignTokens('dark'); +export const theme = extendTheme({ + cssVarPrefix:'omshub', + colorSchemes:{ + light:{ + palette: lightPalette + }, + dark:{ + palette: darkPalette + } + } +}) export const ColorProvider = ({ children }: TContextProviderProps) => { - const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); - const [mode, setMode] = useState('light'); - const theme = useMemo(()=>createTheme(deepmerge(getDesignTokens(mode),getThemeComponents(mode))),[mode]) - const colorMode = useMemo( - () => ({ - // The dark mode switch would invoke this method - toggleColorMode: () => { - setMode((prevMode: PaletteMode) => - prevMode === 'light' ? 'dark' : 'light', - ); - }, - }), - [], - ); + return ( - - + {children} - - + ); -}; +}; \ No newline at end of file diff --git a/next.config.js b/next.config.js index 1201cd68..10a43359 100755 --- a/next.config.js +++ b/next.config.js @@ -12,10 +12,11 @@ module.exports = { appId: process.env.APP_ID, measurementId: process.env.MEASUREMENT_ID, }, - transpilePackages: ['@mui/system', '@mui/material', '@mui/icons-material'], +transpilePackages: ['@mui/system', '@mui/material', '@mui/icons-material'], modularizeImports: { - '@mui/material/?(((\\w*)?/?)*)': { - transform: '@mui/material/{{ matches.[1] }}/{{member}}', + '@mui/material/!(styles)/?*': { + transform: '@mui/material/{{path}}/{{member}}', + skipDefaultConversion: true, }, '@mui/icons-material/?(((\\w*)?/?)*)': { transform: '@mui/icons-material/{{ matches.[1] }}/{{member}}', diff --git a/package.json b/package.json index bcdab42d..883c25ea 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "html-to-image": "^1.11.11", "isomorphic-dompurify": "^1.8.0", "next": "13.4.12", + "next-themes": "^0.2.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.45.2", diff --git a/pages/_app.tsx b/pages/_app.tsx index 7bd1f3b4..41284146 100755 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -7,12 +7,19 @@ import { CacheProvider, EmotionCache } from '@emotion/react'; import CssBaseline from '@mui/material/CssBaseline'; import { NavBar } from '@src/components/NavBar'; import createEmotionCache from '@src/createEmotionCache'; +import type { NextPage } from 'next'; import { AppProps } from 'next/app'; import Head from 'next/head'; +import type { ReactElement, ReactNode } from 'react'; + // Client-side cache, shared for the whole session of the user in the browser. const clientSideEmotionCache = createEmotionCache(); +export type NextPageWithLayout

= NextPage & { + getLayout?: (page: ReactElement) => ReactNode +} interface MyAppProps extends AppProps { + Component: NextPageWithLayout emotionCache?: EmotionCache; fallback: object; } @@ -23,8 +30,7 @@ const MyApp = ({ pageProps, }: MyAppProps) => { - - + const getLayout = Component.getLayout ?? ((page) => page) return ( @@ -40,7 +46,7 @@ const MyApp = ({ - + {getLayout()} {/* */} diff --git a/pages/_document.tsx b/pages/_document.tsx index 60ba9f48..e672d704 100755 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,7 +1,9 @@ import createEmotionServer from '@emotion/server/create-instance'; -import { useTheme } from '@mui/material/styles'; +import { getInitColorSchemeScript, useTheme } from '@mui/material/styles'; import createEmotionCache from '@src/createEmotionCache'; import Document, { Head, Html, Main, NextScript } from 'next/document'; +import React from 'react'; + export default function MyDocument(props:any){ @@ -20,6 +22,7 @@ export default function MyDocument(props:any){ {(props as any).emotionStyleTags} + {getInitColorSchemeScript()}

@@ -82,6 +85,9 @@ MyDocument.getInitialProps = async (ctx:any) => { return { ...initialProps, - emotionStyleTags, + styles: [ + ...React.Children.toArray(initialProps.styles), + ...emotionStyleTags, + ], }; }; diff --git a/pages/course/[courseid].tsx b/pages/course/[courseid].tsx index 69cc2a76..01baed77 100755 --- a/pages/course/[courseid].tsx +++ b/pages/course/[courseid].tsx @@ -211,7 +211,7 @@ const CourseId: NextPage = ({ alignItems: 'center', }} > - + {courseData?.name} {courseData && courseData?.url && ( @@ -224,7 +224,7 @@ const CourseId: NextPage = ({ }} > - + {'Course Website'} @@ -242,16 +242,15 @@ const CourseId: NextPage = ({ justifyContent='center' > - + {`Average Workload`} - + {roundNumber(Number(courseData?.avgWorkload), 1) + ' hrs/wk'} @@ -270,8 +269,11 @@ const CourseId: NextPage = ({ > {`Average Difficulty`} @@ -303,8 +305,7 @@ const CourseId: NextPage = ({ > {`Average Overall`} @@ -395,7 +396,7 @@ const CourseId: NextPage = ({ <> @@ -440,7 +441,7 @@ const CourseId: NextPage = ({ autoHideDuration={6000} onClose={handleClose} action={ - } diff --git a/pages/index.tsx b/pages/index.tsx index 6d184b5c..0bf9d6ca 100755 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -40,7 +40,7 @@ const Home: NextPage = ({ allCourseData }) => { minWidth: isDesktop ? 50 : 300, renderCell: (params: GridRenderCellParams) => ( - + {params.row.name} @@ -118,17 +118,20 @@ const Home: NextPage = ({ allCourseData }) => { rows={courses} columns={columns} loading={!allCourseData} - components={{ Toolbar: GridToolbar }} + slots={{ toolbar : GridToolbar }} sx={{ borderRadius: '25px', padding: '20px 10px' }} columnVisibilityModel={{ isDeprecated: false, aliases: false, }} - componentsProps={{ + slotProps={{ toolbar: { printOptions: { disableToolbarButton: true }, + disableDensitySelector: true, showQuickFilter: true, - quickFilterProps: { debounceMs: 500 }, + sx:{ + + } }, }} initialState={{ diff --git a/src/components/FormEditor.tsx b/src/components/FormEditor.tsx index bbe45fa7..8d4b45eb 100644 --- a/src/components/FormEditor.tsx +++ b/src/components/FormEditor.tsx @@ -1,3 +1,4 @@ +import { useTheme } from '@mui/material/styles'; import '@toast-ui/editor/dist/toastui-editor.css'; import { Editor } from '@toast-ui/react-editor'; import DOMPurify from 'isomorphic-dompurify'; @@ -13,7 +14,7 @@ export default function FormEditor({ onChange: any; }) { const editorRef = useRef(null); - + const theme = useTheme(); function handleChange() { const dirty = editorRef?.current ? editorRef?.current.getInstance().getMarkdown() @@ -21,24 +22,24 @@ export default function FormEditor({ const clean = DOMPurify.sanitize(dirty, { FORBID_TAGS: ['img'] }); onChange(clean); } - return ( - + ); } diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index 63ba2b28..674e5eb7 100755 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -2,13 +2,12 @@ import Login from '@components/LoginContent'; import MobileMenu from '@components/MobileMenu'; import ProfileMenu from '@components/ProfileMenu'; import { useAuth } from '@context/AuthContext'; -import { useColorMode } from '@context/ColorContext'; import { useMenu } from '@context/MenuContext'; import { FirebaseAuthUser } from '@context/types'; import Brightness4Icon from '@mui/icons-material/Brightness4'; import Brightness7Icon from '@mui/icons-material/Brightness7'; import GitHubIcon from '@mui/icons-material/GitHub'; -import { IconButton, Tooltip } from '@mui/material'; +import { IconButton, Tooltip, useColorScheme } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -49,18 +48,14 @@ export const NavBar = ({ ...props }: NavBarProps) => { }; const theme = useTheme(); - const { colorMode } = useColorMode(); + const { mode, setMode } = useColorScheme(); return ( `${theme.palette.primary.contrastText}`, - color: (theme) => `${theme.palette.primary.main}`, - boxShadow: `0 5px 15px 0 ${theme.palette.primary.contrastText}`, - }} {...props} > @@ -114,7 +109,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { height: "100%", my: 1, mx: 1.5, }} - onClick={colorMode.toggleColorMode} + onClick={()=>setMode(mode == 'light' ? 'dark' : 'light')} color="inherit" > diff --git a/src/components/ProfileMenu.tsx b/src/components/ProfileMenu.tsx index db8f37c9..086fe9de 100644 --- a/src/components/ProfileMenu.tsx +++ b/src/components/ProfileMenu.tsx @@ -29,7 +29,7 @@ const ProfileMenu = (profileMenuItems: MenuLinksProps) => { const menuId = 'primary-search-account-menu'; return ( <> - + - {courseId} + {courseId} - {courseName} + {courseName} - + Taken {mapSemesterIdToName[semesterId]} {year} - + Reviewed on {timestamp} diff --git a/src/components/ReviewForm.tsx b/src/components/ReviewForm.tsx index 40ca117a..39a88709 100644 --- a/src/components/ReviewForm.tsx +++ b/src/components/ReviewForm.tsx @@ -211,7 +211,7 @@ const ReviewForm = ({ /> - Year + Year - Semester + Semester - Workload + Workload - + Review diff --git a/src/theme.ts b/src/theme.ts index f609950d..a2b7d7ee 100755 --- a/src/theme.ts +++ b/src/theme.ts @@ -1,6 +1,6 @@ import { PaletteMode } from '@mui/material'; -import { grey, red } from '@mui/material/colors'; -import { techGold, white } from '@src/colorPalette'; +import { red } from '@mui/material/colors'; +import { navyBlue, techGold } from '@src/colorPalette'; @@ -9,31 +9,47 @@ export const getDesignTokens = (mode: PaletteMode ) => ({ palette :{ mode, ...(mode == 'light')? + //Light { primary: { main: '#000', - contrastText: grey[200], + contrastText:'#FFF' }, secondary: { - main: techGold, + main: navyBlue, }, error: { main: red.A400, } }: + //Dark { - primary: { - main: white, - contrastText: '#000', - }, - secondary: { - main: techGold, - }, - error: { - main: red.A400, + primary: { + main: '#FFF', + contrastText: '#000', + }, + secondary: { + main: techGold, + }, + error: { + main: red.A400, + } + } + }, + dark:{ + palette:{ + primary: { + main: '#000', + contrastText: '#FFF', + }, + secondary: { + main: techGold, + }, + error: { + main: red.A400, + } } } - } }) // Create a theme instance. @@ -44,6 +60,12 @@ export const getThemeComponents = (mode : PaletteMode ) =>({ { }: - {} + { + MuiAppBar:{ + styleOverrides:{ + + } + } + } } }) diff --git a/yarn.lock b/yarn.lock index cc3a1aaf..c44327cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10256,6 +10256,11 @@ next-sitemap@^4.1.8: fast-glob "^3.2.12" minimist "^1.2.8" +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.4.12: version "13.4.12" resolved "https://registry.yarnpkg.com/next/-/next-13.4.12.tgz#809b21ea0aabbe88ced53252c88c4a5bd5af95df" From e3106f107d24b520a978057313ba341f5893e91c Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Wed, 23 Aug 2023 18:24:07 -0500 Subject: [PATCH 04/16] chore(darkmode): remove next-themes --- package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/package.json b/package.json index 883c25ea..bcdab42d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "html-to-image": "^1.11.11", "isomorphic-dompurify": "^1.8.0", "next": "13.4.12", - "next-themes": "^0.2.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.45.2", diff --git a/yarn.lock b/yarn.lock index c44327cb..cc3a1aaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10256,11 +10256,6 @@ next-sitemap@^4.1.8: fast-glob "^3.2.12" minimist "^1.2.8" -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.4.12: version "13.4.12" resolved "https://registry.yarnpkg.com/next/-/next-13.4.12.tgz#809b21ea0aabbe88ced53252c88c4a5bd5af95df" From 26e6e5c6148f5be0b8e0bb91082adba9836001f3 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Wed, 23 Aug 2023 18:26:00 -0500 Subject: [PATCH 05/16] chore(darkmode): remove random function --- pages/_app.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index 41284146..5b4236b1 100755 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -30,7 +30,6 @@ const MyApp = ({ pageProps, }: MyAppProps) => { - const getLayout = Component.getLayout ?? ((page) => page) return ( @@ -46,7 +45,7 @@ const MyApp = ({ - {getLayout()} + {} {/* */} From 356a6daaa110aeeea0ff8d8d03b725536ec88a69 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Wed, 23 Aug 2023 19:17:59 -0500 Subject: [PATCH 06/16] feat(darkmode): remove unused type --- pages/_app.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index 5b4236b1..6bc5f4a1 100755 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -7,19 +7,14 @@ import { CacheProvider, EmotionCache } from '@emotion/react'; import CssBaseline from '@mui/material/CssBaseline'; import { NavBar } from '@src/components/NavBar'; import createEmotionCache from '@src/createEmotionCache'; -import type { NextPage } from 'next'; import { AppProps } from 'next/app'; import Head from 'next/head'; -import type { ReactElement, ReactNode } from 'react'; // Client-side cache, shared for the whole session of the user in the browser. const clientSideEmotionCache = createEmotionCache(); -export type NextPageWithLayout

= NextPage & { - getLayout?: (page: ReactElement) => ReactNode -} + interface MyAppProps extends AppProps { - Component: NextPageWithLayout emotionCache?: EmotionCache; fallback: object; } From 6c3bdf22bd563ed3ac162726429707c3f9f83ac7 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Tue, 10 Oct 2023 02:49:49 -0500 Subject: [PATCH 07/16] fix(dark mode): redesigned mobile nav and login to accomodate dark mode --- context/ColorContext.tsx | 28 ++++++++++++- context/MenuContext.tsx | 12 +++--- pages/index.tsx | 20 ++++++--- src/components/LoginContent.tsx | 43 +++++++++++--------- src/components/MobileMenu.tsx | 72 ++++++++++++++------------------- src/components/NavBar.tsx | 18 +++------ src/theme.ts | 71 +++++++++++++++++++------------- 7 files changed, 151 insertions(+), 113 deletions(-) diff --git a/context/ColorContext.tsx b/context/ColorContext.tsx index acb51f16..be5f6b91 100644 --- a/context/ColorContext.tsx +++ b/context/ColorContext.tsx @@ -4,7 +4,22 @@ import { getDesignTokens } from '@src/theme'; const { palette: lightPalette } = getDesignTokens('light'); const { palette: darkPalette } = getDesignTokens('dark'); + export const theme = extendTheme({ + typography: { + fontFamily:[ + '-apple-system', + 'BlinkMacSystemFont', + '"Segoe UI"', + 'Roboto', + '"Helvetica Neue"', + 'Arial', + 'sans-serif', + '"Apple Color Emoji"', + '"Segoe UI Emoji"', + '"Segoe UI Symbol"', + ].join(','), + }, cssVarPrefix:'omshub', colorSchemes:{ light:{ @@ -13,7 +28,18 @@ export const theme = extendTheme({ dark:{ palette: darkPalette } - } + }, + components: { + MuiDrawer: { + styleOverrides: { + paper: { + backgroundColor: "123", + boxShadow:"", + backgroundImage:"", + } + } + } + } }) export const ColorProvider = ({ children }: TContextProviderProps) => { diff --git a/context/MenuContext.tsx b/context/MenuContext.tsx index 7e8141b2..6aa5125f 100644 --- a/context/MenuContext.tsx +++ b/context/MenuContext.tsx @@ -6,10 +6,10 @@ const MenuContext = createContext({}); export const useMenu = () => useContext(MenuContext); export const MenuContextProvider = ({ children }: TContextProviderProps) => { - const [loginModalOpen, setLoginModalOpen] = useState(false); + const [loginOpen, setLoginOpen] = useState(false); - const handleLoginModalOpen = () => setLoginModalOpen(true); - const handleLoginModalClose = () => setLoginModalOpen(false); + const handleLoginOpen = () => setLoginOpen(true); + const handleLoginClose = () => setLoginOpen(false); const [profileMenuAnchorEl, setProfileMenuAnchorEl] = React.useState(null); @@ -37,9 +37,9 @@ export const MenuContextProvider = ({ children }: TContextProviderProps) => { = ({ allCourseData }) => { field: courseFields.NAME, headerName: 'Course Name', flex: isDesktop ? 1 : 0, - minWidth: isDesktop ? 50 : 300, + minWidth: isDesktop ? 50 : 200, renderCell: (params: GridRenderCellParams) => ( @@ -50,25 +50,31 @@ const Home: NextPage = ({ allCourseData }) => { field: courseFields.COURSE_ID, headerName: 'Course ID', flex: isDesktop ? 0.5 : 0, + minWidth: isDesktop ? 50 : 150, }, { field: courseFields.AVG_DIFFICULTY, - headerName: 'Difficulty (out of 5)', + headerName: `Difficulty ${isDesktop ? "(out of 5)" : ""}`, flex: isDesktop ? 0.5 : 0, + minWidth: isDesktop ? 50 : 150, valueGetter: (params: any) => roundNumber(params.row.avgDifficulty, 1), type: 'number', }, { field: courseFields.AVG_WORKLOAD, - headerName: 'Workload (hrs/wk)', + headerName: `Workload ${isDesktop ? "(hrs/wk)": " "}`, flex: isDesktop ? 0.5 : 0, + minWidth: isDesktop ? 50 : 150, + valueGetter: (params: any) => roundNumber(params.row.avgWorkload, 1), type: 'number', }, { field: courseFields.AVG_OVERALL, - headerName: 'Overall (out of 5)', + headerName: `Overall ${isDesktop ? "(out of 5)" : ""}`, flex: isDesktop ? 0.5 : 0, + minWidth: isDesktop ? 50 : 150, + valueGetter: (params: any) => roundNumber(params.row.avgOverall, 1), type: 'number', }, @@ -76,6 +82,8 @@ const Home: NextPage = ({ allCourseData }) => { field: courseFields.NUM_REVIEWS, headerName: 'Number of Reviews', flex: isDesktop ? 0.5 : 0, + minWidth: isDesktop ? 50 : 200, + type: 'number', }, { @@ -111,14 +119,14 @@ const Home: NextPage = ({ allCourseData }) => { {`Georgia Tech's Online Master's Course Catalog`} <> - + { const authContext = useAuth(); @@ -21,7 +22,7 @@ const Login: NextPage = () => { if (authContext) { ({ signInWithProvider, signWithMagic } = authContext); } - const { handleLoginModalClose } = useMenu(); + const { loginOpen, handleLoginClose } = useMenu(); const [email, setEmail] = useState(''); const handleEmailChange = (event: any) => { setEmail(event?.target?.value); @@ -29,31 +30,34 @@ const Login: NextPage = () => { const handleKeyPress = (event: any) => { if (event?.charCode === 13) { signWithMagic(email); - handleLoginModalClose(); + handleLoginClose(); } }; + const isDesktop = useMediaQuery('(min-width:600px)'); const providers: TProviderName[] = ['Google', 'Facebook', 'Github']; return ( - - + + - Login via preferred method + LOGIN - - { key={index} onClick={() => { signInWithProvider(provider); - handleLoginModalClose(); + handleLoginClose(); }} provider={provider} > ))} + - - + + ); }; diff --git a/src/components/MobileMenu.tsx b/src/components/MobileMenu.tsx index 8fc622c5..8ed900a0 100644 --- a/src/components/MobileMenu.tsx +++ b/src/components/MobileMenu.tsx @@ -1,8 +1,10 @@ import { MenuLinksProps } from '@components/NavBar'; import { useMenu } from '@context/MenuContext'; import MenuIcon from '@mui/icons-material/Menu'; -import { Container, IconButton, Menu, MenuItem } from '@mui/material'; +import { Box, Container, Drawer, IconButton, ListItemButton, Stack, Typography } from '@mui/material'; import Link from '@src/Link'; +import CloseIcon from '@mui/icons-material/Close'; + const MobileMenu = (navigationMenuItems: MenuLinksProps) => { const { @@ -11,11 +13,12 @@ const MobileMenu = (navigationMenuItems: MenuLinksProps) => { handleMobileNavMenuClose, } = useMenu(); + // const isMobileNavMenuOpen = Boolean(mobileNavMenuAnchorEl) - const menuId = 'mobile-navigation-menu'; return ( <> { > -

+ + + - + NAVIGATION + + {`Home`} - + {Object.keys(navigationMenuItems).map( (name: string, index: number) => ( - + {name} - + ), )} - + {`Github`} - - + + + + + ); diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index 674e5eb7..8b30e66d 100755 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -11,7 +11,6 @@ import { IconButton, Tooltip, useColorScheme } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; -import Dialog from '@mui/material/Dialog'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import { useTheme } from '@mui/material/styles'; @@ -31,7 +30,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { ({ user } = authContext); } - const { loginModalOpen, handleLoginModalOpen, handleLoginModalClose } = + const { handleLoginOpen } = useMenu(); const navigationMenuItems: MenuLinksProps = { @@ -58,7 +57,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { elevation={0} {...props} > - + { onClick={()=>setMode(mode == 'light' ? 'dark' : 'light')} color="inherit" > - + {theme.palette.mode === 'dark' ? ( ) : ( @@ -140,21 +139,14 @@ export const NavBar = ({ ...props }: NavBarProps) => { <> - - ) : ( diff --git a/src/theme.ts b/src/theme.ts index a2b7d7ee..d5c7c02a 100755 --- a/src/theme.ts +++ b/src/theme.ts @@ -20,6 +20,10 @@ export const getDesignTokens = (mode: PaletteMode ) => ({ }, error: { main: red.A400, + }, + background:{ + default: '#FFF', + paper: '#FFF', } }: //Dark @@ -33,39 +37,50 @@ export const getDesignTokens = (mode: PaletteMode ) => ({ }, error: { main: red.A400, + }, + background:{ + default: '#000', + paper: '#000', } } }, - dark:{ - palette:{ - primary: { - main: '#000', - contrastText: '#FFF', - }, - secondary: { - main: techGold, - }, - error: { - main: red.A400, - } - } - } }) // Create a theme instance. -export const getThemeComponents = (mode : PaletteMode ) =>({ - mode, - components: { - ...(mode == 'light')? - { +// export const getThemeComponents = (mode : PaletteMode ) =>({ +// typography: { +// fontFamily:[ +// '-apple-system', +// 'BlinkMacSystemFont', +// '"Segoe UI"', +// 'Roboto', +// '"Helvetica Neue"', +// 'Arial', +// 'sans-serif', +// '"Apple Color Emoji"', +// '"Segoe UI Emoji"', +// '"Segoe UI Symbol"', +// ].join(','), +// }, +// mode, +// components: { +// ...(mode == 'light')? +// { - }: - { - MuiAppBar:{ - styleOverrides:{ +// }: +// { +// MuiAppBar:{ +// styleOverrides:{ - } - } - } - } -}) +// }, +// }, +// MuiDrawer: { +// styleOverrides: { +// paper: { +// backgroundColor: "000", +// } +// } +// } +// } +// } +// }) From 289966d8e91a6cc15d68d565b7b9f71cb148db18 Mon Sep 17 00:00:00 2001 From: Christian Tran Date: Tue, 10 Oct 2023 11:09:40 -0500 Subject: [PATCH 08/16] fix(dark mode): added skeleton for component flash that would occur for user --- context/AuthContext.tsx | 7 ++++++- src/components/NavBar.tsx | 21 +++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/context/AuthContext.tsx b/context/AuthContext.tsx index 2426ad6d..9be8ebeb 100644 --- a/context/AuthContext.tsx +++ b/context/AuthContext.tsx @@ -24,6 +24,7 @@ import { createContext, useContext, useEffect, useState } from 'react'; type TAuthContext = { user: FirebaseAuthUser | null; + loading: Boolean; signInWithProvider: TSignInAction; signWithMagic: TSignInAction; logout: () => void; @@ -36,16 +37,20 @@ export const useAuth = () => useContext(AuthContext); // eslint-disable-next-line no-undef export const AuthContextProvider = ({ children }: TContextProviderProps) => { const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); const { setAlert } = useAlert(); useEffect(() => { + setLoading(true); const unsubscribe = onAuthStateChanged( auth, (user: FirebaseAuthUser | null) => { if (user) { setUser(user); + setLoading(false); } else { setUser(null); + setLoading(false); } }, ); @@ -153,7 +158,7 @@ export const AuthContextProvider = ({ children }: TContextProviderProps) => { return ( {children} diff --git a/src/components/NavBar.tsx b/src/components/NavBar.tsx index 8b30e66d..2a0907ca 100755 --- a/src/components/NavBar.tsx +++ b/src/components/NavBar.tsx @@ -7,7 +7,7 @@ import { FirebaseAuthUser } from '@context/types'; import Brightness4Icon from '@mui/icons-material/Brightness4'; import Brightness7Icon from '@mui/icons-material/Brightness7'; import GitHubIcon from '@mui/icons-material/GitHub'; -import { IconButton, Tooltip, useColorScheme } from '@mui/material'; +import { IconButton, Skeleton, Tooltip, useColorScheme } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -22,13 +22,7 @@ export interface MenuLinksProps { } export const NavBar = ({ ...props }: NavBarProps) => { - const authContext = useAuth(); - - let user: FirebaseAuthUser | null = null; - - if (authContext) { - ({ user } = authContext); - } + const {user, loading} = useAuth(); const { handleLoginOpen } = useMenu(); @@ -42,7 +36,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { }; const profileMenuItems: MenuLinksProps = { - // 'My Account': '/user/...', + // 'My Account': '/user/', 'My Reviews': '/user/reviews', }; @@ -111,7 +105,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { onClick={()=>setMode(mode == 'light' ? 'dark' : 'light')} color="inherit" > - + {theme.palette.mode === 'dark' ? ( ) : ( @@ -135,7 +129,7 @@ export const NavBar = ({ ...props }: NavBarProps) => { {/* User Profile Side */} - {!user ? ( + {!loading ? <> {!user ? ( <>