diff --git a/src/app-nav-bar/__tests__/app-nav-bar.test.tsx b/src/app-nav-bar/__tests__/app-nav-bar.test.tsx new file mode 100644 index 0000000000..db48d654ff --- /dev/null +++ b/src/app-nav-bar/__tests__/app-nav-bar.test.tsx @@ -0,0 +1,30 @@ +/* +Copyright (c) Uber Technologies, Inc. + +This source code is licensed under the MIT license found in the +LICENSE file in the root directory of this source tree. +*/ +import * as React from 'react'; +import { render } from '@testing-library/react'; + +import { AppNavBar } from '..'; +import type { NavItem } from '../types'; + +const mainItems: NavItem[] = [ + { + label: 'Primary A', + active: true, + navPosition: { mobile: 'horizontal', desktop: 'vertical' }, + children: [{ label: 'Secondary A' }, { label: 'Secondary B' }], + }, +]; + +describe('AppNavBar', () => { + it('renders the horizontal mobile sub-nav when the active item requests it', () => { + const { queryAllByLabelText } = render(); + + // navPosition.mobile is 'horizontal' and navPosition.desktop is 'vertical', so exactly one + // "Secondary navigation" nav (the mobile one) should render. + expect(queryAllByLabelText('Secondary navigation')).toHaveLength(1); + }); +}); diff --git a/src/app-nav-bar/app-nav-bar.tsx b/src/app-nav-bar/app-nav-bar.tsx index 0627f41933..8eeb904a7b 100644 --- a/src/app-nav-bar/app-nav-bar.tsx +++ b/src/app-nav-bar/app-nav-bar.tsx @@ -151,9 +151,15 @@ export default function AppNavBar(props: AppNavBarProps) { ); const [DesktopMenu, desktopMenuProps] = getOverrides(overrides.DesktopMenu, StyledDesktopMenu); - let secondaryMenu; - let desktopSubNavPosition: (typeof POSITION)[keyof typeof POSITION] = POSITION.horizontal; - let mobileSubNavPosition: (typeof POSITION)[keyof typeof POSITION] = POSITION.vertical; + // The active top level menu item determines the secondary navigation and its positioning. + const activeItemWithChildren = React.useMemo( + () => mainItems.find((item) => item.active && item.children && item.children.length), + [mainItems] + ); + const secondaryMenu = activeItemWithChildren?.children; + const desktopSubNavPosition = + activeItemWithChildren?.navPosition?.desktop || POSITION.horizontal; + const mobileSubNavPosition = activeItemWithChildren?.navPosition?.mobile || POSITION.vertical; return ( @@ -170,16 +176,14 @@ export default function AppNavBar(props: AppNavBarProps) { {title} - {secondaryMenu && - // @ts-expect-error todo(flow->ts) always false - mobileSubNavPosition === POSITION.horizontal && ( - - )} + {secondaryMenu && mobileSubNavPosition === POSITION.horizontal && ( + + )} {/* Desktop Nav Experience */} @@ -200,25 +204,15 @@ export default function AppNavBar(props: AppNavBarProps) { aria-label="Main navigation" {...primaryMenuContainerProps} > - {mainItems.map((item, index) => { - // For an active top level menu get the secondary navigation and its positioning - if (item.active && item.children && item.children.length) { - secondaryMenu = item.children; - if (item.navPosition) { - desktopSubNavPosition = item.navPosition.desktop || desktopSubNavPosition; - mobileSubNavPosition = item.navPosition.mobile || mobileSubNavPosition; - } - } - return ( - - ); - })} + {mainItems.map((item, index) => ( + + ))} {userItems.length ? (