diff --git a/src/navbar/navbar-items.tsx b/src/navbar/navbar-items.tsx index 4fb58eafc..319298265 100644 --- a/src/navbar/navbar-items.tsx +++ b/src/navbar/navbar-items.tsx @@ -130,7 +130,11 @@ export const NavbarItems = ({ {...options} > {children} - {selected && } + {selected && ( + + )} {mobile && item.subMenu && ( ( ); }; + const hasUncollapsibleActionButtons = () => { + if (actionButtons.mobile) { + const hasUncollapsibleItems = actionButtons.mobile.some( + (actionButton) => { + return actionButton.uncollapsible; + } + ); + + if (hasUncollapsibleItems) return true; + } + + if (actionButtons.desktop) { + const hasUncollapsibleItems = actionButtons.desktop.some( + (actionButton) => { + return actionButton.uncollapsible; + } + ); + + if (hasUncollapsibleItems) return true; + } + return false; + }; + // ============================================================================= // EVENT HANDLER // ============================================================================= @@ -228,6 +251,27 @@ const Component = ( ); + const renderMobileMenuButton = () => { + if ( + (items.mobile && items.mobile.length > 0) || + (items.desktop && items.desktop.length > 0) || + (actionButtons && !hasUncollapsibleActionButtons()) + ) { + return ( + + + + ); + } + + return null; + }; + const renderNavbar = () => { return ( @@ -244,14 +288,7 @@ const Component = ( actionButtons={actionButtons} onActionButtonClick={handleActionButtonClick} /> - - - + {renderMobileMenuButton()} )} diff --git a/stories/navbar/props-table.tsx b/stories/navbar/props-table.tsx index cdc73437f..0d265c868 100644 --- a/stories/navbar/props-table.tsx +++ b/stories/navbar/props-table.tsx @@ -262,8 +262,13 @@ const DATA: ApiTableSectionProps[] = [ }, { name: "uncollapsible", - description: - "Specifies if the action button should collapse in mobile viewports", + description: ( + <> + If specified, the item will remain on the{" "} + Navbar and not be collapsed to the drawer + in mobile viewports + + ), propTypes: ["boolean"], }, ], diff --git a/tests/navbar/navbar.spec.tsx b/tests/navbar/navbar.spec.tsx new file mode 100644 index 000000000..65efaeb41 --- /dev/null +++ b/tests/navbar/navbar.spec.tsx @@ -0,0 +1,163 @@ +import { render } from "@testing-library/react"; +import { Navbar } from "src/navbar"; + +describe("Navbar", () => { + describe("Basic functions", () => { + it("should render the items (desktop and mobile) if specified", () => { + const rendered = render( + + ); + + const { getByTestId } = rendered; + + expect(getByTestId("link__1")).toBeInTheDocument(); + expect(getByTestId("link__2")).toBeInTheDocument(); + expect(getByTestId("link__mobile-1")).toBeInTheDocument(); + expect(getByTestId("link__mobile-2")).toBeInTheDocument(); + }); + + it("should render the mobile items even if mobile items are not specified", () => { + const rendered = render(); + + const { getByTestId } = rendered; + + expect(getByTestId("link__1")).toBeInTheDocument(); + expect(getByTestId("link__2")).toBeInTheDocument(); + expect(getByTestId("link__mobile-1")).toBeInTheDocument(); + expect(getByTestId("link__mobile-2")).toBeInTheDocument(); + }); + + it("should render the indicator on the correct item when clicked", () => { + const rendered = render( + + ); + + const { getByTestId } = rendered; + expect(getByTestId("link__1-indicator")).toBeInTheDocument(); + }); + + it("should render the primary brand", () => { + const rendered = render(); + + const { getByTestId } = rendered; + expect(getByTestId("main__brand")).toBeInTheDocument(); + }); + + it("should render the secondary brand if specified", () => { + const rendered = render( + + ); + + const { getByTestId } = rendered; + expect(getByTestId("main__brand-secondary")).toBeInTheDocument(); + }); + + it("should render the mobile menu button if there are items specified", () => { + const rendered = render(); + + const { getByTestId } = rendered; + expect(getByTestId("button__mobile-menu")).toBeInTheDocument(); + }); + + it("should not render the links and mobile menu button if there no items are specified", () => { + const rendered = render(); + + const { queryByTestId } = rendered; + expect(queryByTestId("link__1")).not.toBeInTheDocument(); + expect( + queryByTestId("button__mobile-menu") + ).not.toBeInTheDocument(); + }); + + it("should not render the links and mobile menu button if hideNavElements is set to true", () => { + const rendered = render( + + ); + + const { queryByTestId } = rendered; + expect(queryByTestId("link__1")).not.toBeInTheDocument(); + expect( + queryByTestId("button__mobile-menu") + ).not.toBeInTheDocument(); + }); + + it("should render the mobile menu items if no items are specified but there are action items specified", () => { + const rendered = render( + + ); + + const { getByTestId } = rendered; + expect(getByTestId("button__mobile-menu")).toBeInTheDocument(); + }); + + it("should not render the mobile menu items if no items are specified the action items are uncollapsible", () => { + const rendered = render( + + ); + + const { queryByTestId } = rendered; + expect( + queryByTestId("button__mobile-menu") + ).not.toBeInTheDocument(); + }); + }); +}); +// ============================================================================= +// MOCKS +// ============================================================================= +const MOCK_ITEMS = [ + { + id: "first", + children: "First", + }, + { + id: "second", + children: "Second", + }, +];