My Preliminary Implementations of A Nested Volto Navigation Menubar

Before @myriadicity/volto-navigation-dropdown I implemented two variants in trying to solve an implementation problem. When working on the issue I chronicled my efforts and preserve the details here.

For information about the fully functional successor to the versions described below see An Automatically Populated Nested Plone 6 Navigation Menubar.

My Precursor Navigation Menubar Versions, Stubborn and Oblique

Starting with one of the malfunctioning addons, codesyntax/volto-menu-customization, I implemented two versions of an addon that implements the functionality, one demonstrating a problem and the other demonstrating an awkward workaround.

The sidebar for both of those package pages have a link to a github repository with the code for both, each in a separate branch.

The Problem With These Prior Implementations

  • Volto uses the React Semantic UI, which includes a decent Dropdown menus facility. Using that it's fairly easy to attach recursively populated dropdown menus to our default Volto navbar header entries.
  • What's complicated is associating the right link behavior with the dropdown menu container entries.
  • Inferring from the Volto NavItem objects (volto/NavItem.jsx at master · plone/volto), it looks like the link needs to be implemented as a React NavLink object (NavLink v6.6.2 | React Router).
  • Fortunately, Dropdowns implement an as= option that we can use to add NavLink functionality to the Dropdown container entry:
          <Dropdown simple
                    text={item.title}
                    [...]
                    as={NavLink}
                    key={item.url} >
  • Doing this makes the menu items for the container entries traverse to the right place on selection, enabling customary navigation menus that people commonly use.
  • Unfortunately, the combination of `NavLink` and `Dropdown` causes the menus for selected pages to stay open, even on page refresh. You can't close the menus (and it's not a good option to require manually closing them, even if we found a way to do so).
    • I believe that the problem is because the NavLink objects signal being on the path of the currently visited page using the CSS class named "active", while Dropdown menus use that same class name to recognize and maintain active - open –state.
    • So when the NavLink functionality recognizes active state, because it's by definition on the path to the item that's being selected, it adopts the CSS active class and that causes the Dropdown to remain open.
    • This is an unfortunate collision in the use of a CSS class. I'm not sure that's causing the problem, but it makes sense to me that it would.

The Stubborn Alternative

Whether or not the above analysis of the exact cause is correct, I have not found a way to prevent the menus from staying open when the NavLink functionality is added. You can see this behavior by including the @myriadicity/volto-navigation-dropdown-stubborn - npm (npmjs.com) addon in it Volto frontend.

Aside from the stubborn-open-menu behavior, I believe this functionality needs to be implemented as the navbar default behavior shipped with Volto. There are other rough edges – there is enough of a gap between where you hover to open the menu and the menu that it sometimes closes when moving the cursor to it. CSS tweaking would be needed to settle those kinds of things, but I expect that people with good CSS skills can take care of that. The more important piece is resolving the stubbornness.

The Oblique Alternative

One way to avoid the stubborn problem is to omit the NavLink functionality. That means people can't click on the primary entry for the container to visit it. Instead, we add a secondary entry for the container as the top, header-like item on its contents menu. Users can then select that secondary entry to visit the container. This is implemented in the @myriadicity/volto-navigation-dropdown-oblique - npm (npmjs.com) package, and what is currently running on my prototype instance.

It's not a good solution. Visitors will first be puzzled when they try to click on the primary entry for a container, as you would do on any regular navigation menu. If they notice the secondary entry they can click on that. Some won't notice the secondary entry and give up.

I aim to work on these issues next chance I get, but would happily welcome contributions that resolve them! My ultimate aim is to submit a pull request for the GitHub - plone/volto: React-based frontend for the Plone Content Management System repository, to propose pushing the functionality to Volto proper, but in the meanwhile am fine with developing the functionality in the addon and making it available for anyone to use.

The npm module page has links to the code repository and the alternate implementations with funky problems.

I also revisited the codesyntax/volto-menu-customization implementation to see the progress they made. It still has just two levels hard wired in, which is a different choice than I made, but I see they’ve incorporated behavior conditioning according to the state of the hamburger menu and mobile platform, so figure there will be useful clues there for conditioning behavior in my volto-navigation-dropdown.