menu: Always align the flyout caret with the menu item

This commit is contained in:
Johannes Meyer 2025-04-30 10:02:37 +02:00
parent 91396aeb73
commit 6100281c89
2 changed files with 22 additions and 19 deletions

View File

@ -259,6 +259,7 @@
width: 14em; width: 14em;
position: fixed; position: fixed;
z-index: 1; z-index: 1;
margin-top: -1px; // Align content with the menu item, not its border
&::after { &::after {
.transform(rotate(45deg)); .transform(rotate(45deg));
@ -271,14 +272,18 @@
height: 1.1em; height: 1.1em;
width: 1.1em; width: 1.1em;
position: absolute; position: absolute;
top: 1em; top: ~"calc((@{nav-item-height} / 2) - (1.1em / 2))";
left: -.6em; left: -.6em;
z-index: -1; z-index: -1;
} }
&.bottom-up::after { &.bottom-up {
top: unset; --caretY: 100%;
bottom: 1em; margin-top: 1px;
&::after {
top: ~"calc(var(--caretY) - (@{nav-item-height} / 2) - (1.1em / 2))";
}
} }
> .nav-item { > .nav-item {
@ -325,17 +330,13 @@
#layout:not(.minimal-layout) #menu .nav-level-1 > .nav-item:not(.active).hover { #layout:not(.minimal-layout) #menu .nav-level-1 > .nav-item:not(.active).hover {
> .nav-level-2 { > .nav-level-2 {
// Position relative to parent
margin-left: 16em; margin-left: 16em;
margin-top: -3.167em;
} }
} }
#layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item.hover { #layout:not(.minimal-layout).sidebar-collapsed #menu .nav-level-1 > .nav-item.hover {
> .nav-level-2 { > .nav-level-2 {
// Position relative to parent
margin-left: 4em; margin-left: 4em;
margin-top: -3.333em;
> .badge-nav-item { > .badge-nav-item {
display: flex; display: flex;

View File

@ -319,23 +319,25 @@
$target.siblings().not($target).removeClass('hover'); $target.siblings().not($target).removeClass('hover');
$target.addClass('hover'); $target.addClass('hover');
var targetHeight = $target.offset().top + $target.outerHeight(); const targetRect = $target[0].getBoundingClientRect();
$flyout.css({ const flyoutRect = $flyout[0].getBoundingClientRect();
bottom: 'auto',
top: targetHeight
});
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.addClass('bottom-up');
$flyout.css({
bottom: window.innerHeight - targetHeight,
top: 'auto'
});
} else { } else {
$flyout.removeClass('bottom-up'); $flyout.removeClass('bottom-up');
css.top = targetRect.top;
} }
$flyout.css(css);
}, delay); }, delay);
}; };