core-components: fix route matching in SidebarItem
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Fix for `SidebarItem` matching the active route too broadly.
|
||||
@@ -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<BackstageTheme>(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 (
|
||||
<Link
|
||||
{...rest}
|
||||
to={to}
|
||||
ref={ref}
|
||||
aria-current={ariaCurrent}
|
||||
style={{ ...style, ...(isActive ? activeStyle : undefined) }}
|
||||
className={clsx([className, isActive ? activeClassName : undefined])}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => {
|
||||
const {
|
||||
icon: Icon,
|
||||
@@ -211,7 +264,7 @@ export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
<WorkaroundNavLink
|
||||
{...childProps}
|
||||
activeClassName={classes.selected}
|
||||
to={props.to}
|
||||
@@ -220,7 +273,7 @@ export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => {
|
||||
{...navLinkProps}
|
||||
>
|
||||
{content}
|
||||
</NavLink>
|
||||
</WorkaroundNavLink>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user