From 9f25901e0f434aaa9332ebdc72ed5c4b207c03f6 Mon Sep 17 00:00:00 2001 From: Seung Park Date: Wed, 9 Oct 2024 15:09:47 -0400 Subject: [PATCH] move correction to tab context --- src/components/Tabs/index.js | 33 +++++------------------------- src/components/Tabs/tab-context.js | 15 ++++++++++++-- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/components/Tabs/index.js b/src/components/Tabs/index.js index c25cbc8ab..5610f013b 100644 --- a/src/components/Tabs/index.js +++ b/src/components/Tabs/index.js @@ -1,12 +1,10 @@ -import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { isEmpty } from 'lodash'; +import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { css, cx } from '@leafygreen-ui/emotion'; import { Tabs as LeafyTabs, Tab as LeafyTab } from '@leafygreen-ui/tabs'; import { palette } from '@leafygreen-ui/palette'; import { CodeProvider } from '../Code/code-context'; import ComponentFactory from '../ComponentFactory'; -import { ContentsContext } from '../Contents/contents-context'; import { HeadingContextProvider, useHeadingContext } from '../../context/heading-context'; import { theme } from '../../theme/docsTheme'; import { reportAnalytics } from '../../utils/report-analytics'; @@ -105,13 +103,9 @@ const productLandingTabContentStyling = css` } `; -const activeMethodIncludesActiveTab = (activeTabValues, activeTabsSelector) => - activeTabValues.every((tabValue) => activeTabsSelector['tab']?.includes(tabValue)); - const Tabs = ({ nodeData: { children, options = {} }, page, ...rest }) => { const { activeTabs, selectors, setActiveTab } = useContext(TabContext); const tabIds = children.map((child) => getTabId(child)); - const { activeSelectorIds, setActiveSelectorIds } = useContext(ContentsContext); const tabsetName = options.tabset || generateAnonymousTabsetName(tabIds); const [activeTab, setActiveTabIndex] = useState(() => { // activeTabIdx at build time should be -1 if tabsetName !== drivers @@ -120,26 +114,6 @@ const Tabs = ({ nodeData: { children, options = {} }, page, ...rest }) => { return activeTabIdx > -1 ? activeTabIdx : 0; }); - const correctedSelectorIds = useMemo(() => { - if (isEmpty(activeTabs)) { - return; - } - if (!activeMethodIncludesActiveTab(Object.values(activeTabs), activeSelectorIds)) { - return { - ...activeSelectorIds, - tab: Object.values(activeTabs), - }; - } - }, [activeSelectorIds, activeTabs]); - - useEffect(() => { - if (!correctedSelectorIds) { - return; - } - - setActiveSelectorIds(correctedSelectorIds); - }, [correctedSelectorIds, setActiveSelectorIds]); - const scrollAnchorRef = useRef(); // Hide tabset if it includes the :hidden: option, or if it is controlled by a dropdown selector const isHidden = options.hidden || Object.keys(selectors).includes(tabsetName); @@ -169,6 +143,9 @@ const Tabs = ({ nodeData: { children, options = {} }, page, ...rest }) => { const handleClick = useCallback( (index) => { + if (activeTab === index) { + return; + } const tabId = tabIds[index]; const priorAnchorOffset = getPosition(scrollAnchorRef.current).y; @@ -183,7 +160,7 @@ const Tabs = ({ nodeData: { children, options = {} }, page, ...rest }) => { window.scrollTo(0, getPosition(scrollAnchorRef.current).y + window.scrollY - priorAnchorOffset); }, 40); }, - [setActiveTab, tabIds, tabsetName] // eslint-disable-line react-hooks/exhaustive-deps + [activeTab, setActiveTab, tabIds, tabsetName] ); return ( diff --git a/src/components/Tabs/tab-context.js b/src/components/Tabs/tab-context.js index c7cc663f9..24aac1aa3 100644 --- a/src/components/Tabs/tab-context.js +++ b/src/components/Tabs/tab-context.js @@ -5,9 +5,11 @@ * child components to read and update */ -import React, { useEffect, useReducer, useRef } from 'react'; +import React, { useContext, useEffect, useReducer, useRef } from 'react'; +import { isEmpty } from 'lodash'; import { getLocalValue, setLocalValue } from '../../utils/browser-storage'; import { DRIVER_ICON_MAP } from '../icons/DriverIconMap'; +import { ContentsContext } from '../Contents/contents-context'; import { makeChoices } from './make-choices'; const defaultContextValue = { @@ -54,6 +56,7 @@ const getLocalTabs = (localTabs, selectors) => const TabProvider = ({ children, selectors = {} }) => { // init value to {} to match server and client side const [activeTabs, setActiveTab] = useReducer(reducer, {}); + const { setActiveSelectorIds } = useContext(ContentsContext); const initLoaded = useRef(false); @@ -61,7 +64,15 @@ const TabProvider = ({ children, selectors = {} }) => { // dont update local value on initial load if (!initLoaded.current) return; setLocalValue('activeTabs', activeTabs); - }, [activeTabs]); + + if (isEmpty(activeTabs)) { + return; + } + + // on Tab update, update the active selector ids + // so headings can be shown/hidden + setActiveSelectorIds((activeSelectorIds) => ({ ...activeSelectorIds, tab: Object.values(activeTabs) })); + }, [activeTabs, setActiveSelectorIds]); // initial effect to read from local storage // used in an effect to keep SSG HTML consistent