Merge p9-w8-8j-popover-dismiss into dev (8.J: close ARCHIVE dropdown on child click)

This commit is contained in:
daniel-c-harvey
2026-06-13 20:08:03 -04:00
2 changed files with 23 additions and 3 deletions
@@ -13,14 +13,20 @@
@if (navPage.HasChildren) @if (navPage.HasChildren)
{ {
@* Dual-role node: the parent anchor navigates to its own route on click, @* 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).
<li class="dd-nav-item-parent"> 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. *@
<li class="dd-nav-item-parent @(_collapsedDropdowns.Contains(navPage.Route) ? "dd-nav-item-collapsed" : "")"
@onmouseleave="() => ResetDropdown(navPage.Route)"
@onfocusout="() => ResetDropdown(navPage.Route)">
<a href="@navPage.Route" class="dd-nav-link">@navPage.Name</a> <a href="@navPage.Route" class="dd-nav-link">@navPage.Name</a>
<ul class="dd-nav-dropdown"> <ul class="dd-nav-dropdown">
@foreach (var child in navPage.Children) @foreach (var child in navPage.Children)
{ {
<li> <li>
<a href="@child.Route" class="dd-nav-link dd-nav-dropdown-link">@child.Name</a> <a href="@child.Route" class="dd-nav-link dd-nav-dropdown-link"
@onclick="() => CollapseDropdown(navPage.Route)">@child.Name</a>
</li> </li>
} }
</ul> </ul>
@@ -90,6 +96,7 @@
[Parameter] public required EventCallback<bool> IsDarkModeChanged { get; set; } [Parameter] public required EventCallback<bool> IsDarkModeChanged { get; set; }
private bool _mobileMenuOpen; private bool _mobileMenuOpen;
private readonly HashSet<string> _collapsedDropdowns = [];
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
@@ -122,4 +129,8 @@
private void ToggleMobileMenu() => _mobileMenuOpen = !_mobileMenuOpen; private void ToggleMobileMenu() => _mobileMenuOpen = !_mobileMenuOpen;
private void CloseMobileMenu() => _mobileMenuOpen = false; private void CloseMobileMenu() => _mobileMenuOpen = false;
private void CollapseDropdown(string route) => _collapsedDropdowns.Add(route);
private void ResetDropdown(string route) => _collapsedDropdowns.Remove(route);
} }
@@ -129,6 +129,15 @@
pointer-events: auto; 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 { .dd-nav-dropdown-link {
white-space: nowrap; white-space: nowrap;
} }