I am building a next.js/tailwind website and I am trying to create individual horizontal sub-navigation menus that appear across the entire screen directly below the entire navbar. Each submenu should appear on hover of its respective nav item and stay open while the mouse is on either the nav item or the submenu itself. I don't want the traditional drop down look, I want each submenu to look like an entirely new navbar with submenu items.
I am quite new to react/next.js/tailwind and so I am having a lot of trouble with the debugging/troubleshooting. The issues I'm having are that either
- The submenu disappears too early, when the mouse leaves the nav item (so the user cannot reach the submenu items). This occurs when I try to use group-hover:block to make the submenu appear (which you can see in the first submenu shown in my code below) or when I put the onMouseLeave in the parent div element's opening tag, where the onMouseEnter is listed.
or
- Once a submenu is opened, it will not go away unless a different submenu replaces it (which happens in the second nav item listed in my code). The onMouseLeave never seems to trigger.
CoPilot and ChatGPT keep suggesting that the issues must be one of the following, but I've been going around in circles trying to troubleshoot with no success:
- CSS Styles: Check if there are any CSS styles applied to the "about" submenu that might be causing the issue. For example, if there's a CSS property that's creating an invisible gap or overlap, the onMouseLeave event could be triggered unexpectedly.
- HTML Structure: Make sure that the HTML structure of the "about" submenu is correct and consistent with the other submenus. If there's an issue with the HTML structure, it could cause unexpected behavior.
- JavaScript State: Check if there's any issue with the activeSubmenu state. If the state is not updated correctly, it could cause the onMouseLeave event to not work as expected.
- Browser Compatibility: Check if the issue occurs in all browsers or only in specific ones. Some features might not be fully supported in all browsers.
- The issue you're experiencing is a common one when trying to create a hoverable dropdown menu. The problem is that when the mouse leaves the parent element (the nav item), the dropdown (submenu) disappears, even if the mouse is moving into the dropdown. One solution is to use a timeout to delay the disappearance of the dropdown. This gives the user a small window of time to move the mouse from the nav item to the dropdown without the dropdown disappearing. (I don't want to use a timeout!)
Here is all of the code that might be relevant for reference:
Nav component:
"use client";
import Link from 'next/link';
import { useState, useEffect } from 'react';
const Nav = () => {
const [showSubmenu, setShowSubmenu] = useState(false);
const [activeSubmenu, setActiveSubmenu] = useState(null);
return (
<nav id="nav" className="w-full break-words">
<div className="relative">
<div id="lowerNav" className="pb-7 pt-[30px] self-stretch flex justify-around items-center bg-blue-default w-full h-[85px] px-[435px] justify-center font-gotham-bold text-[22px] text-white ">
<div className="group">
<button>
<span>About</span>
</button>
{/* <Link href="">About</Link> */}
<div className="w-full h-[3px] bg-transparent group-hover:bg-white transition-all duration-500 ease-in-out" />
<div className="absolute z-10 hidden top-full left-0 w-full group-hover:block">
<div id="aboutSubNav" className="h-[143px] px-[320px] bg-white flex items-center font-gotham-medium text-xl text-black">
<div className="flex-grow flex justify-between items-center transition-opacity duration-500 ease-in-out">
<Link href="">1</Link>
<Link href="">2</Link>
<Link href="">3</Link>
<Link href="">4</Link>
</div>
</div>
</div>
</div>
<div className="group"
onMouseEnter={() => setActiveSubmenu('admissions')}>
<Link href="">Admissions</Link>
<div className="w-full h-[3px] bg-transparent group-hover:bg-white transition-all duration-500 ease-in-out" />
{activeSubmenu === 'admissions' && (
<div className="absolute top-full left-0 w-full"
onMouseLeave={() => setActiveSubmenu(null)}>
<div id="admissionsSubNav" className="w-full min-h-[284px] px-[320px] pt-[65px] pb-[75px] bg-white justify-center items-center inline-flex font-gotham-medium text-xl text-black ">
<div className="grow shrink basis-0 self-stretch justify-between items-start inline-flex">
<div className="flex-grow flex flex-col justify-start items-start gap-6 inline-flex">
<Link href="">Tuition & Fees</Link>
</div>
<div className="flex-grow flex flex-col justify-start items-start gap-6 inline-flex">
<Link href="">Financial Aid</Link>
<Link href="" className="text-lg font-gotham-book-regular">Graduate Assistants & Work Studies</Link>
</div>
<div className="flex-grow flex flex-col justify-start items-start gap-6 inline-flex">
<Link href="">How to Apply</Link>
<Link href="" className="text-lg font-gotham-book-regular">International Students</Link>
</div>
<div className="flex w-[188.83px] h-[50.94px] pl-[25px] pr-[24.83px] pt-[18px] pb-[18.94px] bg-blue-secondary rounded-[3px] border-10 border-blue-secondary inline-flex justify-center items-start ">
<div className="w-[139px] h-[15px] text-center text-white text-[13px] justify-center leading-[14.95px] tracking-tight">Apply Now</div>
</div>
</div>
</div>
</div>
)}
</div>
</div>
</div>
</nav>
)
}
export default Nav
layout.jsx
import '@styles/globals.css';
import '@styles/fonts.css';
import localFont from 'next/font/local'
import Nav from '@components/Nav';
import Provider from '@components/Provider';
import LowerNav from '@components/LowerNav';
export const metadata = {
title: 'site',
description: 'Official Website'
}
const RootLayout = ({ children }) => {
return (
<html lang='en' >
<body>
<div className='main'></div>
<main className='app bg-blue-secondary'>
<Nav />
<LowerNav />
{ children }
</main>
</body>
</html>
)
}
export default RootLayout;
page.jsx
import Image from 'next/image'
import touroLogo from '../public/assets/images/touro_gst_logo.png'
// import touroBuildingVideo from '../public/assets/videos/touro_nyc_night_view.mp4'
const Home = () => {
return (
<section className="relative flex flex-row w-full h-screen">
</section >
)
}
export default Home
tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
darkMode: "class",
important: true,
theme: {
screens: {
xs: "540px",
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px",
lg_992: "992px",
},
container: {
center: true,
// padding: {
// DEFAULT: "12px",
// sm: "1rem",
// lg: "45px",
// xl: "5rem",
// "2xl": "13rem",
// },
},
extend: {
fontSize: {
'sm': '14px',
},
fontWeight: {
'bold': 700,
},
textColor: {
'white': '#FFFFFF',
},
colors: {
colors: {
'blue-default': '#012F87',
'blue-secondary': '#103CCC',
'silver': '#F2F2F2'
},
},
},
},
theme: {
backgroundColor: theme => ({
...theme('colors'),
'blue-default': '#012F87',
'blue-secondary': '#103CCC',
'silver': '#F2F2F2',
})
},
variants: {
display: ['responsive', 'group-hover', 'group-focus'],
},
plugins: [require("tailwindcss"), require("autoprefixer")],
};
globals.css:
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
Any fixes and/or points in the right direction would be appreciated. TIA!