diff --git a/apps/next-app/pages/_app.page.tsx b/apps/next-app/pages/_app.page.tsx index 3cd7749a4..1ceb489ad 100644 --- a/apps/next-app/pages/_app.page.tsx +++ b/apps/next-app/pages/_app.page.tsx @@ -7,7 +7,6 @@ import { AnalyticsProvider } from "@chair-flight/react/analytics"; import { StopResizeAnimation } from "@chair-flight/react/components"; import { theme } from "@chair-flight/react/containers"; import { trpc } from "@chair-flight/trpc/client"; -import type { DefaultColorScheme } from "@mui/joy/styles/types"; import type { AppProps } from "next/app"; import type { FunctionComponent } from "react"; import "@fontsource/public-sans"; @@ -16,6 +15,13 @@ if (typeof document === "undefined") { React.useLayoutEffect = React.useEffect; } +if (typeof document !== "undefined") { + // temporary fix to rollback the custom scheme colors. + // remove me if you are reading this in 2024 + localStorage.setItem("joy-color-scheme-light", "light"); + localStorage.setItem("joy-color-scheme-dark", "dark"); +} + const DynamicToaster = dynamic( () => import("@chair-flight/react/components").then((m) => m.Toaster), { loading: () => null, ssr: false }, @@ -34,11 +40,7 @@ const App: FunctionComponent = ({ Component, pageProps }) => { Welcome to chair-flight! - + diff --git a/apps/next-app/pages/index.page.tsx b/apps/next-app/pages/index.page.tsx index fc70df120..93dece8a6 100644 --- a/apps/next-app/pages/index.page.tsx +++ b/apps/next-app/pages/index.page.tsx @@ -5,20 +5,28 @@ import { default as AirplaneTicketIcon } from "@mui/icons-material/AirplaneTicke import { default as ChevronRightIcon } from "@mui/icons-material/ChevronRight"; import { default as FlightTakeoffIcon } from "@mui/icons-material/FlightTakeoff"; import { default as StyleIcon } from "@mui/icons-material/Style"; -import { Box, styled, Grid, Typography, Button, Link, Divider } from "@mui/joy"; +import { + Box, + styled, + Grid, + Typography, + Button, + Link, + Divider, + GlobalStyles, +} from "@mui/joy"; import { CoolSlidingThing, CountUp, ModuleSelectionButton, Typical, - useThemeSwitcher, + getGlobalColorScheme, } from "@chair-flight/react/components"; import { AppHead, LayoutPublic } from "@chair-flight/react/containers"; import { getTrpcHelper, preloadContentForStaticRender, } from "@chair-flight/trpc/server"; -import type { ThemeColor } from "@chair-flight/react/components"; import type { GetStaticProps, NextPage } from "next"; const fadeIn = keyframes` @@ -37,12 +45,14 @@ const RightContainer = styled(Grid)` } `; -export type IndexPageProps = { +type IndexPageProps = { numberOfAtplQuestions: number; numberOf737Questions: number; numberOfFlashcards: number; }; +type Theme = "737" | "atpl" | "prep"; + const MEDIA_LONG_SCREEN = "@media (min-height: 560px) and (min-width: 440px)"; export const IndexPage: NextPage = ({ @@ -51,11 +61,9 @@ export const IndexPage: NextPage = ({ numberOf737Questions, }) => { const rightSideContainer = useRef(null); - const [activeTheme, setActiveTheme] = useState(); - const [, setCurrentTheme] = useThemeSwitcher(); + const [activeTheme, setActiveTheme] = useState(); - const goToTheme = (theme: ThemeColor) => { - setCurrentTheme(theme); + const goToTheme = (theme: Theme) => { setActiveTheme(theme); const top = rightSideContainer.current?.offsetTop ?? 0; setTimeout( @@ -68,6 +76,21 @@ export const IndexPage: NextPage = ({ return ( }> + { + const palette = t.colorSchemes.light.palette; + switch (activeTheme) { + case "737": + return getGlobalColorScheme(palette.primaryRose); + case "prep": + return getGlobalColorScheme(palette.primaryTeal); + case "atpl": + return getGlobalColorScheme(palette.primaryBlue); + default: + return getGlobalColorScheme(palette.primaryBlue); + } + }} + /> = ({ "improve your knowledge... for free!", ].join("")} /> - = ({ "Explore questions, learning objectives, and theory reviews ", "from the EASA QB ATPL exams.", ].join("")} - active={activeTheme === "blue"} + active={activeTheme === "atpl"} icon={} - onClick={() => goToTheme("blue")} + onClick={() => goToTheme("atpl")} showMoreHref="/modules/atpl" /> = ({ "Use our flash cards to practice answering open ended ", "questions and secure your first job.", ].join("")} - active={activeTheme === "teal"} + active={activeTheme === "prep"} icon={} - onClick={() => goToTheme("teal")} + onClick={() => goToTheme("prep")} showMoreHref="/modules/prep" /> = ({ sx={{ mb: { xs: 1, md: 2 } }} color={"rose"} title={"737 Type rating"} - active={activeTheme === "rose"} + active={activeTheme === "737"} description={[ `Prepare or review your theory knowledge for a type rating `, `on the Boeing 737 with ${numberOf737Questions} questions.`, ].join("")} icon={} - onClick={() => goToTheme("rose")} + onClick={() => goToTheme("737")} showMoreHref="/modules/737" /> @@ -236,7 +258,7 @@ export const IndexPage: NextPage = ({ })} > - {activeTheme === "blue" && ( + {activeTheme === "atpl" && ( = ({ )} - {activeTheme === "teal" && ( + {activeTheme === "prep" && ( = ({ /> )} - {activeTheme === "rose" && ( + {activeTheme === "737" && ( = ({ collectionId, seed, }) => { - const [, setCurrentTheme] = useThemeSwitcher(); - - useEffect(() => setCurrentTheme("teal"), [setCurrentTheme]); - return ( - + = ({ , ])} - + ); }; diff --git a/apps/next-app/pages/modules/prep/flashcards/[collectionId]/index.page.tsx b/apps/next-app/pages/modules/prep/flashcards/[collectionId]/index.page.tsx index a416cb94c..cb6ce49fe 100644 --- a/apps/next-app/pages/modules/prep/flashcards/[collectionId]/index.page.tsx +++ b/apps/next-app/pages/modules/prep/flashcards/[collectionId]/index.page.tsx @@ -1,7 +1,7 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { Grid } from "@mui/joy"; -import { Flashcard, useThemeSwitcher } from "@chair-flight/react/components"; -import { AppHead, LayoutPublic } from "@chair-flight/react/containers"; +import { Flashcard } from "@chair-flight/react/components"; +import { AppHead, LayoutModulePrep } from "@chair-flight/react/containers"; import { getTrpcHelper, preloadContentForStaticRender, @@ -31,12 +31,8 @@ const FlashcardWithOwnControl: FunctionComponent = ( const FlashcardsThemePage: NextPage = ({ flashcards, }) => { - const [, setCurrentTheme] = useThemeSwitcher(); - - useEffect(() => setCurrentTheme("teal"), [setCurrentTheme]); - return ( - + = ({ ))} - + ); }; diff --git a/apps/next-app/pages/modules/prep/flashcards/index.page.tsx b/apps/next-app/pages/modules/prep/flashcards/index.page.tsx index d8f9240dd..be451b5a3 100644 --- a/apps/next-app/pages/modules/prep/flashcards/index.page.tsx +++ b/apps/next-app/pages/modules/prep/flashcards/index.page.tsx @@ -1,4 +1,3 @@ -import { useEffect } from "react"; import { default as Image } from "next/image"; import { Button, @@ -10,8 +9,7 @@ import { CardCover, Box, } from "@mui/joy"; -import { useThemeSwitcher } from "@chair-flight/react/components"; -import { AppHead, LayoutPublic } from "@chair-flight/react/containers"; +import { AppHead, LayoutModulePrep } from "@chair-flight/react/containers"; import { getTrpcHelper, preloadContentForStaticRender, @@ -29,12 +27,8 @@ type flashcardsIndexPageProps = { const QuestionsIndexPage: NextPage = ({ flashcardCollections, }) => { - const [, setCurrentTheme] = useThemeSwitcher(); - - useEffect(() => setCurrentTheme("teal"), [setCurrentTheme]); - return ( - + = ({ Once you are satisfied with the answer, Flip the card to see if you are close enough. - + Have fun! @@ -126,7 +120,7 @@ const QuestionsIndexPage: NextPage = ({ ))} - + ); }; diff --git a/libs/react/components/src/sidebar/sidebar.tsx b/libs/react/components/src/sidebar/sidebar.tsx index 09fceca01..7ea5ecd83 100644 --- a/libs/react/components/src/sidebar/sidebar.tsx +++ b/libs/react/components/src/sidebar/sidebar.tsx @@ -128,9 +128,8 @@ export const Sidebar = forwardRef( borderTop: 0, }, - // TODO fix this, should be a sibling selector - "&": { - borderBottom: 0, + "& + .filler": { + borderBottom: "1px", }, "&:hover": { @@ -145,10 +144,6 @@ export const Sidebar = forwardRef( borderLeftColor: "var(--joy-palette-primary-plainColor)", bgcolor: "transparent", }, - - "&.toggle-button": { - borderBottom: 0, - }, }, ["& .chevron"]: { @@ -165,7 +160,7 @@ export const Sidebar = forwardRef( > isMobileOpen && setMobileOpen(false)}> {children.filter((c) => !c.props.bottom)} - + {children.filter((c) => c.props.bottom)} ({ + '[data-joy-color-scheme="dark"], [data-joy-color-scheme="light"]': { + "--joy-palette-primary-50": palette[50], + "--joy-palette-primary-100": palette[100], + "--joy-palette-primary-200": palette[200], + "--joy-palette-primary-300": palette[300], + "--joy-palette-primary-400": palette[400], + "--joy-palette-primary-500": palette[500], + "--joy-palette-primary-600": palette[600], + "--joy-palette-primary-700": palette[700], + "--joy-palette-primary-800": palette[800], + "--joy-palette-primary-900": palette[900], + "--joy-palette-primary-mainChannel": palette.mainChannel, + "--joy-palette-primary-darkChannel": palette.darkChannel, + "--joy-palette-primary-lightChannel": palette.lightChannel, + }, +}); diff --git a/libs/react/components/src/theme/index.ts b/libs/react/components/src/theme/index.ts index 9655665e8..7d415077f 100644 --- a/libs/react/components/src/theme/index.ts +++ b/libs/react/components/src/theme/index.ts @@ -1,4 +1,3 @@ export { theme } from "./theme"; -export { useThemeSwitcher } from "./useThemeSwitcher"; +export { getGlobalColorScheme } from "./get-global-color-scheme"; export { StopResizeAnimation } from "./stop-resize-animation"; -export type { ThemeColor } from "./useThemeSwitcher"; diff --git a/libs/react/components/src/theme/theme.ts b/libs/react/components/src/theme/theme.ts index 05f941c0d..691c1535a 100644 --- a/libs/react/components/src/theme/theme.ts +++ b/libs/react/components/src/theme/theme.ts @@ -19,15 +19,10 @@ declare module "@mui/joy/styles" { "body-xs": true; } - interface ColorSchemeOverrides { - light: false; - dark: false; - lightBlue: true; - lightTeal: true; - lightRose: true; - darkBlue: true; - darkTeal: true; - darkRose: true; + interface PaletteOverrides { + primaryBlue: true; + primaryTeal: true; + primaryRose: true; } } @@ -43,6 +38,9 @@ const extraColors = { "700": "#12467B", "800": "#0A2744", "900": "#051423", + mainChannel: "11 107 203", + darkChannel: "18 70 123", + lightChannel: "199 223 247", }, primaryTeal: { "50": "#f0fdf4", @@ -55,6 +53,9 @@ const extraColors = { "700": "#15803d", "800": "#166534", "900": "#14532d", + mainChannel: "34 197 94", + darkChannel: "21 128 61", + lightChannel: "187 247 208", }, primaryRose: { "50": "#ffebee", @@ -67,6 +68,9 @@ const extraColors = { "700": "#d32f2f", "800": "#c62828", "900": "#b71c1c", + mainChannel: "244 67 54", + darkChannel: "211 47 47", + lightChannel: "239 154 154", }, }; @@ -91,53 +95,21 @@ export const theme: CssVarsThemeOptions = extendTheme({ "title-sm": undefined, }, colorSchemes: { - lightBlue: { + light: { ...basicTheme.colorSchemes.light, palette: { ...basicTheme.colorSchemes.light.palette, ...extraColors, ...lightBackground, + primary: extraColors.primaryBlue, }, }, - lightTeal: { - ...basicTheme.colorSchemes.light, - palette: { - ...basicTheme.colorSchemes.light.palette, - ...extraColors, - ...lightBackground, - primary: extraColors.primaryTeal, - }, - }, - lightRose: { - ...basicTheme.colorSchemes.light, - palette: { - ...basicTheme.colorSchemes.light.palette, - ...extraColors, - ...lightBackground, - primary: extraColors.primaryRose, - }, - }, - darkBlue: { - ...basicTheme.colorSchemes.dark, - palette: { - ...basicTheme.colorSchemes.dark.palette, - ...extraColors, - }, - }, - darkTeal: { - ...basicTheme.colorSchemes.dark, - palette: { - ...basicTheme.colorSchemes.dark.palette, - ...extraColors, - primary: extraColors.primaryTeal, - }, - }, - darkRose: { + dark: { ...basicTheme.colorSchemes.dark, palette: { ...basicTheme.colorSchemes.dark.palette, ...extraColors, - primary: extraColors.primaryRose, + primary: extraColors.primaryBlue, }, }, }, diff --git a/libs/react/components/src/theme/useThemeSwitcher.ts b/libs/react/components/src/theme/useThemeSwitcher.ts deleted file mode 100644 index bc59c94a6..000000000 --- a/libs/react/components/src/theme/useThemeSwitcher.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { useColorScheme } from "@mui/joy"; -import type { DefaultColorScheme } from "@mui/joy/styles/types"; - -export type ThemeColor = "rose" | "teal" | "blue"; -export type ThemeColorSchemeLight = "lightRose" | "lightTeal" | "lightBlue"; - -export const useThemeSwitcher = (): [ - currentTheme: "rose" | "teal" | "blue", - setCurrentTheme: (theme: "rose" | "teal" | "blue") => void, -] => { - const { setColorScheme, colorScheme } = useColorScheme(); - const [currentTheme, setStateCurrentTheme] = useState("blue"); - - const setCurrentTheme = useCallback( - (theme: ThemeColor) => { - const themeWithUppercase = theme[0].toUpperCase() + theme.slice(1); - setColorScheme({ - light: `light${themeWithUppercase}` as DefaultColorScheme, - dark: `dark${themeWithUppercase}` as DefaultColorScheme, - }); - }, - [setColorScheme], - ); - - useEffect(() => { - const newCurrentTheme = (colorScheme ?? "blue") - .toLocaleLowerCase() - .replace("light", "") - .replace("dark", ""); - - if (["rose", "teal", "blue"].includes(newCurrentTheme)) { - setStateCurrentTheme(newCurrentTheme as ThemeColor); - } else { - setCurrentTheme("blue"); - } - }, [colorScheme, setCurrentTheme]); - - return [currentTheme, setCurrentTheme]; -}; diff --git a/libs/react/containers/src/index.ts b/libs/react/containers/src/index.ts index 298427072..acf79b09f 100644 --- a/libs/react/containers/src/index.ts +++ b/libs/react/containers/src/index.ts @@ -13,5 +13,6 @@ export * from "./tests/tests-overview"; export * from "./theme"; export * from "./layouts/layout-module-737"; export * from "./layouts/layout-module-atpl"; +export * from "./layouts/layout-module-prep"; export * from "./layouts/layout-public"; export * from "./user/user-settings"; diff --git a/libs/react/containers/src/layouts/layout-module-737/layout-module-737.tsx b/libs/react/containers/src/layouts/layout-module-737/layout-module-737.tsx index 4d37fb5f0..37865473a 100644 --- a/libs/react/containers/src/layouts/layout-module-737/layout-module-737.tsx +++ b/libs/react/containers/src/layouts/layout-module-737/layout-module-737.tsx @@ -1,14 +1,14 @@ -import { type FunctionComponent, useEffect } from "react"; +import { type FunctionComponent } from "react"; import { useRouter } from "next/router"; import { default as TestIcon } from "@mui/icons-material/FlightTakeoffOutlined"; import { default as QuestionsIcon } from "@mui/icons-material/QuizOutlined"; import { default as SettingsIcon } from "@mui/icons-material/SettingsOutlined"; -import { Box, listItemContentClasses } from "@mui/joy"; +import { Box, listItemContentClasses, GlobalStyles } from "@mui/joy"; import { AppLogo, Sidebar, SidebarListItem, - useThemeSwitcher, + getGlobalColorScheme, } from "@chair-flight/react/components"; export type LayoutModule737Props = { @@ -22,16 +22,18 @@ export const LayoutModule737: FunctionComponent = ({ fixedHeight, noPadding, }) => { - const [, setCurrentTheme] = useThemeSwitcher(); const router = useRouter(); const isQuestions = router.asPath.includes("questions"); const isTests = router.asPath.includes("tests"); const isSettings = router.asPath.includes("settings"); - useEffect(() => setCurrentTheme("rose"), [setCurrentTheme]); - return ( <> + { + return getGlobalColorScheme(t.colorSchemes.light.palette.primaryRose); + }} + /> = ({ children, fixedHeight, noPadding }) => { - const [, setCurrentTheme] = useThemeSwitcher(); const router = useRouter(); const isQuestions = router.asPath.includes("questions"); const isTests = router.asPath.includes("tests"); const isLearningObjectives = router.asPath.includes("learning-objectives"); const isSettings = router.asPath.includes("settings"); - useEffect(() => setCurrentTheme("blue"), [setCurrentTheme]); - return ( <> diff --git a/libs/react/containers/src/layouts/layout-module-prep/index.ts b/libs/react/containers/src/layouts/layout-module-prep/index.ts new file mode 100644 index 000000000..d12215664 --- /dev/null +++ b/libs/react/containers/src/layouts/layout-module-prep/index.ts @@ -0,0 +1 @@ +export * from "./layout-module-prep"; diff --git a/libs/react/containers/src/layouts/layout-module-prep/layout-module-prep.tsx b/libs/react/containers/src/layouts/layout-module-prep/layout-module-prep.tsx new file mode 100644 index 000000000..ba8d96f39 --- /dev/null +++ b/libs/react/containers/src/layouts/layout-module-prep/layout-module-prep.tsx @@ -0,0 +1,36 @@ +import { Box, GlobalStyles } from "@mui/joy"; +import { getGlobalColorScheme } from "@chair-flight/react/components"; +import type { FunctionComponent, ReactNode } from "react"; + +export type LayoutModulePrepProps = { + children: ReactNode; + fixedHeight?: boolean; + noPadding?: boolean; +}; + +const HEIGHT = `100vh`; + +export const LayoutModulePrep: FunctionComponent = ({ + children, + fixedHeight, + noPadding, +}) => ( + <> + { + return getGlobalColorScheme(t.colorSchemes.light.palette.primaryTeal); + }} + /> + + +);