Skip to content

Commit

Permalink
fix: left nav duplicate active selection and jumping scroll (#819)
Browse files Browse the repository at this point in the history
* v1.17.2

* v1.17.3

* fix: left nav is active bug and jumping scroll

* fix: query selector classname

* chore: add testing example

* chore: comments

* fix: update scollOffset name

* fix: tweak hooks logic

* fix: remove hook reference

* fix: only set scroll top when it isn't defined

* fix: remove nav context scroll function

* fix: remove testing pages

Co-authored-by: Vince Picone <vpicone@gmail.com>
Co-authored-by: Scott Strubberg <sstrubberg@protonmail.com>
Co-authored-by: Vince Picone <Vincent.Patrick.Picone@ibm.com>
  • Loading branch information
4 people authored May 19, 2020
1 parent 0a8b2a0 commit 5aa20b9
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 9 deletions.
28 changes: 25 additions & 3 deletions packages/gatsby-theme-carbon/src/components/LeftNav/LeftNav.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from 'react';
import React, { useContext, useRef, useEffect } from 'react';
import classnames from 'classnames';
import { SideNav, SideNavItems } from 'carbon-components-react';
import { useNavItems } from './LeftNavItemProvider';
Expand All @@ -11,14 +11,36 @@ import LeftNavWrapper from './LeftNavWrapper';
import { sideNavDark } from './LeftNav.module.scss';

const LeftNav = (props) => {
const { leftNavIsOpen } = useContext(NavContext);
const { leftNavIsOpen, leftNavScrollTop, setLeftNavScrollTop } = useContext(
NavContext
);

const sideNavRef = useRef();
const sideNavListRef = useRef();

useEffect(() => {
sideNavListRef.current = sideNavRef.current.querySelector('.sidenav-list');
}, []);

useEffect(() => {
sideNavListRef.current.addEventListener('scroll', (e) => {
setLeftNavScrollTop(e.target.scrollTop);
});
}, [setLeftNavScrollTop]);

useEffect(() => {
if (leftNavScrollTop >= 0 && !sideNavListRef?.current.scrollTop) {
sideNavListRef.current.scrollTop = leftNavScrollTop;
}
}, [leftNavScrollTop]);

const navItems = useNavItems();

// TODO: replace old addon website styles with sass modules, move to wrapper
return (
<LeftNavWrapper expanded={leftNavIsOpen}>
<SideNav
ref={sideNavRef}
expanded
defaultExpanded
aria-label="Side navigation"
Expand All @@ -31,7 +53,7 @@ const LeftNav = (props) => {
props.theme !== 'dark' && !props.homepage,
})}
>
<SideNavItems>
<SideNavItems className="sidenav-list">
{navItems.map((item, i) => (
<LeftNavItem items={item.pages} category={item.title} key={i} />
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import usePathprefix from '../../util/hooks/usePathprefix';
const LeftNavItem = (props) => {
const { items, category } = props;
const { toggleNavState } = useContext(NavContext);
const closeLeftNav = () => toggleNavState('leftNavIsOpen', 'close');
const closeLeftNav = () => {
toggleNavState('leftNavIsOpen', 'close');
};
const pathPrefix = usePathprefix();

return (
Expand Down Expand Up @@ -66,10 +68,8 @@ const LeftNavItem = (props) => {
const SubNavItems = ({ items, pathname, onClick }) =>
items.map((item, i) => {
const hasActiveTab =
item.path.split('/') > 3
? item.path.split('/')[3] === pathname.split('/')[3]
: item.path.split('/')[2] === pathname.split('/')[2];

`${item.path.split('/')[1]}/${item.path.split('/')[2]}` ===
`${pathname.split('/')[1]}/${pathname.split('/')[2]}`;
return (
<SideNavMenuItem
to={`${item.path}`}
Expand Down
8 changes: 7 additions & 1 deletion packages/gatsby-theme-carbon/src/util/context/NavContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const NavContext = React.createContext({
searchIsOpen: false,
switcherIsOpen: false,
isManagingFocus: false,
leftNavScrollOffset: 0,
});

const reducer = (state, action) => {
Expand All @@ -19,14 +20,16 @@ const reducer = (state, action) => {
};
export const NavContextProvider = ({ children }) => {
const [
{ leftNavIsOpen, searchIsOpen, switcherIsOpen },
{ leftNavIsOpen, searchIsOpen, switcherIsOpen, leftNavScrollOffset },
dispatch,
] = useReducer(reducer, {
leftNavIsOpen: false,
searchIsOpen: false,
switcherIsOpen: false,
});

const [leftNavScrollTop, setLeftNavScrollTop] = useState(0);

const toggleNavState = (nav, type) => {
dispatch({ nav, type });
};
Expand All @@ -40,6 +43,9 @@ export const NavContextProvider = ({ children }) => {
toggleNavState,
isManagingFocus,
setIsManagingFocus,
leftNavScrollOffset,
leftNavScrollTop,
setLeftNavScrollTop,
};

return <NavContext.Provider value={value}>{children}</NavContext.Provider>;
Expand Down

1 comment on commit 5aa20b9

@vercel
Copy link

@vercel vercel bot commented on 5aa20b9 May 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.