From faf8cc102196bf8bf542a034dd8abb90aecbec80 Mon Sep 17 00:00:00 2001 From: Suhaha Date: Mon, 24 Nov 2025 15:58:49 +0800 Subject: [PATCH 1/3] feat: enhance navigation state management with session storage - Updated the LeftNavTree component to support saving and retrieving navigation item IDs from session storage, improving user experience by maintaining state across sessions. - Modified the calcExpandedIds function to accept an optional targetId for more precise matching. - Implemented helper functions to handle session storage interactions for navigation items. --- .../Layout/Navigation/LeftNavTree.tsx | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/components/Layout/Navigation/LeftNavTree.tsx b/src/components/Layout/Navigation/LeftNavTree.tsx index c31c02d67..3f834714a 100644 --- a/src/components/Layout/Navigation/LeftNavTree.tsx +++ b/src/components/Layout/Navigation/LeftNavTree.tsx @@ -72,11 +72,18 @@ function StyledTreeItem(props: StyledTreeItemProps) { ); } -const calcExpandedIds = (data: RepoNavLink[], targetLink: string) => { +const calcExpandedIds = ( + data: RepoNavLink[], + targetLink: string, + targetId?: string +) => { const ids: string[] = []; const treeForeach = (data: RepoNavLink[], parents: string[] = []): void => { data.forEach((item) => { - if (item.link === targetLink) { + const isMatch = targetId + ? item.link === targetLink && item.id === targetId + : item.link === targetLink; + if (isMatch) { ids.push(...parents); ids.push(item.id); return; @@ -90,6 +97,29 @@ const calcExpandedIds = (data: RepoNavLink[], targetLink: string) => { return ids; }; +// Session storage key prefix for nav item id +const NAV_ITEM_ID_STORAGE_KEY = "nav_item_id_"; + +// Get nav item id from session storage for a given path +const getNavItemIdFromStorage = (path: string): string | null => { + if (typeof window === "undefined") return null; + try { + return sessionStorage.getItem(`${NAV_ITEM_ID_STORAGE_KEY}${path}`); + } catch { + return null; + } +}; + +// Save nav item id to session storage for a given path +const saveNavItemIdToStorage = (path: string, id: string): void => { + if (typeof window === "undefined") return; + try { + sessionStorage.setItem(`${NAV_ITEM_ID_STORAGE_KEY}${path}`, id); + } catch { + // Ignore storage errors + } +}; + export default function ControlledTreeView(props: { data: RepoNav; current: string; @@ -97,10 +127,16 @@ export default function ControlledTreeView(props: { const { data, current: currentUrl } = props; const [expanded, setExpanded] = React.useState(() => { - return calcExpandedIds(data, currentUrl); + const storedId = getNavItemIdFromStorage(currentUrl); + return calcExpandedIds(data, currentUrl, storedId || undefined); }); const [selected, setSelected] = React.useState(() => { - const expandedIds = calcExpandedIds(data, currentUrl); + const storedId = getNavItemIdFromStorage(currentUrl); + const expandedIds = calcExpandedIds( + data, + currentUrl, + storedId || undefined + ); if (expandedIds.length) { return [expandedIds[expandedIds.length - 1]]; } @@ -110,7 +146,12 @@ export default function ControlledTreeView(props: { const theme = useTheme(); React.useEffect(() => { - const expandedIds = calcExpandedIds(data, currentUrl); + const storedId = getNavItemIdFromStorage(currentUrl); + const expandedIds = calcExpandedIds( + data, + currentUrl, + storedId || undefined + ); setExpanded(expandedIds); expandedIds.length && setSelected([expandedIds[expandedIds.length - 1]]); }, [data, currentUrl]); @@ -191,7 +232,13 @@ export default function ControlledTreeView(props: { key={item.id} to={item.link} style={{ width: "100%", color: "inherit" }} - onClick={(e) => e.stopPropagation()} + onClick={(e) => { + e.stopPropagation(); + // Save nav item id to session storage when clicked + if (item.link) { + saveNavItemIdToStorage(item.link, item.id); + } + }} > Date: Mon, 24 Nov 2025 16:03:03 +0800 Subject: [PATCH 2/3] refactor: simplify navigation state management in LeftNavTree component - Removed session storage interactions for expanded and selected navigation items, streamlining state management. - Updated the calcExpandedIds function calls to eliminate unnecessary parameters, enhancing clarity and performance. --- src/components/Layout/Navigation/LeftNavTree.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/Layout/Navigation/LeftNavTree.tsx b/src/components/Layout/Navigation/LeftNavTree.tsx index 3f834714a..4f033ae86 100644 --- a/src/components/Layout/Navigation/LeftNavTree.tsx +++ b/src/components/Layout/Navigation/LeftNavTree.tsx @@ -127,16 +127,10 @@ export default function ControlledTreeView(props: { const { data, current: currentUrl } = props; const [expanded, setExpanded] = React.useState(() => { - const storedId = getNavItemIdFromStorage(currentUrl); - return calcExpandedIds(data, currentUrl, storedId || undefined); + return calcExpandedIds(data, currentUrl); }); const [selected, setSelected] = React.useState(() => { - const storedId = getNavItemIdFromStorage(currentUrl); - const expandedIds = calcExpandedIds( - data, - currentUrl, - storedId || undefined - ); + const expandedIds = calcExpandedIds(data, currentUrl); if (expandedIds.length) { return [expandedIds[expandedIds.length - 1]]; } From d0b01d0ac71783e374ece99567e3d55919df5c2d Mon Sep 17 00:00:00 2001 From: Suhaha Date: Mon, 24 Nov 2025 16:35:39 +0800 Subject: [PATCH 3/3] refactor: simplify scroll behavior in scrollToElementIfInView function - Updated the scrollToElementIfInView function to directly call scrollIntoView with a "center" block option, removing unnecessary viewport checks and improving code clarity. --- src/shared/utils/index.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts index 72beeee6c..4b61f0ba6 100644 --- a/src/shared/utils/index.ts +++ b/src/shared/utils/index.ts @@ -289,15 +289,7 @@ export function isInViewport(element: HTMLElement) { export function scrollToElementIfInView( element: HTMLElement & { scrollIntoViewIfNeeded: () => void } ) { - const isVisiable = isInViewport(element); - if (isVisiable) { - return; - } - if (element.scrollIntoViewIfNeeded) { - element.scrollIntoViewIfNeeded(); - } else { - element.scrollIntoView({ block: "end" }); - } + element.scrollIntoView({ block: "center" }); } export type PageType = "home" | "tidb" | "tidbcloud" | undefined;