From 4d33da3d0812a2a82ae54e3d59265e5aef200094 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Mon, 16 May 2022 16:49:11 +0800 Subject: [PATCH] fix(theme-classic): consistently apply the right active class name for all navbar items --- .../src/theme-classic.d.ts | 16 +++-------- .../theme/NavbarItem/DefaultNavbarItem.tsx | 12 ++++++++- .../src/theme/NavbarItem/DocNavbarItem.tsx | 16 +++-------- .../theme/NavbarItem/DocSidebarNavbarItem.tsx | 9 +------ .../DocsVersionDropdownNavbarItem.tsx | 1 - .../theme/NavbarItem/DropdownNavbarItem.tsx | 12 ++++----- .../LocaleDropdownNavbarItem/index.tsx | 3 +-- .../src/theme/NavbarItem/NavbarNavLink.tsx | 8 +----- .../src/theme/NavbarItem/index.tsx | 27 +++++++------------ .../src/theme/NavbarItem/utils.ts | 13 --------- 10 files changed, 36 insertions(+), 81 deletions(-) delete mode 100644 packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index ef8c33023fd2..a795630da3a2 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -806,7 +806,8 @@ declare module '@theme/NavbarItem/NavbarNavLink' { readonly exact?: boolean; readonly label?: ReactNode; readonly html?: string; - readonly prependBaseUrlToHref?: string; + readonly prependBaseUrlToHref?: boolean; + readonly isDropdownLink?: boolean; } export default function NavbarNavLink(props: Props): JSX.Element; @@ -974,22 +975,11 @@ declare module '@theme/NavbarItem' { } & SearchNavbarItemProps) ); - export type Types = Props['type']; + export type NavbarItemType = Props['type']; export default function NavbarItem(props: Props): JSX.Element; } -declare module '@theme/NavbarItem/utils' { - /** - * On desktop and mobile, we would apply different class names for dropdown - * items. - * @see https://github.com/facebook/docusaurus/pull/5431 - */ - export function getInfimaActiveClassName( - mobile?: boolean, - ): `${'menu' | 'navbar'}__link--active`; -} - declare module '@theme/PaginatorNavLink' { import type {ReactNode} from 'react'; import type {PropNavigationLink} from '@docusaurus/plugin-content-docs'; diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx index 7036b2b6c12e..21d22bb012ee 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DefaultNavbarItem.tsx @@ -8,12 +8,21 @@ import React from 'react'; import clsx from 'clsx'; import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type { DesktopOrMobileNavBarItemProps, Props, } from '@theme/NavbarItem/DefaultNavbarItem'; +/** + * On desktop and mobile, we would apply different class names for dropdown + * items. + * @see https://github.com/facebook/docusaurus/pull/5431 + */ +const getInfimaActiveClassName = ( + mobile?: boolean, +): `${'menu' | 'navbar'}__link--active` => + mobile ? 'menu__link--active' : 'navbar__link--active'; + function DefaultNavbarItemDesktop({ className, isDropdownItem = false, @@ -25,6 +34,7 @@ function DefaultNavbarItemDesktop({ isDropdownItem ? 'dropdown__link' : 'navbar__item navbar__link', className, )} + isDropdownLink={isDropdownItem} {...props} /> ); diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx index 797ef1ec2d50..76df1591ba90 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx @@ -6,11 +6,9 @@ */ import React from 'react'; -import clsx from 'clsx'; import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; import {useLayoutDoc} from '@docusaurus/theme-common'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type {Props} from '@theme/NavbarItem/DocNavbarItem'; export default function DocNavbarItem({ @@ -27,20 +25,14 @@ export default function DocNavbarItem({ return null; } - const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile); - return ( + activeDoc?.path === doc.path || + (!!activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar) + } label={staticLabel ?? doc.id} to={doc.path} /> diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx index 874605bcf1a1..08771f8aa6c7 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocSidebarNavbarItem.tsx @@ -6,11 +6,9 @@ */ import React from 'react'; -import clsx from 'clsx'; import {useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; import {useLayoutDocsSidebar} from '@docusaurus/theme-common'; import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem'; -import {getInfimaActiveClassName} from '@theme/NavbarItem/utils'; import type {Props} from '@theme/NavbarItem/DocSidebarNavbarItem'; export default function DocSidebarNavbarItem({ @@ -26,16 +24,11 @@ export default function DocSidebarNavbarItem({ `DocSidebarNavbarItem: Sidebar with ID "${sidebarId}" doesn't have anything to be linked to.`, ); } - const activeDocInfimaClassName = getInfimaActiveClassName(props.mobile); - return ( activeDoc?.sidebar === sidebarId} label={label ?? sidebarLink.label} to={sidebarLink.path} /> diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx index b351eeeef1a8..2bfef7cb4265 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocsVersionDropdownNavbarItem.tsx @@ -41,7 +41,6 @@ export default function DocsVersionDropdownNavbarItem({ activeDocContext?.alternateDocVersions[version.name] ?? getVersionMainDoc(version); return { - isNavLink: true, label: version.label, to: versionDoc.path, isActive: () => version === activeDocContext?.activeVersion, diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx index ca5e03d92f12..3803cfec458d 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DropdownNavbarItem.tsx @@ -22,8 +22,6 @@ import type { } from '@theme/NavbarItem/DropdownNavbarItem'; import type {LinkLikeNavbarItemProps} from '@theme/NavbarItem'; -const dropdownLinkActiveClass = 'dropdown__link--active'; - function isItemActive( item: LinkLikeNavbarItemProps, localPathname: string, @@ -51,6 +49,7 @@ function DropdownNavbarItemDesktop({ items, position, className, + onClick, ...props }: DesktopOrMobileNavBarItemProps) { const dropdownRef = useRef(null); @@ -114,12 +113,12 @@ function DropdownNavbarItemDesktop({ ? nextNavbarItem : // Next item is another dropdown; focus on the inner // anchor element instead so there's outline - nextNavbarItem.querySelector('a'); - (targetItem as HTMLElement).focus(); + nextNavbarItem.querySelector('a')!; + targetItem.focus(); } } }} - activeClassName={dropdownLinkActiveClass} + activeClassName="dropdown__link--active" {...childItemProps} key={i} /> @@ -133,6 +132,7 @@ function DropdownNavbarItemMobile({ items, className, position, // Need to destructure position from props so that it doesn't get passed on. + onClick, ...props }: DesktopOrMobileNavBarItemProps) { const localPathname = useLocalPathname(); @@ -172,7 +172,7 @@ function DropdownNavbarItemMobile({ locale === currentLocale, }; }); diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/NavbarNavLink.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/NavbarNavLink.tsx index 94157e97eec5..050c6ed5c7f7 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/NavbarNavLink.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/NavbarNavLink.tsx @@ -13,8 +13,6 @@ import {isRegexpStringMatch} from '@docusaurus/theme-common'; import IconExternalLink from '@theme/IconExternalLink'; import type {Props} from '@theme/NavbarItem/NavbarNavLink'; -const dropdownLinkActiveClass = 'dropdown__link--active'; - export default function NavbarNavLink({ activeBasePath, activeBaseRegex, @@ -22,7 +20,7 @@ export default function NavbarNavLink({ href, label, html, - activeClassName = '', + isDropdownLink, prependBaseUrlToHref, ...props }: Props): JSX.Element { @@ -32,7 +30,6 @@ export default function NavbarNavLink({ const activeBaseUrl = useBaseUrl(activeBasePath); const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true}); const isExternalLink = label && href && !isInternalUrl(href); - const isDropdownLink = activeClassName === dropdownLinkActiveClass; // Link content is set through html XOR label const linkContentProps = html @@ -64,9 +61,6 @@ export default function NavbarNavLink({ activeBaseRegex diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx index ca3253143a16..0096e2bdb1e3 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx @@ -7,31 +7,22 @@ import React from 'react'; import ComponentTypes from '@theme/NavbarItem/ComponentTypes'; -import {type Props as DropdownNavbarItemProps} from '@theme/NavbarItem/DropdownNavbarItem'; -import type {Types, Props} from '@theme/NavbarItem'; +import type {NavbarItemType, Props} from '@theme/NavbarItem'; -const getNavbarItemComponent = (type: NonNullable) => { - const component = ComponentTypes[type]; - if (!component) { - throw new Error(`No NavbarItem component found for type "${type}".`); - } - return component; -}; - -function getComponentType(type: Types, isDropdown: boolean) { +function normalizeComponentType(type: NavbarItemType, props: object) { // Backward compatibility: navbar item with no type set // but containing dropdown items should use the type "dropdown" if (!type || type === 'default') { - return isDropdown ? 'dropdown' : 'default'; + return 'items' in props ? 'dropdown' : 'default'; } - return type as NonNullable; + return type; } export default function NavbarItem({type, ...props}: Props): JSX.Element { - const componentType = getComponentType( - type, - (props as DropdownNavbarItemProps).items !== undefined, - ); - const NavbarItemComponent = getNavbarItemComponent(componentType); + const componentType = normalizeComponentType(type, props); + const NavbarItemComponent = ComponentTypes[componentType]; + if (!NavbarItemComponent) { + throw new Error(`No NavbarItem component found for type "${type}".`); + } return ; } diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts b/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts deleted file mode 100644 index a98db455f25e..000000000000 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 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. - */ - -/* eslint-disable import/no-named-export */ - -export const getInfimaActiveClassName = ( - mobile?: boolean, -): `${'menu' | 'navbar'}__link--active` => - mobile ? 'menu__link--active' : 'navbar__link--active';