From d311a3bef5b918772a0e92cb14231ae93e668c0f Mon Sep 17 00:00:00 2001
From: Joao Silva <100691367+JoaoSilvaGrafana@users.noreply.github.com>
Date: Tue, 5 Apr 2022 15:38:58 +0100
Subject: [PATCH] Navigation: Keeps nav item hover when hovering over the item
menu (#47281)
---
.../components/NavBar/Next/NavBarItem.tsx | 8 +++++++-
.../NavBar/Next/NavBarItemMenuTrigger.tsx | 19 ++++++++++++-------
.../components/NavBar/Next/NavBarNext.tsx | 2 +-
public/app/core/components/NavBar/context.tsx | 6 +++---
4 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/public/app/core/components/NavBar/Next/NavBarItem.tsx b/public/app/core/components/NavBar/Next/NavBarItem.tsx
index 752e8807431..fb4731ce773 100644
--- a/public/app/core/components/NavBar/Next/NavBarItem.tsx
+++ b/public/app/core/components/NavBar/Next/NavBarItem.tsx
@@ -12,6 +12,7 @@ import { NavBarItemMenu } from './NavBarItemMenu';
import { getNavModelItemKey } from '../utils';
import { useLingui } from '@lingui/react';
import menuItemTranslations from '../navBarItem-translations';
+import { useNavBarContext } from '../context';
export interface Props {
isActive?: boolean;
@@ -33,6 +34,7 @@ const NavBarItem = ({
const { i18n } = useLingui();
const theme = useTheme2();
const menuItems = link.children ?? [];
+ const { menuIdOpen } = useNavBarContext();
// Spreading `menuItems` here as otherwise we'd be mutating props
const menuItemsSorted = reverseMenuDirection ? [...menuItems].reverse() : menuItems;
@@ -81,7 +83,7 @@ const NavBarItem = ({
);
} else {
return (
-
+
({
...getNavBarItemWithoutMenuStyles(theme, isActive),
+ containerHover: css({
+ backgroundColor: theme.colors.action.hover,
+ color: theme.colors.text.primary,
+ }),
primaryText: css({
color: theme.colors.text.primary,
}),
diff --git a/public/app/core/components/NavBar/Next/NavBarItemMenuTrigger.tsx b/public/app/core/components/NavBar/Next/NavBarItemMenuTrigger.tsx
index 9d81447e735..0d266ac2165 100644
--- a/public/app/core/components/NavBar/Next/NavBarItemMenuTrigger.tsx
+++ b/public/app/core/components/NavBar/Next/NavBarItemMenuTrigger.tsx
@@ -47,9 +47,10 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
onHoverChange: (isHovering) => {
if (isHovering) {
state.open();
- setMenuIdOpen(ref.current?.id || null);
+ setMenuIdOpen(item.id);
} else {
state.close();
+ setMenuIdOpen(undefined);
}
},
});
@@ -57,13 +58,13 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
useEffect(() => {
// close the menu when changing submenus
// or when the state of the overlay changes (i.e hovering outside)
- if (menuIdOpen !== ref.current?.id || !state.isOpen) {
+ if (menuIdOpen !== item.id || !state.isOpen) {
state.close();
setMenuHasFocus(false);
} else {
state.open();
}
- }, [menuIdOpen, state]);
+ }, [menuIdOpen, state, item.id]);
const { keyboardProps } = useKeyboard({
onKeyDown: (e) => {
@@ -71,11 +72,12 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
case 'ArrowRight':
if (!state.isOpen) {
state.open();
+ setMenuIdOpen(item.id);
}
setMenuHasFocus(true);
break;
case 'Tab':
- setMenuIdOpen(null);
+ setMenuIdOpen(undefined);
break;
default:
break;
@@ -142,7 +144,10 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
const { dialogProps } = useDialog({}, overlayRef);
const { overlayProps } = useOverlay(
{
- onClose: () => state.close(),
+ onClose: () => {
+ state.close();
+ setMenuIdOpen(undefined);
+ },
isOpen: state.isOpen,
isDismissable: true,
},
@@ -160,7 +165,7 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
onFocusWithin: (e) => {
if (e.target.id === ref.current?.id) {
// If focussing on the trigger itself, set the menu id that is open
- setMenuIdOpen(ref.current?.id);
+ setMenuIdOpen(item.id);
state.open();
}
},
@@ -168,7 +173,7 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
if (e.target?.getAttribute('role') === 'menuitem' && !overlayRef.current?.contains(e.relatedTarget)) {
// If it is blurring from a menuitem to an element outside the current overlay
// close the menu that is open
- setMenuIdOpen(null);
+ setMenuIdOpen(undefined);
}
},
});
diff --git a/public/app/core/components/NavBar/Next/NavBarNext.tsx b/public/app/core/components/NavBar/Next/NavBarNext.tsx
index 63cf25fcb27..a2a07fbac5e 100644
--- a/public/app/core/components/NavBar/Next/NavBarNext.tsx
+++ b/public/app/core/components/NavBar/Next/NavBarNext.tsx
@@ -59,7 +59,7 @@ export const NavBarNext = React.memo(() => {
const activeItem = isSearchActive(location) ? searchItem : getActiveItem(navTree, location.pathname);
const [menuOpen, setMenuOpen] = useState(false);
const [menuAnimationInProgress, setMenuAnimationInProgress] = useState(false);
- const [menuIdOpen, setMenuIdOpen] = useState(null);
+ const [menuIdOpen, setMenuIdOpen] = useState(undefined);
if (kiosk !== KioskMode.Off) {
return null;
diff --git a/public/app/core/components/NavBar/context.tsx b/public/app/core/components/NavBar/context.tsx
index 2beb99d8ab6..e7baf632b4c 100644
--- a/public/app/core/components/NavBar/context.tsx
+++ b/public/app/core/components/NavBar/context.tsx
@@ -18,12 +18,12 @@ export function useNavBarItemMenuContext(): NavBarItemMenuContextProps {
}
export interface NavBarContextProps {
- menuIdOpen: string | null;
- setMenuIdOpen: (id: string | null) => void;
+ menuIdOpen: string | undefined;
+ setMenuIdOpen: (id: string | undefined) => void;
}
export const NavBarContext = createContext({
- menuIdOpen: null,
+ menuIdOpen: undefined,
setMenuIdOpen: () => undefined,
});