SideNav: allow the user to control when parent is expanded
Describe your motivation
In SideNav, when the user navigates to a view which is in the menu, the parent item is always expanded. I'd like to have a way to disable that. I'm working on an application where the side nav was changed by CSS to be used in the top of the screen, just like a menu, because of its accessibility features. In this case, it's weird when the user goes to a page and the "menu" is opened.
Describe the solution you'd like
A flag like 'expandParentsAfterNavigation' which would be true by default and would keep the current behavior. If false, when the user navigated to a page, the component wouldn't try to expand the side navigation in case of matches.
Describe alternatives you've considered
I tried calling 'sideNavItem.setExpanded(false)' in a afterNavigation event, without luck. One option that I haven't tried would be to some how attach an event listener to vaadin-navigated and try to collapse the side navigation.
Additional context
No response
As a workaround, I think the custom CSS could be updated to not rely on the [expanded] state of the nav item, but rather rely on :focus and :focus-within selectors.
Styling the SideNav to be a horizontal navigation component is not a supported use case, and I'm wondering if there are use cases for not ensuring that the current view is visible in the (vertical) navigation tree (suggestions welcome)
I'd say a proper solution would be to introduce a horizontal navigation component: https://github.com/vaadin/web-components/issues/9191.
I believe I can assist with this, assuming we're referring to the TopNav variant in Reindeer+. As Jouni mentioned, I think we can resolve it with CSS.
IIRC a horizontal navigation bar with dropdowns needs different ARIA semantics from a vertical one, so just a theme variant would not suffice. I also suspect there will be other features that are specific to either/or but not both, which would favor a separate component (all of the nav-related logic could still be shared between them in a single mixin though).
Closing as not planned (plan to instead introduce horizontal dropdown navigation component).
Reopening as this is a valid use case requested by multiple customers and discussed internally as V25.0 candidate.
API proposal: noAutoExpand on the vaadin-side-nav-item (similar to autoExpandHorizontally in MSCB).
For the Flow counterpart it would be setAutoExpand(false) which would then also match MultiSelectComboBox.
Workaround confirmed to work with the Flow counterpart - call patchItem() for every child item that needs it.
@Route("vaadin-side-nav/side-nav-test")
public class SideNavPage extends Div {
public SideNavPage() {
setMaxWidth("400px");
SideNav sideNav = new SideNav();
sideNav.setCollapsible(true);
SideNavItem parentItem = new SideNavItem("Parent");
SideNavItem nestedItem = new SideNavItem("Nested",
"vaadin-side-nav/side-nav-test");
patchItem(nestedItem);
parentItem.addItem(nestedItem);
sideNav.addItem(parentItem);
add(sideNav);
}
protected void patchItem(SideNavItem item) {
item.getElement().setAttribute("noexpand", "");
item.getElement().executeJs("""
const old = this.__expandParentItems;
this.__expandParentItems = function () {
if (this.hasAttribute('noexpand')) {
let item = this;
do {
item.expanded = false;
item = item.parentElement;
} while (item && item.localName === 'vaadin-side-nav-item');
} else {
old.call(this);
}
}
""");
}
}