From 53b6fd4f7eb60e6ac07b269331da527aee87daf6 Mon Sep 17 00:00:00 2001 From: Gage Krumbach Date: Thu, 11 Jul 2024 09:15:08 -0500 Subject: [PATCH] update side nav --- src/components/shared/Layout.tsx | 2 +- src/components/shared/SideNavigation.tsx | 298 ++++++++++++++++------- 2 files changed, 214 insertions(+), 86 deletions(-) diff --git a/src/components/shared/Layout.tsx b/src/components/shared/Layout.tsx index a5f508b06b9..665d65d77a7 100644 --- a/src/components/shared/Layout.tsx +++ b/src/components/shared/Layout.tsx @@ -20,7 +20,7 @@ export const Layout = ({ className={!!sidebar ? "pf-u-h-100vh" : undefined} isManagedSidebar sidebar={ - sidebar ? : undefined + sidebar ? : undefined } header={ { - function nestSections(sections: AsciiDocSection[]): NestedAsciiDocSection[] { - const nestedSections: NestedAsciiDocSection[] = []; - - const sectionMap: Record = {}; - // create a map of sections using their `id` as key - sections.forEach((section) => { - sectionMap[section.id] = { ...section, sections: [] }; - }); - - // assign child sections to their parent - sections.forEach((section) => { - const parentId = section.parentId; - if (parentId && sectionMap[parentId]) { - sectionMap[parentId].sections.push(sectionMap[section.id]); - } else { - nestedSections.push(sectionMap[section.id]); - } - }); - - return nestedSections; - } + config: SideNavItemConfig[]; + location: Location; + toc: { [key: string]: AsciiDocSection[] }; +}; - const renderSection = (section: NestedAsciiDocSection, slug: string) => { - if (section.sections.length > 0) { - return ( - - {section.sections.map(section => renderSection(section, slug))} - - ) - } - else { - return ( - - - {section.name} - - - ) - } +const NavSection = ({ + section, + slug, + location, + toc, +}: { + section: NestedAsciiDocSection; + slug: string; + location: Location; + toc: { + [key: string]: AsciiDocSection[]; + }; +}) => { + function isParentOfCurrentSection( + currentSection: AsciiDocSection, + parentSection: AsciiDocSection, + page: AsciiDocSection[] + ): boolean { + if (currentSection.id === parentSection.id) { + return true; + } + if (!currentSection.parentId) { + return false; } + const currentSectionsParent = page.find( + (s) => s.id === currentSection.parentId + ); + if (!currentSectionsParent) { + return false; + } + + return isParentOfCurrentSection(currentSectionsParent, parentSection, page); + } - const renderNavItem = (item: SideNavItemConfig) => { - if (toc[item.slug]) { - return ( - - {nestSections(toc[item.slug]).map(section => renderSection(section, item.slug))} - - ) - } - else if (item.children) { - return ( - - {item.children.map(i => renderNavItem(i))} - - ) - } - else { - return ( - - - {item.title} - - - ) - } + function isChildSectionActive( + slug: string, + section: AsciiDocSection + ): boolean { + if (location.pathname.includes(slug)) { + const page = toc[slug]; + const currentSection = page.find((s) => location.hash.includes(s.id)); + if (!currentSection) { + return false; + } + return isParentOfCurrentSection(currentSection, section, page); } + return false; + } + + const [isExpanded, setIsExpanded] = React.useState(true); + + const isActive = + location.hash.includes(section.id) || isChildSectionActive(slug, section); + if (section.sections.length > 0) { + return ( + { + navigate(`${slug}#${section.id}`); + setIsExpanded(!isExpanded); + }} + buttonProps={{ + className: css( + navStyles.navLink, + isActive && navStyles.modifiers.current + ), + }} + > + {section.sections.map((section) => ( + + ))} + + ); + } else { return ( - - ) - -} \ No newline at end of file + + {section.name} + + ); + } +}; + +const CustomNavExpandable = ({ + item, + toc, + location, +}: { + item: SideNavItemConfig; + toc: { [key: string]: AsciiDocSection[] }; + location: Location; +}) => { + const isActive = location.pathname.includes(item.slug); + const [isExpanded, setIsExpanded] = React.useState(isActive); + + function nestSections(sections: AsciiDocSection[]): NestedAsciiDocSection[] { + const nestedSections: NestedAsciiDocSection[] = []; + + const sectionMap: Record = {}; + // create a map of sections using their `id` as key + sections.forEach((section) => { + sectionMap[section.id] = { ...section, sections: [] }; + }); + + // assign child sections to their parent + sections.forEach((section) => { + const parentId = section.parentId; + if (parentId && sectionMap[parentId]) { + sectionMap[parentId].sections.push(sectionMap[section.id]); + } else { + nestedSections.push(sectionMap[section.id]); + } + }); + + return nestedSections; + } + + return ( + { + navigate(item.slug); + setIsExpanded(!isExpanded); + }} + buttonProps={{ + className: css( + navStyles.navLink, + isActive && navStyles.modifiers.current + ), + }} + > + {nestSections(toc[item.slug]).map((section) => ( + + ))} + + ); +}; + +export const SideNavigation = ({ + config, + location, + toc = {}, +}: SideNavigationProps) => { + const renderNavItem = (item: SideNavItemConfig) => { + const isActive = location.pathname.includes(item.slug); + if (toc[item.slug]) { + return ( + + ); + } else if (item.children) { + return ( + + {item.children.map((i) => renderNavItem(i))} + + ); + } else { + return ( + + {item.title} + + ); + } + }; + + return ( + + ); +};