From d15243ce18ffba7b2d53ddae6f3926a3c8a5679a Mon Sep 17 00:00:00 2001 From: Gabriele Antonini <106664971+gabriele-ct@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:05:14 +0200 Subject: [PATCH] fix: issue with scroll to item during page navigation (#1821) * fix: issue with scroll to item during page navigation * chore: handle edge cases * chore: changeset * chore: fix other internal navigation issue --- .changeset/good-vans-teach.md | 5 ++ .../src/components/content-pagination.js | 3 - .../src/layouts/internals/sidebar.js | 58 ++++++++++++------- .../src/layouts/internals/sidebar.utils.js | 27 +++++++-- 4 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 .changeset/good-vans-teach.md diff --git a/.changeset/good-vans-teach.md b/.changeset/good-vans-teach.md new file mode 100644 index 0000000000..7e329fc0b1 --- /dev/null +++ b/.changeset/good-vans-teach.md @@ -0,0 +1,5 @@ +--- +'@commercetools-docs/gatsby-theme-docs': patch +--- + +Fix issue with sidebar navigation not scrolling to the actual expanded item when navigating through pages diff --git a/packages/gatsby-theme-docs/src/components/content-pagination.js b/packages/gatsby-theme-docs/src/components/content-pagination.js index 94322617fb..781f8769b3 100644 --- a/packages/gatsby-theme-docs/src/components/content-pagination.js +++ b/packages/gatsby-theme-docs/src/components/content-pagination.js @@ -245,9 +245,6 @@ export const PurePagination = (props) => { ? getNextPageLink(activeChapter, currentPageLinkIndex) : getNextPageLinkSub(activeChapter, currentPageLinkIndex); - console.log('previousPage', previousPage, hasPagination); - console.log('nextPage', nextPage); - return ( {hasPagination && previousPage?.path ? ( diff --git a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js index 7afc99456c..c4c71726bb 100644 --- a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js +++ b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.js @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import PropTypes from 'prop-types'; import { Location } from '@reach/router'; import { Link, withPrefix } from 'gatsby'; @@ -26,7 +26,12 @@ import { SidebarContextApi, SidebarContextState, } from '../../components/sidebar-context'; -import { getItemDescendants, getItemAncestors } from './sidebar.utils'; +import { + getItemDescendants, + getItemAncestors, + isRightChapter, + isRightChapterRecursive, +} from './sidebar.utils'; const ReleaseNotesIcon = createStyledIcon(Icons.ReleaseNotesSvgIcon); @@ -315,30 +320,37 @@ const ChapterItem = styled.div` `; const Chapter = (props) => { - // TODO: move this logic to context initialization - const isRightChapter = (chapter) => { - return chapter.pages.find((page) => - page.pages - ? isRightChapter(page) - : props.location.pathname.includes(page.path) - ); - }; - const ssrExpanded = isRightChapter(props.chapter); + const isSelectedChapter = isRightChapter(props.chapter, props.location); + const isSSRSelectedChapter = isRightChapterRecursive( + props.chapter, + props.location + ); const { ancestorsMap } = useSidebarNavigationItems(); const chapterId = `${props.level}-${props.index}`; const { setExpandedChapters } = useContext(SidebarContextApi); const { expandedChapters } = useContext(SidebarContextState); - if (ssrExpanded && !expandedChapters) { - const initialState = getItemAncestors( - props.level, - props.index, - ancestorsMap - ); - if (initialState !== expandedChapters) { - setExpandedChapters(initialState); + useEffect(() => { + if (isSelectedChapter) { + const initialState = getItemAncestors( + props.level, + props.index, + ancestorsMap + ); + const expandedItemsList = + initialState.length > 0 ? initialState : [chapterId]; + + if (expandedChapters) { + // this case happens in all the subsequent interactions with the UI (client side) + setExpandedChapters([...expandedChapters, ...expandedItemsList]); + } else { + // this case happens only on first page load (SSR) + setExpandedChapters(expandedItemsList); + } } - } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [props.location]); // we want to re-calculate the menu state only when the URL changes const toggleExpand = () => { if (expandedChapters?.includes(chapterId)) { @@ -357,9 +369,13 @@ const Chapter = (props) => { setExpandedChapters(updatedState); } }; + + // the state of each chapter is based on the (expandedChapters) which is stored in the context. + // The initial SSR state (when context is not available) is handled by isSelecteChapter const isExpanded = expandedChapters ? expandedChapters.includes(chapterId) - : ssrExpanded; + : isSSRSelectedChapter; + const elemId = `sidebar-chapter-${props.level}-${props.index}`; const chapterTitle = props.level === 0 ? props.chapter.chapterTitle : props.chapter.title; diff --git a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.utils.js b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.utils.js index dea3f3e9fe..e0b3ff1005 100644 --- a/packages/gatsby-theme-docs/src/layouts/internals/sidebar.utils.js +++ b/packages/gatsby-theme-docs/src/layouts/internals/sidebar.utils.js @@ -3,17 +3,36 @@ export const getItemDescendants = (level, index, ancestorsMap) => { if (level === 1) { return [chapterId]; } else { - const ancestorsArray = ancestorsMap.filter((element) => + const descendantsArray = ancestorsMap.filter((element) => element.includes(chapterId) ); - return [].concat(...ancestorsArray); + return [].concat(...descendantsArray); } }; export const getItemAncestors = (level, index, ancestorsMap) => { const chapterId = `${level}-${index}`; - const ancestorsArray = ancestorsMap.filter((element) => - element.includes(chapterId) + const ancestorsArray = ancestorsMap.filter( + (element) => element.includes(chapterId) && element.indexOf(chapterId) > 0 ); return [].concat(...ancestorsArray); }; + +export const isRightChapter = (chapter, loc) => { + return ( + chapter.pages.find((page) => loc.pathname.includes(page.path)) !== undefined + ); +}; + +export const isRightChapterRecursive = (chapter, loc) => { + if (!loc) { + return false; + } + return ( + chapter.pages.find((page) => + page.pages + ? isRightChapterRecursive(page, loc) + : loc.pathname.includes(page.path) + ) !== undefined + ); +};