diff --git a/cypress/e2e/with-users/base/navigation.spec.ts b/cypress/e2e/with-users/base/navigation.spec.ts index e774397ca3..79553508ce 100644 --- a/cypress/e2e/with-users/base/navigation.spec.ts +++ b/cypress/e2e/with-users/base/navigation.spec.ts @@ -77,6 +77,18 @@ context("Navigation - admin - collapse", () => { .within(() => cy.findByRole("button", { name: /close menu/i }).click()); cy.getMainNavigation().should("not.be.visible"); }); + + it("automatically closes the menu on mobile when a link is clicked", () => { + cy.viewport("iphone-8"); + cy.getMainNavigation().should("not.be.visible"); + cy.findByRole("banner", { name: "navigation" }).within(() => + cy.findByRole("button", { name: "Menu" }).click() + ); + cy.getMainNavigation() + .should("be.visible") + .within(() => cy.findByRole("link", { name: /devices/i }).click()); + cy.getMainNavigation().should("not.be.visible"); + }); }); context("Navigation - admin", () => { diff --git a/src/app/base/components/AppSideNavigation/AppSideNavItem/AppSideNavItem.tsx b/src/app/base/components/AppSideNavigation/AppSideNavItem/AppSideNavItem.tsx index bad6f05154..3819c8254c 100644 --- a/src/app/base/components/AppSideNavigation/AppSideNavItem/AppSideNavItem.tsx +++ b/src/app/base/components/AppSideNavigation/AppSideNavItem/AppSideNavItem.tsx @@ -4,18 +4,26 @@ import { Navigation } from "@canonical/maas-react-components"; import classNames from "classnames"; import { Link } from "react-router-dom-v5-compat"; +import type { SideNavigationProps } from "../AppSideNavigation"; import type { NavItem } from "../types"; import { isSelected } from "../utils"; import { useId } from "@/app/base/hooks/base"; +import { MOBILE_VIEW_MAX_WIDTH } from "@/app/constants"; type Props = { navLink: NavItem; icon?: string | ReactNode; path: string; + setIsCollapsed: SideNavigationProps["setIsCollapsed"]; }; -export const AppSideNavItem = ({ navLink, icon, path }: Props): JSX.Element => { +export const AppSideNavItem = ({ + navLink, + icon, + path, + setIsCollapsed, +}: Props): JSX.Element => { const id = useId(); return ( { // removing the focus from the link element after click // this allows the side navigation to collapse on mouseleave e.currentTarget.blur(); + + if (window.innerWidth < MOBILE_VIEW_MAX_WIDTH) { + setIsCollapsed(true); + } }} to={navLink.url} > diff --git a/src/app/base/components/AppSideNavigation/AppSideNavItems/AppSideNavItems.tsx b/src/app/base/components/AppSideNavigation/AppSideNavItems/AppSideNavItems.tsx index 2d4d1fa1da..7f83b65f37 100644 --- a/src/app/base/components/AppSideNavigation/AppSideNavItems/AppSideNavItems.tsx +++ b/src/app/base/components/AppSideNavigation/AppSideNavItems/AppSideNavItems.tsx @@ -4,6 +4,7 @@ import { Navigation } from "@canonical/maas-react-components"; import { Button, Icon } from "@canonical/react-components"; import AppSideNavItem from "../AppSideNavItem"; +import type { SideNavigationProps } from "../AppSideNavigation"; import type { NavGroup } from "../types"; import { isSelected } from "../utils"; @@ -18,6 +19,7 @@ type Props = { isAuthenticated: boolean; logout: () => void; path: string; + setIsCollapsed: SideNavigationProps["setIsCollapsed"]; showLinks: boolean; vaultIncomplete: boolean; }; @@ -27,9 +29,10 @@ const AppSideNavItemGroup = ({ isAdmin, vaultIncomplete, path, + setIsCollapsed, }: { group: NavGroup } & Pick< Props, - "isAdmin" | "vaultIncomplete" | "path" + "isAdmin" | "vaultIncomplete" | "path" | "setIsCollapsed" >) => { const id = useId(); const hasActiveChild = useMemo(() => { @@ -67,6 +70,7 @@ const AppSideNavItemGroup = ({ key={navLink.label} navLink={navLink} path={path} + setIsCollapsed={setIsCollapsed} /> ); } else return null; @@ -84,6 +88,7 @@ export const AppSideNavItems = ({ isAuthenticated, logout, path, + setIsCollapsed, showLinks, vaultIncomplete, }: Props): JSX.Element => { @@ -97,6 +102,7 @@ export const AppSideNavItems = ({ isAdmin={isAdmin} key={`${i}-${group.groupTitle}`} path={path} + setIsCollapsed={setIsCollapsed} vaultIncomplete={vaultIncomplete} /> ))} @@ -111,6 +117,7 @@ export const AppSideNavItems = ({ icon="settings" navLink={{ label: "Settings", url: urls.settings.index }} path={path} + setIsCollapsed={setIsCollapsed} /> @@ -123,6 +130,7 @@ export const AppSideNavItems = ({ url: urls.preferences.index, }} path={path} + setIsCollapsed={setIsCollapsed} />