mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-23 14:06:59 +02:00
refactor(v2): mobile dropdown navbar: expand when subitem become active (#5168)
This commit is contained in:
parent
007e901354
commit
818fb3956b
3 changed files with 63 additions and 5 deletions
|
@ -7,21 +7,49 @@
|
|||
|
||||
import React, {useState, useRef, useEffect} from 'react';
|
||||
import clsx from 'clsx';
|
||||
import {useLocation} from '@docusaurus/router';
|
||||
import {
|
||||
isSamePath,
|
||||
useCollapsible,
|
||||
Collapsible,
|
||||
useLocalPathname,
|
||||
} from '@docusaurus/theme-common';
|
||||
import type {
|
||||
DesktopOrMobileNavBarItemProps,
|
||||
Props,
|
||||
} from '@theme/NavbarItem/DropdownNavbarItem';
|
||||
import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem';
|
||||
|
||||
import {NavLink} from '@theme/NavbarItem/DefaultNavbarItem';
|
||||
import NavbarItem from '@theme/NavbarItem';
|
||||
|
||||
const dropdownLinkActiveClass = 'dropdown__link--active';
|
||||
|
||||
function isItemActive(
|
||||
item: LinkLikeNavbarItemProps,
|
||||
localPathname: string,
|
||||
): boolean {
|
||||
if (isSamePath(item.to, localPathname)) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
item.activeBaseRegex &&
|
||||
new RegExp(item.activeBaseRegex).test(localPathname)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function containsActiveItems(
|
||||
items: readonly LinkLikeNavbarItemProps[],
|
||||
localPathname: string,
|
||||
): boolean {
|
||||
return items.some((item) => isItemActive(item, localPathname));
|
||||
}
|
||||
|
||||
function DropdownNavbarItemDesktop({
|
||||
items,
|
||||
position,
|
||||
|
@ -102,12 +130,20 @@ function DropdownNavbarItemMobile({
|
|||
position: _position, // Need to destructure position from props so that it doesn't get passed on.
|
||||
...props
|
||||
}: DesktopOrMobileNavBarItemProps) {
|
||||
const {pathname} = useLocation();
|
||||
const {collapsed, toggleCollapsed} = useCollapsible({
|
||||
initialState: () =>
|
||||
!items?.some((item) => isSamePath(item.to, pathname)) ?? true,
|
||||
const localPathname = useLocalPathname();
|
||||
const containsActive = containsActiveItems(items, localPathname);
|
||||
|
||||
const {collapsed, toggleCollapsed, setCollapsed} = useCollapsible({
|
||||
initialState: () => !containsActive,
|
||||
});
|
||||
|
||||
// Expand/collapse if any item active after a navigation
|
||||
useEffect(() => {
|
||||
if (containsActive) {
|
||||
setCollapsed(!containsActive);
|
||||
}
|
||||
}, [localPathname, containsActive]);
|
||||
|
||||
return (
|
||||
<li
|
||||
className={clsx('menu__list-item', {
|
||||
|
|
|
@ -63,3 +63,5 @@ export {
|
|||
AnnouncementBarProvider,
|
||||
useAnnouncementBar,
|
||||
} from './utils/announcementBarUtils';
|
||||
|
||||
export {useLocalPathname} from './utils/useLocalPathname';
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import {useLocation} from '@docusaurus/router';
|
||||
|
||||
// Get the pathname of current route, without the optional site baseUrl
|
||||
// - /docs/myDoc => /docs/myDoc
|
||||
// - /baseUrl/docs/myDoc => /docs/myDoc
|
||||
export function useLocalPathname(): string {
|
||||
const {
|
||||
siteConfig: {baseUrl},
|
||||
} = useDocusaurusContext();
|
||||
const {pathname} = useLocation();
|
||||
return pathname.replace(baseUrl, '/');
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue