From 74734251d2a08cc6cce14457278667c1a18f515b Mon Sep 17 00:00:00 2001 From: Scott Williams <5209283+scott-williams-az@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:54:56 -0700 Subject: [PATCH 1/2] fix(unity-react-core): sidebar menu should auto-expand if it contains an active page item --- .../SidebarMenu/SidebarMenu.stories.tsx | 30 ++++++++--- .../SidebarMenu/SidebarMenu.test.tsx | 34 +++++++++---- .../components/SidebarMenu/SidebarMenu.tsx | 51 ++++++++++--------- 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.stories.tsx b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.stories.tsx index b02c1d9d8d..1e344c90a2 100644 --- a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.stories.tsx +++ b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.stories.tsx @@ -20,6 +20,7 @@ const defaultProps = { { href: "https://example.com", text: "Link 2.1", + isActive: false, }, { href: "https://example.com", @@ -56,18 +57,33 @@ const defaultProps = { text: "Link 5.2", }, ], - } - ] -} + }, + ], +}; -const sidebarMenuTemplate = args =>
- -
; +const sidebarMenuTemplate = args => ( +
+ +
+); export const Overview = { render: sidebarMenuTemplate.bind({}), name: "Sidebar", args: { ...defaultProps, - } + }, +}; + +const defaultProps2 = JSON.parse(JSON.stringify(defaultProps)); +defaultProps2.links[0].text = "Link 1"; +defaultProps2.links[0].isActive = false; +defaultProps2.links[1].items[0].isActive = true; +defaultProps2.links[1].items[0].text = "Active Link"; + +export const WithNestedActivePage = { + render: sidebarMenuTemplate.bind({}), + args: { + ...defaultProps2, + }, }; diff --git a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx index d1743fc28f..6bb1eb40f6 100644 --- a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx +++ b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx @@ -10,6 +10,7 @@ const defaultProps: SidebarProps = { { href: "https://example.com", text: "Link 1", + isActive: true, }, { text: "Link 2 dropdown", @@ -23,24 +24,39 @@ const defaultProps: SidebarProps = { text: "Link 2.2", }, ], - } - ] + }, + ], }; -const renderComponent = (props:SidebarProps) => { +const defaultProps2 = JSON.parse(JSON.stringify(defaultProps)); +delete defaultProps2.links[0].isActive; +defaultProps2.links[1].items[0].isActive = true; + +const renderComponent = (props: SidebarProps) => { return render(); }; describe("SidebarMenu tests", () => { - let component:RenderResult; + let component: RenderResult; + + afterEach(cleanup); - beforeEach(() => { + it("should have top level active link", () => { component = renderComponent(defaultProps); + expect(component.getByText("Link 1")).toHaveClass("is-active"); + expect(component.queryByText("Link 2 dropdown")).toHaveAttribute( + "aria-expanded", + "false" + ); }); - afterEach(cleanup); - - it("should define component", () => { - expect(component).toBeDefined(); + it("should have nested level active link", () => { + component = renderComponent(defaultProps2); + expect(component.getByText("Link 2.1")).toBeVisible(); + expect(component.getByText("Link 2.1")).toHaveClass("is-active"); + expect(component.queryByText("Link 2 dropdown")).toHaveAttribute( + "aria-expanded", + "true" + ); }); }); diff --git a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx index ae7d326397..82cdd58adf 100644 --- a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx +++ b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx @@ -1,16 +1,18 @@ import React from "react"; import { GaEventWrapper } from "../GaEventWrapper/GaEventWrapper"; +interface SidebarItemProps { + href: string; + text: string; + isActive?: boolean; +} + export interface Link { href?: string; text: string; isActive?: boolean; - items?: Array<{ - href: string; - text: string; - isActive?: boolean; - }>; -}; + items?: SidebarItemProps[]; +} const defaultGaProps = { name: "onclick", @@ -24,6 +26,16 @@ export interface SidebarProps { links: Link[]; } +const SidebarItem: React.FC = ({ + href, + text, + isActive, +}) => ( + + {text} + +); + export const SidebarMenu: React.FC = ({ title, links }) => { return (
@@ -46,9 +58,10 @@ export const SidebarMenu: React.FC = ({ title, links }) => { > {links.map((link, index) => { if (link.items) { + const isExpanded = link.items.some(({ isActive }) => isActive); // Render dropdown card return ( -
+
= ({ title, links }) => { href={`#cardBody${index}`} data-bs-toggle="collapse" data-bs-target={`#cardBody${index}`} - aria-expanded="false" + aria-expanded={isExpanded} aria-controls={`cardBody${index}`} > {link.text} @@ -69,18 +82,12 @@ export const SidebarMenu: React.FC = ({ title, links }) => {
{link.items.map(item => ( - - {item.text} - + ))}
@@ -88,13 +95,11 @@ export const SidebarMenu: React.FC = ({ title, links }) => { } else { // Render regular link return ( -
- - {link.text} - +
+
); } From b020a5519a03e6a1c33141f8edfe00c6b11f652b Mon Sep 17 00:00:00 2001 From: Scott Williams <5209283+scott-williams-az@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:21:48 -0700 Subject: [PATCH 2/2] fix(unity-react-core): sidebar menu should auto-expand if it contains an active page item --- .../SidebarMenu/SidebarMenu.test.tsx | 2 +- .../components/SidebarMenu/SidebarMenu.tsx | 31 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx index 6bb1eb40f6..6830e37202 100644 --- a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx +++ b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.test.tsx @@ -53,7 +53,7 @@ describe("SidebarMenu tests", () => { it("should have nested level active link", () => { component = renderComponent(defaultProps2); expect(component.getByText("Link 2.1")).toBeVisible(); - expect(component.getByText("Link 2.1")).toHaveClass("is-active"); + expect(component.getByText("Link 2 dropdown")).toHaveClass("is-active"); expect(component.queryByText("Link 2 dropdown")).toHaveAttribute( "aria-expanded", "true" diff --git a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx index 82cdd58adf..6383c31fe3 100644 --- a/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx +++ b/packages/unity-react-core/src/components/SidebarMenu/SidebarMenu.tsx @@ -26,16 +26,6 @@ export interface SidebarProps { links: Link[]; } -const SidebarItem: React.FC = ({ - href, - text, - isActive, -}) => ( - - {text} - -); - export const SidebarMenu: React.FC = ({ title, links }) => { return (
@@ -58,8 +48,8 @@ export const SidebarMenu: React.FC = ({ title, links }) => { > {links.map((link, index) => { if (link.items) { - const isExpanded = link.items.some(({ isActive }) => isActive); // Render dropdown card + const isExpanded = link.items.some(({ isActive }) => isActive); return (
@@ -68,7 +58,9 @@ export const SidebarMenu: React.FC = ({ title, links }) => { > = ({ title, links }) => { data-bs-parent=".sidebar" > {link.items.map(item => ( - + + {item.text} + ))}
@@ -99,7 +97,12 @@ export const SidebarMenu: React.FC = ({ title, links }) => { key={`${link.text}${link.href}`} className="nav-link-container" > - + + {link.text} +
); }