From bcb9e5fd7d354a4ff895428094c6dc34a43aac50 Mon Sep 17 00:00:00 2001 From: DrMint Date: Sun, 20 Feb 2022 13:49:44 +0100 Subject: [PATCH] Added foundation for a minimizable navbar --- src/components/AppLayout.tsx | 39 +++++++-- src/components/PanelComponents/NavOption.tsx | 29 +++++-- src/components/Panels/MainPanel.tsx | 86 ++++++++++++++++---- src/hooks/useMediaQuery.ts | 47 +++++++++++ src/tailwind.css | 12 +++ 5 files changed, 177 insertions(+), 36 deletions(-) create mode 100644 src/hooks/useMediaQuery.ts diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 327c857..633f80c 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -6,6 +6,7 @@ import { useSwipeable } from "react-swipeable"; import { useRouter } from "next/router"; import Button from "components/Button"; import { prettyLanguage } from "queries/helpers"; +import { useMediaDesktop, useMediaMobile } from "hooks/useMediaQuery"; type AppLayoutProps = { subPanel?: React.ReactNode; @@ -22,6 +23,9 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { const [mainPanelOpen, setMainPanelOpen] = useState(false); const [subPanelOpen, setSubPanelOpen] = useState(false); const [languagePanelOpen, setLanguagePanelOpen] = useState(false); + const [mainPanelReduced, setMainPanelReduced] = useState(false); + const isMobile = useMediaMobile(); + const isDesktop = useMediaDesktop(); const sensibilitySwipe = 1.1; const handlers = useSwipeable({ @@ -43,18 +47,22 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { }, }); - const mainPanelClass = - "fixed desktop:left-0 desktop:top-0 desktop:bottom-0 desktop:w-[20rem]"; - const subPanelClass = - "fixed desktop:left-[20rem] desktop:top-0 desktop:bottom-0 desktop:w-[20rem]"; + const mainPanelClass = `fixed desktop:left-0 desktop:top-0 desktop:bottom-0 transition-all ${ + mainPanelReduced ? "desktop:w-[8rem]" : "desktop:w-[20rem]" + }`; + const subPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:w-[20rem] transition-all ${ + mainPanelReduced ? " desktop:left-[8rem]" : "desktop:left-[20rem]" + }`; let contentPanelClass = ""; let turnSubIntoContent = false; if (props.subPanel && props.contentPanel) { - contentPanelClass = - "fixed desktop:left-[40rem] desktop:top-0 desktop:bottom-0 desktop:right-0"; + contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 transition-all ${ + mainPanelReduced ? "desktop:left-[28rem]" : "desktop:left-[40rem]" + }`; } else if (props.contentPanel) { - contentPanelClass = - "fixed desktop:left-[20rem] desktop:top-0 desktop:bottom-0 desktop:right-0"; + contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 transition-all ${ + mainPanelReduced ? "desktop:left-[8rem]" : "desktop:left-[20rem]" + }`; } else if (props.subPanel) { turnSubIntoContent = true; } @@ -114,7 +122,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { className={`fixed bg-dark inset-0 transition-opacity duration-500 ${turnSubIntoContent ? "z-10" : ""} ${ - mainPanelOpen || subPanelOpen + (mainPanelOpen || subPanelOpen) && isMobile ? "opacity-50" : "opacity-0 pointer-events-none touch-none" }`} @@ -150,9 +158,22 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { + {/* Main panel minimize button*/} +
setMainPanelReduced(!mainPanelReduced)} + > + +
+ {/* Language selection background */}
-
- {props.icon} -

{props.title}

- {props.subtitle &&

{props.subtitle}

} -
- - ); + if (props.reduced) { + return ( + +
+ {props.icon} +
+ + ); + } else { + return ( + +
+ {props.icon} +

{props.title}

+ {props.subtitle &&

{props.subtitle}

} +
+ + ); + } } else { return ( diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index 94746ec..3b2d209 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -10,38 +10,64 @@ import Markdown from "markdown-to-jsx"; type MainPanelProps = { langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]; setLanguagePanelOpen: Function; + reduced: boolean; }; export default function MainPanel(props: MainPanelProps): JSX.Element { const langui = props.langui; const router = useRouter(); + const reduced = props.reduced; + return (
-
-
+ {reduced ? ( +
-
+
-
props.setLanguagePanelOpen(true)}> - {router.locale ? ( - - ) : ( - "" - )} -

Accord’s Library

+ {router.locale ? ( +
props.setLanguagePanelOpen(true)}> + +
+ ) : ( + "" + )} +
+ ) : ( +
+
+ +
+ +
+ +
props.setLanguagePanelOpen(true)} + > + {router.locale ? ( + + ) : ( + "" + )} +

Accord’s Library

+
-
+ )} @@ -50,6 +76,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { icon="library_books" title={langui.main_library} subtitle={langui.main_library_description} + reduced={reduced} /> - - + + + + + - - + -
+ {reduced ? "" : } + +

{langui.main_licensing ? ( {langui.main_licensing} diff --git a/src/hooks/useMediaQuery.ts b/src/hooks/useMediaQuery.ts new file mode 100644 index 0000000..af83360 --- /dev/null +++ b/src/hooks/useMediaQuery.ts @@ -0,0 +1,47 @@ +import { useEffect, useState } from "react"; + +export default function useMediaQuery(query: string): boolean { + const getMatches = (query: string): boolean => { + // Prevents SSR issues + if (typeof window !== "undefined") { + return window.matchMedia(query).matches; + } + return false; + }; + + const [matches, setMatches] = useState(getMatches(query)); + + function handleChange() { + setMatches(getMatches(query)); + } + + useEffect(() => { + const matchMedia = window.matchMedia(query); + + // Triggered at the first client-side load and if query changes + handleChange(); + + // Listen matchMedia + matchMedia.addEventListener("change", handleChange); + + return () => { + matchMedia.removeEventListener("change", handleChange); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [query]); + + return matches; +} + +export function useMediaThin() { + return useMediaQuery("(max-width: 50ch)"); +} + +export function useMediaMobile() { + return useMediaQuery("(max-width: 150ch)"); +} + +export function useMediaDesktop() { + return useMediaQuery("(min-width: 150ch)"); +} + diff --git a/src/tailwind.css b/src/tailwind.css index f8d407c..b06e320 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -56,6 +56,18 @@ .prose { --tw-prose-bullets: theme("colors.dark") !important; + --tw-prose-quote-borders: theme("colors.dark") !important; } + .prose footer { + @apply border-t-[3px] border-dotted pt-6; + } + + .prose footer > div { + @apply my-2 px-6 py-4 rounded-xl; + } + + .prose footer > div:target { + @apply bg-mid shadow-inner-sm shadow-dark; + } }