fix: close collapsed navigation flyouts

This commit is contained in:
2026-07-31 11:21:52 +02:00
parent 5a2276aec9
commit 10e57c0514
4 changed files with 59 additions and 11 deletions
+3 -1
View File
@@ -32,7 +32,7 @@ Release-Tag oder ein bestimmter Commit verwendet werden:
```bash
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.5.1"
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.5.2"
```
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
@@ -209,6 +209,8 @@ ein und wieder aus. Dafür gibt es kein zusätzliches Bedienmenü. Beim Ziehen
wird die neue Breite nach dem Loslassen im Benutzerprofil gespeichert. Im
Icon-Modus öffnen sich die Menüinhalte als seitliches Flyout; auf kleinen
beziehungsweise mobilen Ansichten bleibt das normale NetBox-Menü erhalten.
Das Flyout schließt sich bei Auswahl eines Eintrags, bei erneutem Klick auf
das aktive Icon, bei einem Klick außerhalb und mit der Escape-Taste.
**Zurücksetzen** stellt neben Reihenfolge und Sichtbarkeit auch die normale
ausgeklappte Breite von 288 Pixeln wieder her.
+1 -1
View File
@@ -1,6 +1,6 @@
from netbox.plugins import PluginConfig, get_plugin_config
__version__ = "0.5.1"
__version__ = "0.5.2"
class NetBoxUtilitiesConfig(PluginConfig):
@@ -71,20 +71,40 @@
});
}
function closeDropdown(item) {
if (!item) return false;
const button = item.querySelector(':scope > button.nav-link');
const menu = item.querySelector(':scope > .dropdown-menu');
if (!button || !menu?.classList.contains('show')) return false;
// Let NetBox/Bootstrap tear down its Popper instance when available.
button.click();
if (!menu.classList.contains('show')) {
menu.style.removeProperty('--netbox-utilities-dropdown-top');
return true;
}
// Fallback for pages on which Bootstrap's data API is unavailable.
button.classList.remove('show');
button.setAttribute('aria-expanded', 'false');
menu.classList.remove('show');
menu.style.removeProperty('--netbox-utilities-dropdown-top');
return true;
}
function closeDropdowns(sidebar, exceptItem = null) {
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((item) => {
if (item !== exceptItem) closeDropdown(item);
});
}
function configureCollapsedDropdowns(sidebar) {
sidebar.addEventListener('show.bs.dropdown', (event) => {
if (!preferences.collapsed) return;
const item = event.target.closest('.nav-item.dropdown');
if (!item) return;
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((otherItem) => {
if (otherItem === item) return;
const otherButton = otherItem.querySelector(':scope > button.nav-link');
const otherMenu = otherItem.querySelector(':scope > .dropdown-menu');
otherButton?.classList.remove('show');
otherButton?.setAttribute('aria-expanded', 'false');
otherMenu?.classList.remove('show');
});
closeDropdowns(sidebar, item);
const button = item.querySelector(':scope > button.nav-link');
const menu = item.querySelector(':scope > .dropdown-menu');
@@ -92,6 +112,32 @@
const top = Math.max(8, button.getBoundingClientRect().top);
menu.style.setProperty('--netbox-utilities-dropdown-top', `${top}px`);
});
sidebar.addEventListener('click', (event) => {
if (!preferences.collapsed || !(event.target instanceof Element)) return;
const selectedOption = event.target.closest('.dropdown-menu a[href], .dropdown-menu button');
if (selectedOption) closeDropdown(selectedOption.closest('.nav-item.dropdown'));
});
document.addEventListener(
'click',
(event) => {
if (!preferences.collapsed || !(event.target instanceof Element)) return;
sidebar.querySelectorAll(':scope > li.nav-item.dropdown').forEach((item) => {
if (!item.contains(event.target)) closeDropdown(item);
});
},
true
);
document.addEventListener('keydown', (event) => {
if (!preferences.collapsed || event.key !== 'Escape') return;
const openItem = sidebar.querySelector(':scope > li.nav-item.dropdown > .dropdown-menu.show')?.closest('.nav-item');
if (openItem && closeDropdown(openItem)) {
openItem.querySelector(':scope > button.nav-link')?.focus();
event.preventDefault();
}
});
}
async function saveLayout(action, width) {
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "netbox-utilities"
version = "0.5.1"
version = "0.5.2"
description = "Navigation, tenant filtering, bulk module installation, and atomic rack reordering for NetBox 4.6"
readme = "README.md"
requires-python = ">=3.12"