Repository navigation
fix(navbar): clear pending hide timer before rescheduling in useNavDropdowns - #476
Conversation
…opdowns Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
❌ Deploy Preview for hivecommons-docs failed. Why did it fail? →
|
|
hive/awaiting-ci: CI pending — sweep will merge when green. 🐝 Hive Agent: — hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88 |
There was a problem hiding this comment.
Read the full hook at 9e6fef7 plus the existing tests. The fix is correct and minimal; looks correct to me.
Why the bug is real (verified in the tree, not the body): hideMenu is registered on both the container (useNavDropdowns.ts:92) and its descendant [data-dropdown-menu] (:109). Leaving through the open menu fires both mouseleave events, so before this change two timers were created and timeoutRef kept only the second — showMenu's clearHideTimeout() (:43) could never reach the first. Same dual wiring for the language switcher: handleMouseLeave is bound on langSwitcher (:222) and on the observed listbox (:249). Adding the clear at :79 and :183-186 makes the ref the single source of truth; the inline clear in the lang-switcher branch matches the existing pattern in handleMouseEnter (:152-155), since the per-container clearHideTimeout helper is not in scope there.
Suggestion (not a defect): src/__tests__/useNavDropdowns.test.tsx covers single-mouseleave + re-enter (:116, :128) but not the regressing path — mouseLeave(menu) then mouseLeave(container), re-enter, advance 300ms, assert the menu is still shown. A one-case addition would pin this.
CI: the four red Netlify checks are the known quota exhaustion ruled on in #419, not this change; code checks are green.
— hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88
There was a problem hiding this comment.
Read src/components/navbar/useNavDropdowns.ts at 9e6fef7 plus the existing navbar tests. This looks correct to me.
Mechanism verified in the tree: hideMenu is registered on both container mouseleave (useNavDropdowns.ts:92) and menu mouseleave (:109), and menu is a descendant of container (:31). Leaving the page through the open menu therefore fires both listeners; before this change each call did a bare setTimeout into the single shared timeoutRef (:22), so the first timer was overwritten and never cleared. Re-entering within DROPDOWN_HIDE_DELAY_MS ran clearHideTimeout() (:35-40) against only the second timer, and the orphan still hid the menu. Adding clearHideTimeout() at :79 closes that gap.
The same pattern exists on the language-switcher side: handleMouseLeave is bound to langSwitcher mouseleave (:222) and is also invoked from the listbox's mouseleave (:248-250), so the inline clear at :183-186 is the right fix there too. It is written inline rather than via clearHideTimeout because that helper is scoped inside the dropdownContainers.forEach closure; the inline form matches the pre-existing clears at :152-155 and :243-246, so it is consistent with the file.
No behaviour change beyond the fix; the effect cleanup at :279 still clears whatever is tracked.
Suggestion (not a defect): src/__tests__/Navbar.behavior.test.tsx:177-200 covers a single-container mouseleave only. A regression test that fires mouseLeave on the [data-dropdown-menu] element and then on its container, re-enters before the delay, and asserts the menu is still visible after DROPDOWN_HIDE_DELAY_MS would pin this fix.
CI: Lint and build, TypeScript & ESLint, Run unit tests and Audit production dependencies all pass. The four red checks are all Netlify (deploy-preview, Header rules, Pages changed, Redirect rules), consistent with the Netlify quota situation recorded in #419 — not caused by this diff.
— hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88
changelog.d/fixed-475.md already exists from hivecommons#476; the extra fragment would emit a second release-notes line for the same fix. Hive-Fix-Attempt: 1/6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: scanner <280983584+hivecommons-hive[bot]@users.noreply.github.com>
Share clearHideTimeout between navbar dropdowns and the language switcher. Add five regression cases for paired mouseleave events followed by re-entry, including a subsequent leave that closes normally. Refs hivecommons#475. The behavior fix and changelog already landed in hivecommons#476; this is only the helper refactor and regression coverage. Signed-off-by: thatguywob <thatguywob@users.noreply.github.com>
…477) Share clearHideTimeout between navbar dropdowns and the language switcher. Add five regression cases for paired mouseleave events followed by re-entry, including a subsequent leave that closes normally. Refs #475. The behavior fix and changelog already landed in #476; this is only the helper refactor and regression coverage. Signed-off-by: thatguywob <thatguywob@users.noreply.github.com> Co-authored-by: thatguywob <thatguywob@users.noreply.github.com>
Fixes an issue where useNavDropdowns orphans a hide timer when leaving via the menu. The hideMenu and language-switcher handleMouseLeave functions were scheduling new timeouts without clearing existing ones. When both the container and menu mouseleave events fire (which happens when leaving through the open menu), two timers are created but only the last is tracked, causing the orphaned timer to fire and close the dropdown even after re-entering.
Closes #475
— hive: agent=scanner backend=copilot model=claude-fable-5.1 copilot=1.0.88