mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 04:26:57 +00:00
menu close on click outside
This commit is contained in:
@@ -1,13 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import HamburgerMenu from "@/components/HamburgerMenu";
|
import HamburgerMenu from "@/components/HamburgerMenu";
|
||||||
import { useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
|
||||||
const Hamburger = () => {
|
const Hamburger = () => {
|
||||||
const [menuVisible, setMenuVisible] = useState(false);
|
const [menuVisible, setMenuVisible] = useState(false);
|
||||||
|
const hamburgerButtonRef = useRef<HTMLDivElement>(null);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
|
ref={hamburgerButtonRef}
|
||||||
className="space-y-2 relative z-[99999]"
|
className="space-y-2 relative z-[99999]"
|
||||||
onClick={() => setMenuVisible(!menuVisible)}
|
onClick={() => setMenuVisible(!menuVisible)}
|
||||||
>
|
>
|
||||||
@@ -31,6 +33,7 @@ const Hamburger = () => {
|
|||||||
<HamburgerMenu
|
<HamburgerMenu
|
||||||
menuVisible={menuVisible}
|
menuVisible={menuVisible}
|
||||||
setMenuVisible={setMenuVisible}
|
setMenuVisible={setMenuVisible}
|
||||||
|
hamburgerButtonRef={hamburgerButtonRef}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,15 +1,49 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import ThemeSwitcher from "@/components/ThemeSwitcher";
|
import ThemeSwitcher from "@/components/ThemeSwitcher";
|
||||||
import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react";
|
import {
|
||||||
|
Dispatch,
|
||||||
|
RefObject,
|
||||||
|
SetStateAction,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
type menuState = {
|
type hamburgerMenuState = {
|
||||||
menuVisible: boolean;
|
menuVisible: boolean;
|
||||||
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
||||||
|
hamburgerButtonRef: RefObject<HTMLDivElement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const HamburgerMenu = ({ menuVisible, setMenuVisible }: menuState) => {
|
const HamburgerMenu = ({
|
||||||
|
menuVisible,
|
||||||
|
setMenuVisible,
|
||||||
|
hamburgerButtonRef,
|
||||||
|
}: hamburgerMenuState) => {
|
||||||
const [mouseOverMenu, setMouseOverMenu] = useState(false);
|
const [mouseOverMenu, setMouseOverMenu] = useState(false);
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | undefined>();
|
const timeoutRef = useRef<NodeJS.Timeout | undefined>();
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleMouseDownOutsideMenu = (event: MouseEvent) => {
|
||||||
|
if (
|
||||||
|
menuVisible &&
|
||||||
|
menuRef.current &&
|
||||||
|
!menuRef.current.contains(event.target as Node) &&
|
||||||
|
hamburgerButtonRef.current &&
|
||||||
|
!hamburgerButtonRef.current.contains(event.target as Node)
|
||||||
|
) {
|
||||||
|
setMenuVisible(false);
|
||||||
|
setMouseOverMenu(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", handleMouseDownOutsideMenu);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handleMouseDownOutsideMenu);
|
||||||
|
};
|
||||||
|
}, [menuVisible]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (menuVisible && !mouseOverMenu) {
|
if (menuVisible && !mouseOverMenu) {
|
||||||
@@ -17,7 +51,7 @@ const HamburgerMenu = ({ menuVisible, setMenuVisible }: menuState) => {
|
|||||||
} else {
|
} else {
|
||||||
clearTimeout(timeoutRef.current);
|
clearTimeout(timeoutRef.current);
|
||||||
}
|
}
|
||||||
}, [mouseOverMenu]);
|
}, [mouseOverMenu, menuVisible]);
|
||||||
|
|
||||||
const handleMouseEnterMenu = () => {
|
const handleMouseEnterMenu = () => {
|
||||||
setMouseOverMenu(true);
|
setMouseOverMenu(true);
|
||||||
@@ -38,6 +72,7 @@ const HamburgerMenu = ({ menuVisible, setMenuVisible }: menuState) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={menuRef}
|
||||||
className={`absolute top-0 -right-[173px] ${
|
className={`absolute top-0 -right-[173px] ${
|
||||||
menuVisible ? "-translate-x-full" : ""
|
menuVisible ? "-translate-x-full" : ""
|
||||||
} z-[9999] bg-teal-600 flex md:hidden dark:bg-gray-600 transition-transform duration-500 ease-linear`}
|
} z-[9999] bg-teal-600 flex md:hidden dark:bg-gray-600 transition-transform duration-500 ease-linear`}
|
||||||
|
|||||||
Reference in New Issue
Block a user