diff --git a/.changeset/violet-bobcats-wave.md b/.changeset/violet-bobcats-wave.md new file mode 100644 index 0000000000..339d7e0e74 --- /dev/null +++ b/.changeset/violet-bobcats-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix for `SidebarItem` matching the active route too broadly. diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index b930c455b5..1068a877bd 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -34,7 +34,12 @@ import React, { useContext, useState, } from 'react'; -import { NavLink, NavLinkProps } from 'react-router-dom'; +import { + Link, + NavLinkProps, + useLocation, + useResolvedPath, +} from 'react-router-dom'; import { sidebarConfig, SidebarContext } from './config'; const useStyles = makeStyles(theme => { @@ -147,6 +152,54 @@ function isButtonItem( return (props as SidebarItemLinkProps).to === undefined; } +// TODO(Rugvip): Remove this once NavLink is updated in react-router-dom. +// This is needed because react-router doesn't handle the path comparison +// properly yet, matching for example /foobar with /foo. +export const WorkaroundNavLink = React.forwardRef< + HTMLAnchorElement, + NavLinkProps +>(function WorkaroundNavLinkWithRef( + { + to, + end, + style, + className, + activeStyle, + caseSensitive, + activeClassName = 'active', + 'aria-current': ariaCurrentProp = 'page', + ...rest + }, + ref, +) { + let { pathname: locationPathname } = useLocation(); + let { pathname: toPathname } = useResolvedPath(to); + + if (!caseSensitive) { + locationPathname = locationPathname.toLowerCase(); + toPathname = toPathname.toLowerCase(); + } + + let isActive = locationPathname === toPathname; + if (!isActive && !end) { + // This is the behavior that is different from the original NavLink + isActive = locationPathname.startsWith(`${toPathname}/`); + } + + const ariaCurrent = isActive ? ariaCurrentProp : undefined; + + return ( + + ); +}); + export const SidebarItem = forwardRef((props, ref) => { const { icon: Icon, @@ -211,7 +264,7 @@ export const SidebarItem = forwardRef((props, ref) => { } return ( - ((props, ref) => { {...navLinkProps} > {content} - + ); });