Navigation: Keeps nav item hover when hovering over the item menu (#47281)

This commit is contained in:
Joao Silva 2022-04-05 15:38:58 +01:00 committed by GitHub
parent c1c78bbc32
commit d311a3bef5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 12 deletions

View File

@ -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 (
<li className={cx(styles.container, className)}>
<li className={cx(styles.container, { [styles.containerHover]: section.id === menuIdOpen }, className)}>
<NavBarItemMenuTrigger
item={section}
isActive={isActive}
@ -126,6 +128,10 @@ export default NavBarItem;
const getStyles = (theme: GrafanaTheme2, adjustHeightForBorder: boolean, isActive?: boolean) => ({
...getNavBarItemWithoutMenuStyles(theme, isActive),
containerHover: css({
backgroundColor: theme.colors.action.hover,
color: theme.colors.text.primary,
}),
primaryText: css({
color: theme.colors.text.primary,
}),

View File

@ -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);
}
},
});

View File

@ -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<string | null>(null);
const [menuIdOpen, setMenuIdOpen] = useState<string | undefined>(undefined);
if (kiosk !== KioskMode.Off) {
return null;

View File

@ -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<NavBarContextProps>({
menuIdOpen: null,
menuIdOpen: undefined,
setMenuIdOpen: () => undefined,
});