From 14ed12052cfa6fa685f8128f63fa8068f998bec2 Mon Sep 17 00:00:00 2001 From: Pipicz Petra Date: Thu, 23 Jul 2026 14:29:37 +0200 Subject: [PATCH] feat(navigation): the deepest levels of the navigation will be opened after the initialization --- .../src/app/components/nav/nav.component.html | 27 ++++++++ .../src/app/components/nav/nav.component.ts | 62 ++++++++++++++++++- .../src/app/queries/get-navigation.query.ts | 6 ++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/projects/demo/src/app/components/nav/nav.component.html b/projects/demo/src/app/components/nav/nav.component.html index ab4b2392..074ba4c1 100644 --- a/projects/demo/src/app/components/nav/nav.component.html +++ b/projects/demo/src/app/components/nav/nav.component.html @@ -27,6 +27,20 @@ @if (subItem.icon) { } + + @for (subSubItem of subItem.children; track $index; let l = $index) { + + @if (subSubItem.icon) { + + } + + } } @@ -66,6 +80,19 @@ @if (subItem.icon) { } + @for (subSubItem of subItem.children; track $index; let l = $index) { + + @if (subSubItem.icon) { + + } + + } } diff --git a/projects/demo/src/app/components/nav/nav.component.ts b/projects/demo/src/app/components/nav/nav.component.ts index 09b1de04..f6ddf871 100644 --- a/projects/demo/src/app/components/nav/nav.component.ts +++ b/projects/demo/src/app/components/nav/nav.component.ts @@ -6,6 +6,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, + effect, ElementRef, HostListener, inject, @@ -56,8 +57,18 @@ export class NavComponent implements AfterViewInit { matrixParams: 'ignored', }; + private readonly _autoExpandedDeepestLevelIds = new Set(); + + constructor() { + effect(() => { + this.menu(); + this._openDeepestLevelItems(); + }); + } + public ngAfterViewInit(): void { this.checkMenuItemOverflows(); + this._openDeepestLevelItems(); } @HostListener('window:resize') @@ -71,7 +82,7 @@ export class NavComponent implements AfterViewInit { } public checkMenuItemOverflows(delay = 0): void { - setTimeout(() => { + this._scheduleAfter(() => { const menuItems = this._elementRef.nativeElement.querySelectorAll('ids-side-nav-item') as NodeListOf; this._menuItemsOverflow = Array.from(menuItems).reduce((items: Record, menuItem: HTMLElement) => { @@ -85,4 +96,53 @@ export class NavComponent implements AfterViewInit { this._cdr.markForCheck(); }, delay); } + + private _openDeepestLevelItems(): void { + this._scheduleAfter(() => { + const menuItems = this._elementRef.nativeElement.querySelectorAll('ids-side-nav-item') as NodeListOf; + + menuItems.forEach((menuItem) => { + if (!menuItem.id || this._autoExpandedDeepestLevelIds.has(menuItem.id)) { + return; + } + + const isExpandable = menuItem.classList.contains('ids-side-nav-item-expandable'); + if (!isExpandable) { + return; + } + + const hasNestedExpandable = + menuItem.querySelector(':scope > .ids-side-nav-item-expandable-submenu .ids-side-nav-item-expandable') !== null; + if (hasNestedExpandable) { + return; + } + + const anchor = menuItem.querySelector(':scope > a') as HTMLElement | null; + const toggleButton = anchor?.querySelector('button') as HTMLButtonElement | null; + const isExpanded = anchor?.getAttribute('aria-expanded') === 'true'; + + if (toggleButton && !isExpanded) { + toggleButton.click(); + } + + this._autoExpandedDeepestLevelIds.add(menuItem.id); + }); + + this._cdr.markForCheck(); + }); + } + + private _scheduleAfter(callback: () => void, delay = 0): void { + const start = performance.now(); + + const tick = (now: number): void => { + if (now - start >= delay) { + callback(); + } else { + requestAnimationFrame(tick); + } + }; + + requestAnimationFrame(tick); + } } diff --git a/projects/demo/src/app/queries/get-navigation.query.ts b/projects/demo/src/app/queries/get-navigation.query.ts index 51bb9c28..5261236f 100644 --- a/projects/demo/src/app/queries/get-navigation.query.ts +++ b/projects/demo/src/app/queries/get-navigation.query.ts @@ -43,6 +43,12 @@ export const GET_NAVIGATION = gql` generated } } + children { + depth + page { + title + } + } } } }