11"use client"
22import Link from "next/link"
33import Image from "next/image"
4- import { useEffect , useState } from "react"
4+ import { useCallback , useEffect , useRef , useState } from "react"
55import { HeaderMenu } from "./header-menu"
66import { AnimatePresence } from "motion/react"
77import { merge } from "@halvaradop/ui-core"
@@ -11,11 +11,18 @@ import arrow from "@/assets/arrow.svg"
1111
1212export const Header = ( ) => {
1313 const [ isOpen , setIsOpen ] = useState ( false )
14+ const menuRef = useRef < HTMLDivElement > ( null )
1415
1516 const handleToggleMenu = ( ) => {
1617 setIsOpen ( ! isOpen )
1718 }
1819
20+ const handleMenuLinkClick = useCallback ( ( ) => {
21+ if ( window . innerWidth < 900 ) {
22+ setIsOpen ( false )
23+ }
24+ } , [ ] )
25+
1926 useEffect ( ( ) => {
2027 const matchScreen = matchMedia ( "(min-width: 900px)" )
2128
@@ -28,27 +35,40 @@ export const Header = () => {
2835 return ( ) => matchScreen . removeEventListener ( "change" , handleSetMatchMedia )
2936 } , [ ] )
3037
38+ useEffect ( ( ) => {
39+ if ( ! isOpen ) return
40+ const handleClickOutside = ( event : MouseEvent ) => {
41+ if ( window . innerWidth < 900 && menuRef . current && ! menuRef . current . contains ( event . target as Node ) ) {
42+ setIsOpen ( false )
43+ }
44+ }
45+ document . addEventListener ( "mousedown" , handleClickOutside )
46+ return ( ) => document . removeEventListener ( "mousedown" , handleClickOutside )
47+ } , [ isOpen ] )
48+
3149 return (
3250 < header
33- className = { merge ( "flex items-center border-b border-solid border-border" , isOpen ? "open" : " ") }
51+ className = { merge ( "flex items-center border-b border-solid border-border" , isOpen && "open" ) }
3452 id = "halvaradop-tailwindcss-utilities"
3553 >
3654 < nav className = "flex-100 h-16 ml-10 px-4 border-x border-solid border-border sm:px-6 md:px-8 base:ml-16 base:px-10 base:flex base:items-center base:justify-between base:relative" >
37- < div className = "w-full h-full flex items-center justify-between relative z-20 base:w-fit" >
55+ < div className = "w-full h-full flex items-center justify-between relative base:w-fit" >
3856 < h2 className = "text-primary base:text-lg" >
3957 < Link href = "/" > @halvaradop/tailwindcss</ Link >
4058 </ h2 >
4159 </ div >
42- < AnimatePresence mode = "wait" > { isOpen && < HeaderMenu /> } </ AnimatePresence >
60+ < div ref = { menuRef } style = { { display : "contents" } } >
61+ < AnimatePresence mode = "wait" > { isOpen && < HeaderMenu onLinkClick = { handleMenuLinkClick } /> } </ AnimatePresence >
62+ </ div >
4363 </ nav >
4464 < Button
45- className = "w-10 h-16 p-0 relative z-10 hover:bg-transparent base:hidden"
65+ className = "w-10 h-16 p-0 relative z-30 hover:bg-transparent base:hidden"
4666 variant = "ghost"
4767 onClick = { handleToggleMenu }
4868 >
4969 < Image className = "hover:cursor-pointer" src = { menu } alt = "menu icon" />
5070 </ Button >
51- < figure className = "group w-10 h-full hidden img:transition-transform img:ease-linear img:duration-300 hover:cursor-pointer base:w-16 base:flex base:items-center base:justify-center base:relative base:overflow-hidden" >
71+ < figure className = "group w-10 h-16 hidden img:transition-transform img:ease-linear img:duration-300 hover:cursor-pointer base:w-16 base:flex base:items-center base:justify-center base:relative base:overflow-hidden" >
5272 < Image
5373 className = "-rotate-127 group-hover:-translate-y-14 group-hover:translate-x-14"
5474 src = { arrow }
0 commit comments