In the following code I have a nested menu. On hover I wanted to add selected
class name to the Nav.Item and only remove it when I hover over another Nav.Item
. I could achive that with onMouseOver
. Unfortunately, it doesn't add selected
class to any of the sub-level Nav.Item
.
So the criterias would be: for hover on any nav.item selected class should be added
selected
class if mouse leaves the itemselected
class on the Nav.Item
when a child menu appearsselected
class only, if hover over another Nav.Item
but on the same level"use client";
import Nav from 'react-bootstrap/Nav';
import Link from 'next/link';
import { getMenu } from '@/lib/APIs/menu';
import { use, useEffect, useRef, useState } from 'react';
import { usePathname } from 'next/navigation';
import { Button, NavDropdown } from 'react-bootstrap';
const dataPromise = getMenu();
const GlobalNav = () => {
const MENU = use(dataPromise);
const [selectedItemId, setSelectedItemId] = useState<string | null>(null);
function handleItemHover(itemId: string) {
setSelectedItemId(itemId);
}
function renderMenuItems(menuItems: any[]) {
return menuItems.map((item: any) => (
<Nav.Item
as='li'
key={item.id}
onMouseOver={() => handleItemHover(item.id)}
className={selectedItemId === item.id ? 'selected' : ''}
>
<Nav.Link
as={Link}
href={item.url}
>
<span>
{item.title}
</span>
</Nav.Link>
{item.children && item.children.length > 0 && (
<Nav as='ul'>
{renderMenuItems(item.children)}
</Nav>
)}
</Nav.Item>
));
}
return (
<Nav as='ul'>
{renderMenuItems(MENU)}
</Nav>
);
}
export default GlobalNav;
I hope someone can help with it.
Try this:
function hasSelectedChild(menuItem) {
return menuItem.children && menuItem.children.length > 0 && menuItem.children.find(item => item.id === selectedItemId || hasSelectedChild(item))
}
function renderMenuItems(menuItems: any[]) {
return menuItems.map((item: any) => (
<Nav.Item
as='li'
key={item.id}
onMouseOver={(e) => {
e.stopPropagation();
handleItemHover(item.id)
}}
className={(hasSelectedChild(item) || selectedItemId === item.id) ? 'selected' : ''}
>
<Nav.Link
as={Link}
href={item.url}
>
<span>
{item.title}
</span>
</Nav.Link>
{item.children && item.children.length > 0 && (
<Nav as='ul'>
{renderMenuItems(item.children)}
</Nav>
)}
</Nav.Item>
));
}