From ed5f6aa2b402315a1588f75c1949b61ed52f5ee5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 20:13:14 +0000
Subject: [PATCH 1/3] Initial plan
From c1ecf61734dd60acc622636e1445a2b795f33104 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 20:21:37 +0000
Subject: [PATCH 2/3] Add subNavigationId prop and implement deterministic ID
generation for SSR compatibility
Co-authored-by: mfranzke <787658+mfranzke@users.noreply.github.com>
---
.../src/components/navigation-item/model.ts | 5 +++
.../navigation-item/navigation-item.lite.tsx | 10 +++++-
.../navigation-item/navigation-item.spec.tsx | 33 +++++++++++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/packages/components/src/components/navigation-item/model.ts b/packages/components/src/components/navigation-item/model.ts
index 807e78df61fd..bdbe8938a970 100644
--- a/packages/components/src/components/navigation-item/model.ts
+++ b/packages/components/src/components/navigation-item/model.ts
@@ -36,6 +36,11 @@ export type DBNavigationItemDefaultProps = {
* This is for mobile navigation only, if it is set the sub-navigation is a static overlay
*/
subNavigationExpanded?: boolean | string;
+
+ /**
+ * ID for the sub-navigation element. If not provided, a deterministic ID will be generated to ensure SSR compatibility.
+ */
+ subNavigationId?: string;
};
export type DBNavigationItemProps = DBNavigationItemDefaultProps &
diff --git a/packages/components/src/components/navigation-item/navigation-item.lite.tsx b/packages/components/src/components/navigation-item/navigation-item.lite.tsx
index af2f46b956da..32320c5a5cba 100644
--- a/packages/components/src/components/navigation-item/navigation-item.lite.tsx
+++ b/packages/components/src/components/navigation-item/navigation-item.lite.tsx
@@ -29,7 +29,7 @@ export default function DBNavigationItem(props: DBNavigationItemProps) {
hasSubNavigation: true,
isSubNavigationExpanded: false,
autoClose: false,
- subNavigationId: 'sub-navigation-' + uuid(),
+ subNavigationId: props.subNavigationId ?? (props.id ? `${props.id}-sub-navigation` : 'sub-navigation'),
navigationItemSafeTriangle: undefined,
handleNavigationItemClick: (event: any) => {
if (event?.target?.nodeName === 'A') {
@@ -68,6 +68,14 @@ export default function DBNavigationItem(props: DBNavigationItemProps) {
}
}, [props.subNavigationExpanded]);
+ onUpdate(() => {
+ // Update subNavigationId if props change
+ const newSubNavigationId = props.subNavigationId ?? (props.id ? `${props.id}-sub-navigation` : 'sub-navigation');
+ if (state.subNavigationId !== newSubNavigationId) {
+ state.subNavigationId = newSubNavigationId;
+ }
+ }, [props.subNavigationId, props.id]);
+
onUpdate(() => {
if (state.initialized && _ref) {
const subNavigationSlot = _ref.querySelector('menu');
diff --git a/packages/components/src/components/navigation-item/navigation-item.spec.tsx b/packages/components/src/components/navigation-item/navigation-item.spec.tsx
index aa055f6718d4..4fe216a2e67c 100644
--- a/packages/components/src/components/navigation-item/navigation-item.spec.tsx
+++ b/packages/components/src/components/navigation-item/navigation-item.spec.tsx
@@ -29,6 +29,39 @@ const testComponent = () => {
const component = await mount(comp);
await expect(component).toHaveScreenshot();
});
+
+ test('should use deterministic subNavigationId when id prop is provided', async ({ mount }) => {
+ const componentWithId = (
+
+ Test
+
+ );
+ const component = await mount(componentWithId);
+ const subNav = component.locator('menu[id="test-nav-item-sub-navigation"]');
+ await expect(subNav).toBeAttached();
+ });
+
+ test('should use provided subNavigationId when specified', async ({ mount }) => {
+ const componentWithSubNavId = (
+
+ Test
+
+ );
+ const component = await mount(componentWithSubNavId);
+ const subNav = component.locator('menu[id="custom-sub-nav-id"]');
+ await expect(subNav).toBeAttached();
+ });
+
+ test('should use fallback subNavigationId when no id or subNavigationId provided', async ({ mount }) => {
+ const componentWithoutId = (
+
+ Test
+
+ );
+ const component = await mount(componentWithoutId);
+ const subNav = component.locator('menu[id="sub-navigation"]');
+ await expect(subNav).toBeAttached();
+ });
};
const testA11y = () => {
test('should have same aria-snapshot', async ({ mount }, testInfo) => {
From 1ef965e6671fb657c339229059fb2672e07ea844 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 20:24:31 +0000
Subject: [PATCH 3/3] Add documentation comments and finalize SSR fix
implementation
Co-authored-by: mfranzke <787658+mfranzke@users.noreply.github.com>
---
.../src/components/navigation-item/navigation-item.lite.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/packages/components/src/components/navigation-item/navigation-item.lite.tsx b/packages/components/src/components/navigation-item/navigation-item.lite.tsx
index 32320c5a5cba..ba3823a90792 100644
--- a/packages/components/src/components/navigation-item/navigation-item.lite.tsx
+++ b/packages/components/src/components/navigation-item/navigation-item.lite.tsx
@@ -29,6 +29,10 @@ export default function DBNavigationItem(props: DBNavigationItemProps) {
hasSubNavigation: true,
isSubNavigationExpanded: false,
autoClose: false,
+ // Use deterministic ID generation for SSR compatibility:
+ // 1. Prefer explicit subNavigationId prop
+ // 2. Fallback to component id + suffix
+ // 3. Default to fixed string (instead of random UUID)
subNavigationId: props.subNavigationId ?? (props.id ? `${props.id}-sub-navigation` : 'sub-navigation'),
navigationItemSafeTriangle: undefined,
handleNavigationItemClick: (event: any) => {