fix(nav): close hamburger menu when nested dropdown closes and mouse not hovering
Fixed issue where hamburger menu would stay open after: 1. Hover over hamburger (opens) 2. Click style dropdown (opens) 3. Click outside to close style dropdown 4. Hamburger stays open until clicked Solution: - Track hover state with useRef to know real-time mouse position - When nested dropdown closes, check if mouse is still hovering - If not hovering, close hamburger immediately Also cleaned up debug console.log statements now that the issue is resolved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -19,10 +19,7 @@ export function AbacusDisplayDropdown({ isFullscreen = false, onOpenChange: onOp
|
||||
const [open, setOpen] = useState(false)
|
||||
const { config, updateConfig, resetToDefaults } = useAbacusDisplay()
|
||||
|
||||
console.log('[AbacusDisplayDropdown] State:', { open })
|
||||
|
||||
const handleOpenChange = (isOpen: boolean) => {
|
||||
console.log('[AbacusDisplayDropdown] onOpenChange called with:', isOpen, 'current open:', open)
|
||||
setOpen(isOpen)
|
||||
// Notify parent component
|
||||
onOpenChangeProp?.(isOpen)
|
||||
@@ -81,12 +78,6 @@ export function AbacusDisplayDropdown({ isFullscreen = false, onOpenChange: onOp
|
||||
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
onInteractOutside={(e) => {
|
||||
const target = e.target as HTMLElement
|
||||
console.log('[AbacusDisplayDropdown] onInteractOutside triggered')
|
||||
console.log('[AbacusDisplayDropdown] Target element:', target)
|
||||
console.log('[AbacusDisplayDropdown] Target tagName:', target.tagName)
|
||||
}}
|
||||
className={css({
|
||||
bg: isFullscreen ? 'rgba(0, 0, 0, 0.85)' : 'white',
|
||||
rounded: 'xl',
|
||||
|
||||
@@ -35,14 +35,13 @@ function HamburgerMenu({
|
||||
const [hovered, setHovered] = useState(false)
|
||||
const [nestedDropdownOpen, setNestedDropdownOpen] = useState(false)
|
||||
const hoverTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
|
||||
const isCurrentlyHovering = React.useRef(false)
|
||||
|
||||
// Open on hover or click OR if nested dropdown is open
|
||||
const isOpen = open || hovered || nestedDropdownOpen
|
||||
|
||||
console.log('[HamburgerMenu] State:', { open, hovered, nestedDropdownOpen, isOpen })
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
console.log('[HamburgerMenu] Mouse enter')
|
||||
isCurrentlyHovering.current = true
|
||||
if (hoverTimeoutRef.current) {
|
||||
clearTimeout(hoverTimeoutRef.current)
|
||||
hoverTimeoutRef.current = null
|
||||
@@ -51,25 +50,32 @@ function HamburgerMenu({
|
||||
}
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
console.log('[HamburgerMenu] Mouse leave, nestedDropdownOpen:', nestedDropdownOpen)
|
||||
isCurrentlyHovering.current = false
|
||||
// Don't close if nested dropdown is open
|
||||
if (nestedDropdownOpen) {
|
||||
console.log('[HamburgerMenu] Skipping close - nested dropdown is open')
|
||||
return
|
||||
}
|
||||
|
||||
// Delay closing to allow moving from button to menu
|
||||
hoverTimeoutRef.current = setTimeout(() => {
|
||||
console.log('[HamburgerMenu] Mouse leave timeout fired')
|
||||
setHovered(false)
|
||||
}, 150)
|
||||
}
|
||||
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
console.log('[HamburgerMenu] onOpenChange called with:', newOpen, 'current open:', open)
|
||||
setOpen(newOpen)
|
||||
}
|
||||
|
||||
const handleNestedDropdownChange = (isNestedOpen: boolean) => {
|
||||
setNestedDropdownOpen(isNestedOpen)
|
||||
|
||||
// When nested dropdown closes, also close hamburger if mouse is not hovering
|
||||
if (!isNestedOpen && !isCurrentlyHovering.current) {
|
||||
setHovered(false)
|
||||
setOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => {
|
||||
if (hoverTimeoutRef.current) {
|
||||
@@ -122,18 +128,8 @@ function HamburgerMenu({
|
||||
onInteractOutside={(e) => {
|
||||
// Don't close the hamburger menu when clicking inside the nested style dropdown
|
||||
const target = e.target as HTMLElement
|
||||
console.log('[HamburgerMenu] onInteractOutside triggered')
|
||||
console.log('[HamburgerMenu] Target element:', target)
|
||||
console.log('[HamburgerMenu] Target tagName:', target.tagName)
|
||||
console.log('[HamburgerMenu] Target className:', target.className)
|
||||
console.log('[HamburgerMenu] Has [role="dialog"]:', !!target.closest('[role="dialog"]'))
|
||||
console.log('[HamburgerMenu] Has [data-radix-popper-content-wrapper]:', !!target.closest('[data-radix-popper-content-wrapper]'))
|
||||
|
||||
if (target.closest('[role="dialog"]') || target.closest('[data-radix-popper-content-wrapper]')) {
|
||||
console.log('[HamburgerMenu] Preventing close - nested dropdown interaction')
|
||||
e.preventDefault()
|
||||
} else {
|
||||
console.log('[HamburgerMenu] Allowing close - outside interaction')
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
@@ -385,7 +381,7 @@ function HamburgerMenu({
|
||||
<div style={{ padding: '0 6px' }}>
|
||||
<AbacusDisplayDropdown
|
||||
isFullscreen={isFullscreen}
|
||||
onOpenChange={setNestedDropdownOpen}
|
||||
onOpenChange={handleNestedDropdownChange}
|
||||
/>
|
||||
</div>
|
||||
</DropdownMenu.Content>
|
||||
|
||||
Reference in New Issue
Block a user