Skip to content

Commit

Permalink
Fix pharos-site sidenav on mobile screens (#782)
Browse files Browse the repository at this point in the history
* feat(site): toggle sidenav on mobile sizes

When Pharos v14 was release the default behavior of the sidenav changed
and broke the site navigation

* fix(site): add a check before using the window object for Gatsby SSR
  • Loading branch information
brentswisher authored Jul 19, 2024
1 parent 4f8c37d commit 90dbc66
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-beds-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ithaka/pharos-site': patch
---

Fix mobile sidenav
21 changes: 16 additions & 5 deletions packages/pharos-site/src/components/Sidenav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { useLayoutEffect, useState } from 'react';
import { useEffect, useLayoutEffect, useState } from 'react';
import type { FC, ReactElement } from 'react';
import { withPrefix, useStaticQuery, graphql } from 'gatsby';
import { useLocation } from '@reach/router';

import handleLinkClick from '../utils/handleLinkClick';
import { siteBrand__title, siteBrand__subTitle, sidenav } from './Sidenav.module.css';

const Sidenav: FC = () => {
interface SidenavProps {
isOpen: boolean;
showCloseButton?: boolean;
}

const Sidenav: FC<SidenavProps> = ({ isOpen, showCloseButton }) => {
const [Display, setDisplay] = useState<ReactElement | null>(null);
const Pharos =
typeof window !== `undefined` ? require('@ithaka/pharos/lib/react-components') : null;
Expand All @@ -23,7 +28,7 @@ const Sidenav: FC = () => {
}
`);

useLayoutEffect(() => {
useEffect(() => {
const {
PharosSidenav,
PharosSidenavSection,
Expand Down Expand Up @@ -55,7 +60,13 @@ const Sidenav: FC = () => {
};

const content = (
<PharosSidenav mainContentId="skip-link" open={true} className={sidenav}>
<PharosSidenav
mainContentId="skip-link"
id="site-sidenav"
open={isOpen}
hasCloseButton={showCloseButton}
className={sidenav}
>
<PharosLink href="/" slot="top" flex onClick={handleLinkClick}>
<div>
<div className={siteBrand__title}>{data.site.siteMetadata.title}</div>
Expand Down Expand Up @@ -167,7 +178,7 @@ const Sidenav: FC = () => {
);

setDisplay(content);
}, [Pharos, data, location]);
}, [Pharos, data, location, isOpen, showCloseButton]);

return Display;
};
Expand Down
1 change: 1 addition & 0 deletions packages/pharos-site/src/components/layout.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ a {
@media screen and (width <= 1055px) {
.container {
grid-template-areas:
'sidenav'
'main'
'footer';
grid-template-columns: auto;
Expand Down
73 changes: 54 additions & 19 deletions packages/pharos-site/src/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import type { FC, ReactElement } from 'react';
import type { WindowLocation } from '@reach/router';
import Sidenav from './Sidenav';
Expand Down Expand Up @@ -36,35 +36,70 @@ const Layout: FC<LayoutProps> = ({ children, location, fill }) => {
typeof window !== `undefined` ? require('@ithaka/pharos/lib/react-components') : null;

const [MainContent, setMainContent] = useState<ReactElement | null>(null);
const mobileBreakpoint = 1055;
const [isMobile, setIsMobile] = useState<boolean>(
typeof window !== `undefined` ? window.innerWidth < mobileBreakpoint : false
);
const [isSidenavDisplayed, setIsSidenavDisplayed] = useState<boolean>(!isMobile);
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const { PharosLink, PharosLayout } = Pharos;
const { PharosLink, PharosLayout, PharosButton } = Pharos;
const currentRef = containerRef.current;
const resizeObserver = new ResizeObserver(() => {
const windowWidth = window.innerWidth;
setIsSidenavDisplayed(windowWidth >= mobileBreakpoint);
setIsMobile(windowWidth < mobileBreakpoint);
});

const body = (
<main className={main}>
<div className={topBar}>
<PharosLink id="skip-link" skip href="#sidenav-skip-link" isOnBackground>
Skip to main navigation
</PharosLink>
</div>
<PharosLayout
preset="1-col--sidenav-comfy"
className={`${content} ${fill ? content___fill : ''}`}
rowGap={fill ? PharosSpacing5X : '0'}
>
{fill ? children : <div className={page}>{children}</div>}
</PharosLayout>
</main>
<>
<Sidenav isOpen={isSidenavDisplayed} showCloseButton={isMobile} />
<main className={main}>
<div className={topBar}>
<PharosLink id="skip-link" skip href="#sidenav-skip-link" isOnBackground>
Skip to main navigation
</PharosLink>
</div>
<PharosLayout preset="1-col--sidenav-comfy" rowGap={fill ? PharosSpacing5X : '0'}>
<PharosButton
variant="subtle"
icon="menu"
data-sidenav-id="site-sidenav"
a11yLabel="Open side navigation"
style={{
display: isMobile ? 'block' : 'none',
paddingTop: 'var(--pharos-spacing-2-x)',
}}
/>
</PharosLayout>
<PharosLayout
preset="1-col--sidenav-comfy"
className={`${content} ${fill ? content___fill : ''}`}
rowGap={fill ? PharosSpacing5X : '0'}
>
{fill ? children : <div className={page}>{children}</div>}
</PharosLayout>
</main>
</>
);

setMainContent(body);
}, [Pharos, children, fill]);

if (currentRef) {
resizeObserver.observe(currentRef);
}
return () => {
if (currentRef) {
resizeObserver.unobserve(currentRef);
}
};
}, [Pharos, children, fill, isMobile, isSidenavDisplayed]);

return (
<div className={container}>
<div className={container} ref={containerRef}>
<Fonts />
<SEO title={pageName || 'Home'} pathname={location?.pathname} />
<Sidenav />
{MainContent}
<Footer />
</div>
Expand Down
6 changes: 6 additions & 0 deletions packages/pharos-site/src/components/variables.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@
--sidebar-spacing-padding: var(--pharos-spacing-one-and-a-half-x);
--main-spacing-padding: var(--pharos-spacing-7-x);
}

@media screen and (width <= 1055px) {
:root {
--main-spacing-padding: var(--pharos-spacing-2-x);
}
}

0 comments on commit 90dbc66

Please sign in to comment.