From d03b061c1e9d9eecce90609deb7f79e88576417f Mon Sep 17 00:00:00 2001 From: gbanyan Date: Fri, 21 Nov 2025 01:15:28 +0800 Subject: [PATCH] Keep dropdown nav open while hovering --- components/nav-menu.tsx | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/components/nav-menu.tsx b/components/nav-menu.tsx index 6133dd1..c1841f3 100644 --- a/components/nav-menu.tsx +++ b/components/nav-menu.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useState, FocusEvent } from 'react'; import { FiMenu, FiX, @@ -60,9 +60,15 @@ interface NavMenuProps { export function NavMenu({ items }: NavMenuProps) { const [open, setOpen] = useState(false); + const [activeDropdown, setActiveDropdown] = useState(null); const toggle = () => setOpen((val) => !val); const close = () => setOpen(false); + const handleBlur = (event: FocusEvent) => { + if (!event.currentTarget.contains(event.relatedTarget as Node)) { + setActiveDropdown(null); + } + }; const renderChild = (item: NavLinkItem) => { const Icon = ICON_MAP[item.iconKey] ?? FiFile; @@ -94,14 +100,23 @@ export function NavMenu({ items }: NavMenuProps) { className={`${open ? 'flex' : 'hidden'} flex-col gap-2 sm:flex sm:flex-row sm:items-center sm:gap-3`} > {items.map((item) => { - const Icon = ICON_MAP[item.iconKey] ?? FiFile; - if (item.children && item.children.length > 0) { + const Icon = ICON_MAP[item.iconKey] ?? FiFile; + const isOpen = activeDropdown === item.key; return ( -
+
setActiveDropdown(item.key)} + onMouseLeave={() => setActiveDropdown(null)} + onFocus={() => setActiveDropdown(item.key)} + onBlur={handleBlur} + > {/* Desktop dropdown */} -
+