From 1a32465a4a04f092557f02fbfc38370adf07595f Mon Sep 17 00:00:00 2001 From: Teodor Taushanov Date: Fri, 10 Jul 2026 14:05:29 +0300 Subject: [PATCH 1/4] chore: include margins into calcs --- packages/fiori/src/SideNavigation.ts | 27 +++++++++++++------ packages/fiori/src/themes/SideNavigation.css | 8 ++++++ .../fiori/src/themes/SideNavigationGroup.css | 10 +------ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/packages/fiori/src/SideNavigation.ts b/packages/fiori/src/SideNavigation.ts index 046031c798a71..00a36a8b7b034 100644 --- a/packages/fiori/src/SideNavigation.ts +++ b/packages/fiori/src/SideNavigation.ts @@ -535,13 +535,22 @@ class SideNavigation extends UI5Element { return sum; } itemRef.classList.remove("ui5-sn-item-hidden"); - return sum + itemRef.offsetHeight; + + let itemDomRef = itemRef; + + if (isInstanceOfSideNavigationItemBase(itemRef) && itemRef.getDomRef()) { + itemDomRef = itemRef.getDomRef()!; + } + + const { marginTop, marginBottom } = window.getComputedStyle(itemDomRef); + + return sum + itemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); }, 0); const { paddingTop, paddingBottom } = window.getComputedStyle(flexibleContentDomRef); const listHeight = flexibleContentDomRef?.offsetHeight - parseInt(paddingTop) - parseInt(paddingBottom); - if (itemsHeight <= listHeight) { + if (itemsHeight < listHeight) { return; } @@ -573,13 +582,15 @@ class SideNavigation extends UI5Element { itemDomRef = item; } - if (itemDomRef) { - const { marginTop, marginBottom } = window.getComputedStyle(itemDomRef); - itemsHeight += itemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); + if (!itemDomRef) { + return; + } + + const { marginTop, marginBottom } = window.getComputedStyle(itemDomRef); + itemsHeight += itemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); - if (itemsHeight > listHeight) { - item.classList.add("ui5-sn-item-hidden"); - } + if (itemsHeight > listHeight) { + item.classList.add("ui5-sn-item-hidden"); } }); diff --git a/packages/fiori/src/themes/SideNavigation.css b/packages/fiori/src/themes/SideNavigation.css index 47fdadb8fa4b6..c4b934154865a 100644 --- a/packages/fiori/src/themes/SideNavigation.css +++ b/packages/fiori/src/themes/SideNavigation.css @@ -75,4 +75,12 @@ .ui5-sn-item-overflow { margin-top: auto; +} + +.ui5-sn-spacer { + margin: var(--_ui5_side_navigation_navigation_separator_margin); + height: var(--_ui5_side_navigation_navigation_separator_height); + min-height: var(--_ui5_side_navigation_navigation_separator_height); + background-color: var(--_ui5_side_navigation_navigation_separator_background_color); + border-radius: var(--_ui5_side_navigation_navigation_separator_radius); } \ No newline at end of file diff --git a/packages/fiori/src/themes/SideNavigationGroup.css b/packages/fiori/src/themes/SideNavigationGroup.css index 00833c2f23d2b..c28a6eb844165 100644 --- a/packages/fiori/src/themes/SideNavigationGroup.css +++ b/packages/fiori/src/themes/SideNavigationGroup.css @@ -22,12 +22,4 @@ .ui5-sn-item-group-below-group.ui5-sn-item-separator, .ui5-sn-item-group-below-group .ui5-sn-item-separator:first-child { display: none; -} - -.ui5-sn-spacer { - margin: var(--_ui5_side_navigation_navigation_separator_margin); - height: var(--_ui5_side_navigation_navigation_separator_height); - min-height: var(--_ui5_side_navigation_navigation_separator_height); - background-color: var(--_ui5_side_navigation_navigation_separator_background_color); - border-radius: var(--_ui5_side_navigation_navigation_separator_radius); -} +} \ No newline at end of file From 5e81e31c5ef5832f6546c1181f35cbff1cd9cf43 Mon Sep 17 00:00:00 2001 From: Teodor Taushanov Date: Tue, 28 Jul 2026 13:24:14 +0300 Subject: [PATCH 2/4] chore: add test file --- .../fiori/test/pages/SideNavigationTest.html | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/fiori/test/pages/SideNavigationTest.html diff --git a/packages/fiori/test/pages/SideNavigationTest.html b/packages/fiori/test/pages/SideNavigationTest.html new file mode 100644 index 0000000000000..cf054c63c34c1 --- /dev/null +++ b/packages/fiori/test/pages/SideNavigationTest.html @@ -0,0 +1,68 @@ + + + + + Side Navigation Only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 89486f132f5cc4ffe044e91e67104e3525ad1f39 Mon Sep 17 00:00:00 2001 From: Teodor Taushanov Date: Tue, 28 Jul 2026 14:41:02 +0300 Subject: [PATCH 3/4] chore: add additional calculations --- packages/fiori/src/SideNavigation.ts | 45 +++++++++++++++---- .../src/themes/SideNavigationItemBase.css | 1 + .../fiori/test/pages/SideNavigationTest.html | 5 +++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/fiori/src/SideNavigation.ts b/packages/fiori/src/SideNavigation.ts index 8933993bc393d..81f62170fc1fb 100644 --- a/packages/fiori/src/SideNavigation.ts +++ b/packages/fiori/src/SideNavigation.ts @@ -571,7 +571,7 @@ class SideNavigation extends UI5Element { }, 0); const { paddingTop, paddingBottom } = window.getComputedStyle(flexibleContentDomRef); - const listHeight = flexibleContentDomRef?.offsetHeight - parseInt(paddingTop) - parseInt(paddingBottom); + let listHeight = flexibleContentDomRef?.offsetHeight - parseInt(paddingTop) - parseInt(paddingBottom); if (itemsHeight < listHeight) { return; @@ -590,32 +590,61 @@ class SideNavigation extends UI5Element { const { marginTop, marginBottom } = window.getComputedStyle(selectedItemDomRef); itemsHeight += selectedItemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); } + + const indexOf = overflowItems.indexOf(selectedItem); + const itemAfterSelected = overflowItems[indexOf + 1]; + if (itemAfterSelected && !isInstanceOfSideNavigationItemBase(itemAfterSelected)) { + itemsHeight += itemAfterSelected.offsetHeight; + } + } + + listHeight--; + + const lastItem = overflowItems[overflowItems.length - 1]; + if (!isInstanceOfSideNavigationItemBase(lastItem)) { + listHeight -= lastItem.offsetHeight; } - overflowItems.forEach(item => { + for (let i = 0; i < overflowItems.length; i++) { + const item = overflowItems[i]; + const nextItem = overflowItems[i + 1]; + let nextItemDomRef; + if (!item || item === selectedItem) { - return; + continue; } let itemDomRef; - if (isInstanceOfSideNavigationItemBase(item) && item.getDomRef()) { + if (isInstanceOfSideNavigationItemBase(item)) { itemDomRef = item.getDomRef(); - } else { - itemDomRef = item; } if (!itemDomRef) { - return; + continue; } const { marginTop, marginBottom } = window.getComputedStyle(itemDomRef); itemsHeight += itemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); + if (nextItem && !isInstanceOfSideNavigationItemBase(nextItem)) { + nextItemDomRef = nextItem; + i++; + + if (!nextItemDomRef) { + debugger; + } + + itemsHeight += nextItemDomRef.offsetHeight; + } + if (itemsHeight > listHeight) { item.classList.add("ui5-sn-item-hidden"); + nextItemDomRef?.classList.add("ui5-sn-item-hidden"); } - }); + + nextItemDomRef = null; + } this._flexibleItemNavigation._init(); } diff --git a/packages/fiori/src/themes/SideNavigationItemBase.css b/packages/fiori/src/themes/SideNavigationItemBase.css index 0645081b1bc7b..e55a1ac8d33ae 100644 --- a/packages/fiori/src/themes/SideNavigationItemBase.css +++ b/packages/fiori/src/themes/SideNavigationItemBase.css @@ -407,4 +407,5 @@ and there is an additional border that appears on hover. */ .ui5-sn-item-separator { min-height: 0.625rem; + background: red; } diff --git a/packages/fiori/test/pages/SideNavigationTest.html b/packages/fiori/test/pages/SideNavigationTest.html index cf054c63c34c1..cbb63a9404f11 100644 --- a/packages/fiori/test/pages/SideNavigationTest.html +++ b/packages/fiori/test/pages/SideNavigationTest.html @@ -52,6 +52,11 @@ > + + Date: Tue, 28 Jul 2026 16:02:51 +0300 Subject: [PATCH 4/4] chore: code refactoring --- packages/fiori/src/SideNavigation.ts | 95 +++++++++++++++++----------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/packages/fiori/src/SideNavigation.ts b/packages/fiori/src/SideNavigation.ts index 81f62170fc1fb..52f8ac46629e0 100644 --- a/packages/fiori/src/SideNavigation.ts +++ b/packages/fiori/src/SideNavigation.ts @@ -537,23 +537,8 @@ class SideNavigation extends UI5Element { } } - _updateOverflowItems() { - const domRef = this.getDomRef(); - if (!this.collapsed || !domRef) { - return null; - } - - const overflowItem = this._overflowItem!; - const flexibleContentDomRef: HTMLElement = domRef.querySelector(".ui5-sn-flexible")!; - if (!overflowItem) { - return null; - } - - overflowItem.classList.add("ui5-sn-item-hidden"); - - const overflowItems = this.overflowItems; - - let itemsHeight = overflowItems.reduce((sum, itemRef) => { + _resetAndCalculateItemsHeight() { + return this.overflowItems.reduce((sum, itemRef) => { if (!itemRef) { return sum; } @@ -569,41 +554,38 @@ class SideNavigation extends UI5Element { return sum + itemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); }, 0); + } - const { paddingTop, paddingBottom } = window.getComputedStyle(flexibleContentDomRef); - let listHeight = flexibleContentDomRef?.offsetHeight - parseInt(paddingTop) - parseInt(paddingBottom); + _getSelectedItemHeight() { + const overflowItems = this.overflowItems; + const selectedItem = overflowItems.filter(isInstanceOfSideNavigationSelectableItemBase).find(item => item._selected); - if (itemsHeight < listHeight) { - return; + if (!selectedItem) { + return 0; } - overflowItem.classList.remove("ui5-sn-item-hidden"); - - itemsHeight = overflowItem.offsetHeight; - - const selectedItem = overflowItems.filter(isInstanceOfSideNavigationSelectableItemBase).find(item => item._selected); + let height = 0; if (selectedItem) { const selectedItemDomRef = selectedItem.getDomRef(); if (selectedItemDomRef) { const { marginTop, marginBottom } = window.getComputedStyle(selectedItemDomRef); - itemsHeight += selectedItemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); + height += selectedItemDomRef.offsetHeight + parseFloat(marginTop) + parseFloat(marginBottom); } const indexOf = overflowItems.indexOf(selectedItem); const itemAfterSelected = overflowItems[indexOf + 1]; if (itemAfterSelected && !isInstanceOfSideNavigationItemBase(itemAfterSelected)) { - itemsHeight += itemAfterSelected.offsetHeight; + height += itemAfterSelected.offsetHeight; } } - listHeight--; + return height; + } - const lastItem = overflowItems[overflowItems.length - 1]; - if (!isInstanceOfSideNavigationItemBase(lastItem)) { - listHeight -= lastItem.offsetHeight; - } + _updateVisibility(selectedItem: SideNavigationSelectableItemBase | undefined, itemsHeight: number, listHeight: number) { + const overflowItems = this.overflowItems; for (let i = 0; i < overflowItems.length; i++) { const item = overflowItems[i]; @@ -631,10 +613,6 @@ class SideNavigation extends UI5Element { nextItemDomRef = nextItem; i++; - if (!nextItemDomRef) { - debugger; - } - itemsHeight += nextItemDomRef.offsetHeight; } @@ -645,6 +623,49 @@ class SideNavigation extends UI5Element { nextItemDomRef = null; } + } + + _updateOverflowItems() { + const domRef = this.getDomRef(); + if (!this.collapsed || !domRef) { + return null; + } + + const overflowItem = this._overflowItem; + if (!overflowItem) { + return null; + } + + overflowItem.classList.add("ui5-sn-item-hidden"); + + const overflowItems = this.overflowItems; + + let itemsHeight = this._resetAndCalculateItemsHeight(); + + const flexibleContentDomRef: HTMLElement = domRef.querySelector(".ui5-sn-flexible")!; + const { paddingTop, paddingBottom } = window.getComputedStyle(flexibleContentDomRef); + let listHeight = flexibleContentDomRef?.offsetHeight - parseInt(paddingTop) - parseInt(paddingBottom); + + if (itemsHeight < listHeight) { + return; + } + + overflowItem.classList.remove("ui5-sn-item-hidden"); + + itemsHeight = overflowItem.offsetHeight; + + const selectedItem = overflowItems.filter(isInstanceOfSideNavigationSelectableItemBase).find(item => item._selected); + + itemsHeight += this._getSelectedItemHeight(); + + listHeight--; // account for sub-pixel rounding + + const lastItem = overflowItems[overflowItems.length - 1]; + if (!isInstanceOfSideNavigationItemBase(lastItem)) { + listHeight -= lastItem.offsetHeight; + } + + this._updateVisibility(selectedItem, itemsHeight, listHeight); this._flexibleItemNavigation._init(); }