diff --git a/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor b/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor index 4c638f7..9cfb97d 100644 --- a/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor +++ b/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor @@ -13,14 +13,20 @@ @if (navPage.HasChildren) { @* Dual-role node: the parent anchor navigates to its own route on click, - while hover/focus reveals the child dropdown (pure CSS, no JS). *@ -
  • + while hover/focus reveals the child dropdown (pure CSS, no JS). + dd-nav-item-collapsed is added on child click to force-hide the + dropdown after SPA navigation (which keeps the DOM and may leave + :hover true). It is cleared on mouseleave so the next hover works. *@ +
  • @navPage.Name @@ -90,6 +96,7 @@ [Parameter] public required EventCallback IsDarkModeChanged { get; set; } private bool _mobileMenuOpen; + private readonly HashSet _collapsedDropdowns = []; protected override async Task OnAfterRenderAsync(bool firstRender) { @@ -122,4 +129,8 @@ private void ToggleMobileMenu() => _mobileMenuOpen = !_mobileMenuOpen; private void CloseMobileMenu() => _mobileMenuOpen = false; + + private void CollapseDropdown(string route) => _collapsedDropdowns.Add(route); + + private void ResetDropdown(string route) => _collapsedDropdowns.Remove(route); } diff --git a/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor.css b/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor.css index 7d5f05a..1d4f6e8 100644 --- a/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor.css +++ b/DeepDrftPublic.Client/Layout/DeepDrftMenu.razor.css @@ -129,6 +129,15 @@ pointer-events: auto; } +/* Force-close the dropdown immediately after a child link is clicked (SPA navigation + keeps the DOM and :hover may remain true). Cleared on mouseleave so the next + hover cycle works normally. */ +.dd-nav-item-parent.dd-nav-item-collapsed .dd-nav-dropdown { + opacity: 0 !important; + visibility: hidden !important; + pointer-events: none !important; +} + .dd-nav-dropdown-link { white-space: nowrap; }