diff --git a/src/LocationProvider.tsx b/src/LocationProvider.tsx new file mode 100644 index 0000000..4b8fd92 --- /dev/null +++ b/src/LocationProvider.tsx @@ -0,0 +1,43 @@ +import { WindowLocation } from "@reach/router" +import React, { FC, PropsWithChildren, useMemo } from "react" + +function appendSlashToPath(path: string): string { + return path.endsWith("/") ? path : `${path}/` +} + +export interface ILocationContextInterface { + location: WindowLocation | void + isHome: boolean + isMatchingPath: (path: string) => boolean +} + +interface ILocationProviderProps { + location: WindowLocation | void +} + +export const LocationContext = React.createContext( + null +) + +export const LocationProvider: FC< + PropsWithChildren +> = ({ children, location }) => { + const memoizedContextValue = useMemo( + () => ({ + location, + isHome: location ? location.pathname === "/" : false, + isMatchingPath: (path: string) => { + return location + ? appendSlashToPath(location.pathname).startsWith(path) + : false + }, + }), + [location] + ) + + return ( + + {children} + + ) +} diff --git a/src/components/ResourcesSidebar/index.tsx b/src/components/ResourcesSidebar/index.tsx index 001451d..76c6953 100644 --- a/src/components/ResourcesSidebar/index.tsx +++ b/src/components/ResourcesSidebar/index.tsx @@ -10,6 +10,7 @@ import { ThemeToggler } from "../ThemeToggler" import useSidebar from "./../../hooks/useSidebar" import * as SC from "./styles" import useBuildTree from "./useBuildTree" +import useMatchingPath from "./useMatchingPath" const ALL_RESOURCES = graphql` query { @@ -49,6 +50,10 @@ function plantTree(item: IFileOrFolder, index?: number, firstLevel?: boolean) { function Folder({ item }: { item: IFolder }) { const [collapsed, setCollapse] = useState(true) + useMatchingPath(item.path, () => { + setCollapse(false) + }) + function toggleCollapse() { setCollapse(prevState => !prevState) } @@ -66,6 +71,11 @@ function Folder({ item }: { item: IFolder }) { const FirstLevelFolder = memo( ({ item, index }: { item: IFolder; index: number }) => { const { current, setCurrent } = useSidebar() + + useMatchingPath(item.path, () => { + setCurrent(index) + }) + const collapsed = current !== index return ( diff --git a/src/components/ResourcesSidebar/useMatchingPath.tsx b/src/components/ResourcesSidebar/useMatchingPath.tsx new file mode 100644 index 0000000..a0db98e --- /dev/null +++ b/src/components/ResourcesSidebar/useMatchingPath.tsx @@ -0,0 +1,12 @@ +import { useEffect } from "react" +import useLocation from "../../hooks/useLocation" + +export default function useMatchingPath(path: string, callback: () => void) { + const { isMatchingPath } = useLocation() + + useEffect(() => { + if (isMatchingPath(path)) { + callback() + } + }, []) +} diff --git a/src/hooks/useLocation.tsx b/src/hooks/useLocation.tsx new file mode 100644 index 0000000..730a9f5 --- /dev/null +++ b/src/hooks/useLocation.tsx @@ -0,0 +1,12 @@ +import { useContext } from "react" +import { ILocationContextInterface, LocationContext } from "../LocationProvider" + +export default function useLocation(): ILocationContextInterface { + const locationContext = useContext(LocationContext) + + if (!locationContext) { + throw Error("Need context") + } + + return locationContext +} diff --git a/src/layouts/Layout/index.tsx b/src/layouts/Layout/index.tsx index 339806f..cc9fcf9 100644 --- a/src/layouts/Layout/index.tsx +++ b/src/layouts/Layout/index.tsx @@ -13,12 +13,13 @@ import { Footer } from "../../components/Footer" import { Header } from "../../components/Header" import { WavesBottom } from "../../components/Waves" import { GlobalStyles } from "../../globalStyles" +import useLocation from "../../hooks/useLocation" import { useLockBodyScroll } from "../../hooks/useLockBodyScroll" import { ThemeProvider } from "../../ThemeProvider" import * as SC from "./styles" -export const Layout: FC = ({ children, location }) => { - const isHome = location ? location.pathname === "/" : false +export const Layout: FC = ({ children }) => { + const { isHome } = useLocation() const { locked, unlock } = useLockBodyScroll() useEffect(() => { diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx index 8b4f54b..10dcad1 100644 --- a/src/layouts/index.tsx +++ b/src/layouts/index.tsx @@ -1,4 +1,6 @@ +import { WindowLocation } from "@reach/router" import React, { PropsWithChildren } from "react" +import { LocationProvider } from "../LocationProvider" import { Layout } from "./Layout" import { ResourcesLayout } from "./ResourcesLayout" @@ -10,11 +12,15 @@ export default function BaseLayout({ pageContext: { layout?: string } - location: Location + location: WindowLocation }>) { - if (pageContext.layout === "resources") { - return {children} - } - - return {children} + return ( + + {pageContext.layout === "resources" ? ( + {children} + ) : ( + {children} + )} + + ) }