diff --git a/src/Layout.tsx b/src/Layout.tsx index 23fb1d7e..db4a69c7 100644 --- a/src/Layout.tsx +++ b/src/Layout.tsx @@ -16,6 +16,7 @@ export { scrollFadeMask } import React from 'react' import { getNavItemsWithComputed, NavItem, NavItemComponent } from './NavItemComponent.js' +import { Collapsible } from './MenuModal/Collapsible.js' import { parseMarkdownMini } from './parseMarkdownMini.js' import { usePageContext } from './renderer/usePageContext.js' import { ExternalLinks } from './ExternalLinks.js' @@ -135,6 +136,7 @@ function LayoutDocsPage({ children }: { children: React.ReactNode }) { } #nav-left { min-width: ${navLeftWidthMax + blockMargin}px; + transition: width 0.3s ease; } } .page-content { @@ -265,24 +267,57 @@ function getStyleNavLeft() { }` } -function NavigationContent(props: { - navItems: NavItem[] - showOnlyRelevant?: true -}) { +function NavigationContent(props: { navItems: NavItem[]; showOnlyRelevant?: true }) { const pageContext = usePageContext() const navItemsWithComputed = getNavItemsWithComputed(props.navItems, pageContext.urlPathname) - let navItemsRelevant = navItemsWithComputed - if (props.showOnlyRelevant) navItemsRelevant = navItemsRelevant.filter((navItemGroup) => navItemGroup.isRelevant) - const navContent = navItemsRelevant.map((navItem, i) => ) + if (props.showOnlyRelevant) { + const sections = groupBySections(navItemsWithComputed) + return ( +
+ {sections.map((section, i) => ( + } + disabled={false} + collapsedInit={!section.level1.isRelevant} + > + {section.children.map((navItem, j) => ( + + ))} + + ))} +
+ ) + } return (
- {navContent} + {navItemsWithComputed.map((navItem, i) => ( + + ))}
) } +type NavItemsSection = { + level1: ReturnType[number] + children: ReturnType +} +function groupBySections(navItems: ReturnType): NavItemsSection[] { + const sections: NavItemsSection[] = [] + let current: NavItemsSection | null = null + for (const navItem of navItems) { + if (navItem.level === 1) { + current = { level1: navItem, children: [] } + sections.push(current) + } else if (current) { + current.children.push(navItem) + } + } + return sections +} + function isNavLeftAlwaysHidden() { const pageContext = usePageContext() const { isLandingPage, navItemsDetached, pageDesign } = pageContext.resolved diff --git a/src/MenuModal/Collapsible.tsx b/src/MenuModal/Collapsible.tsx index d99af5ed..06c2a3e5 100644 --- a/src/MenuModal/Collapsible.tsx +++ b/src/MenuModal/Collapsible.tsx @@ -25,7 +25,7 @@ function Collapsible({ if (!disabled) { setIsAnimating(true) if (!collapsed) { - // If expanding, set height to current scroll height before animation + // If collapsing, set height to current scroll height before animation contentRef.current!.style.height = `${contentRef.current!.scrollHeight}px` // Force a reflow contentRef.current!.offsetHeight @@ -34,8 +34,8 @@ function Collapsible({ } } - const onTransitionEnd = () => { - setIsAnimating(false) + const onTransitionEnd = (e: React.TransitionEvent) => { + if (e.propertyName === 'height') setIsAnimating(false) } const showContent = disabled ? true : !collapsed @@ -50,6 +50,7 @@ function Collapsible({ onTransitionEnd={onTransitionEnd} style={{ height: !showContent ? 0 : isAnimating ? contentRef.current!.scrollHeight : 'auto', + width: !showContent ? 0 : 'auto', overflow: 'hidden', transition: 'none 0.3s ease', transitionProperty: 'height, margin-bottom', @@ -57,7 +58,7 @@ function Collapsible({ }} aria-expanded={showContent} > - {children} +
{children}
) diff --git a/src/NavItemComponent.css b/src/NavItemComponent.css index fe673bf9..405723d7 100644 --- a/src/NavItemComponent.css +++ b/src/NavItemComponent.css @@ -53,10 +53,12 @@ } } #nav-left & { - border-bottom: 3px solid var(--color-category); - padding-bottom: 2px; margin-top: 3px; margin-bottom: 10px; + .nav-item-title { + border-bottom: 3px solid var(--color-category); + padding-bottom: 2px; + } } } .nav-item-level-2 { @@ -110,6 +112,8 @@ #nav-left { .nav-item-level-1 { + display: flex; + cursor: pointer; margin-left: min(25px, max(5px, 30 * (1vw - 12.7px) - 5px)); } .nav-head-logo { @@ -120,4 +124,9 @@ .nav-item-level-4 { padding-left: min(30px, max(8px, 30 * (1vw - 12.7px))); } + .collapsible-icon { + position: static; + margin-left: auto; + padding-left: 6px; + } } diff --git a/src/NavItemComponent.tsx b/src/NavItemComponent.tsx index 43993908..56ad7da1 100644 --- a/src/NavItemComponent.tsx +++ b/src/NavItemComponent.tsx @@ -93,8 +93,10 @@ function NavItemComponent({ if (navItem.level === 1) { children = ( <> - {icon} - {children} + + {icon} + {children} + )