From 6100281c897cc9f8bf13e2aceacfd05705d88583 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 30 Apr 2025 10:02:37 +0200 Subject: [PATCH] menu: Always align the flyout caret with the menu item --- public/css/icinga/menu.less | 17 +++++++++-------- public/js/icinga/behavior/navigation.js | 24 +++++++++++++----------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/public/css/icinga/menu.less b/public/css/icinga/menu.less index 9c7b45c6f..a7dbf6598 100644 --- a/public/css/icinga/menu.less +++ b/public/css/icinga/menu.less @@ -259,6 +259,7 @@ width: 14em; position: fixed; z-index: 1; + margin-top: -1px; // Align content with the menu item, not its border &::after { .transform(rotate(45deg)); @@ -271,14 +272,18 @@ height: 1.1em; width: 1.1em; position: absolute; - top: 1em; + top: ~"calc((@{nav-item-height} / 2) - (1.1em / 2))"; left: -.6em; z-index: -1; } - &.bottom-up::after { - top: unset; - bottom: 1em; + &.bottom-up { + --caretY: 100%; + margin-top: 1px; + + &::after { + top: ~"calc(var(--caretY) - (@{nav-item-height} / 2) - (1.1em / 2))"; + } } > .nav-item { @@ -325,17 +330,13 @@ #layout:not(.minimal-layout) #menu .nav-level-1 > .nav-item:not(.active).hover { > .nav-level-2 { - // Position relative to parent margin-left: 16em; - margin-top: -3.167em; } } #layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item.hover { > .nav-level-2 { - // Position relative to parent margin-left: 4em; - margin-top: -3.333em; > .badge-nav-item { display: flex; diff --git a/public/js/icinga/behavior/navigation.js b/public/js/icinga/behavior/navigation.js index bcf5bebd5..fb593fe88 100644 --- a/public/js/icinga/behavior/navigation.js +++ b/public/js/icinga/behavior/navigation.js @@ -319,23 +319,25 @@ $target.siblings().not($target).removeClass('hover'); $target.addClass('hover'); - var targetHeight = $target.offset().top + $target.outerHeight(); - $flyout.css({ - bottom: 'auto', - top: targetHeight - }); + const targetRect = $target[0].getBoundingClientRect(); + const flyoutRect = $flyout[0].getBoundingClientRect(); - var rect = $flyout[0].getBoundingClientRect(); + const css = { "--caretY": "" }; + if (targetRect.top + flyoutRect.height > window.innerHeight) { + css.top = targetRect.bottom - flyoutRect.height; + if (css.top < 10) { + css.top = 10; + // Not sure why -2, but it aligns the caret perfectly with the menu item + css["--caretY"] = `${targetRect.bottom - 10 - 2}px`; + } - if (rect.bottom > window.innerHeight) { $flyout.addClass('bottom-up'); - $flyout.css({ - bottom: window.innerHeight - targetHeight, - top: 'auto' - }); } else { $flyout.removeClass('bottom-up'); + css.top = targetRect.top; } + + $flyout.css(css); }, delay); };