web-components icon indicating copy to clipboard operation
web-components copied to clipboard

SideNav: allow the user to control when parent is expanded

Open brunovianarezende opened this issue 6 months ago • 2 comments

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

brunovianarezende avatar Jun 06 '25 19:06 brunovianarezende

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.

jouni avatar Jun 09 '25 10:06 jouni

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.

rolfsmeds avatar Jun 18 '25 12:06 rolfsmeds

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.

anezthes avatar Jun 30 '25 16:06 anezthes

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).

rolfsmeds avatar Jul 14 '25 06:07 rolfsmeds

Closing as not planned (plan to instead introduce horizontal dropdown navigation component).

rolfsmeds avatar Jul 16 '25 12:07 rolfsmeds

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.

web-padawan avatar Oct 13 '25 09:10 web-padawan

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);
                    }
                }
                """);
    }
}

web-padawan avatar Oct 13 '25 09:10 web-padawan