How to toggle class when click outside element with Javascript? - javascript

I'm using the free example navbar on tailwindui. I wrote some javascript to be able to toggle the menu on mobile and toggle the profile pic tooltip. However the profile pic tooltip doesn't close on clicks outside it.
My current javascript code only toggles the profile pic tooltip on and off when it's clicked. It doesn't hide the tooltip when outside it is clicked.
I tried using a click event listener and toggle the tooltip off when the event listener fired but that didn't work.
Using Javascript, how would you hide the profile pic tooltip on outside clicks?
document.getElementById('togglemebutton').onclick = function () {
document.getElementById("resultnav").classList.toggle("hidden");
}
//document.getElementById('togglemebutton').onclick = function () {
// document.getElementById("toggleme").classList.toggle("hidden");
//}
document.getElementById('toggleprofile').onclick = function () {
document.getElementById("resultprofile").classList.toggle("hidden");
}
<link href="https://unpkg.com/tailwindcss#^1.0/dist/tailwind.min.css" rel="stylesheet">
<nav class="bg-gray-800">
<div class="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
<div class="relative flex items-center justify-between h-16">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<!-- Mobile menu button-->
<button id="togglemebutton" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:bg-gray-700 focus:text-white transition duration-150 ease-in-out" aria-label="Main menu" aria-expanded="false">
<!-- Icon when menu is closed. -->
<!-- Menu open: "hidden", Menu closed: "block" -->
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<!-- Icon when menu is open. -->
<!-- Menu open: "block", Menu closed: "hidden" -->
<svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
<div class="flex-shrink-0">
<img class="block lg:hidden h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-on-dark.svg" alt="Workflow logo">
<img class="hidden lg:block h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-logo-on-dark.svg" alt="Workflow logo">
</div>
<div class="hidden sm:block sm:ml-6">
<div class="flex">
Dashboard
Team
Projects
Calendar
</div>
</div>
</div>
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
<button class="p-1 border-2 border-transparent text-gray-400 rounded-full hover:text-white focus:outline-none focus:text-white focus:bg-gray-700 transition duration-150 ease-in-out" aria-label="Notifications">
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<!-- Profile dropdown -->
<div class="ml-3 relative">
<div>
<button id="toggleprofile" class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-white transition duration-150 ease-in-out" id="user-menu" aria-label="User menu" aria-haspopup="true">
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
</button>
</div>
<!--
Profile dropdown panel, show/hide based on dropdown state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<div id="resultprofile" class="hidden z-40 origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg">
<div class="py-1 rounded-md bg-white shadow-xs" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
Your Profile
Settings
Sign out
</div>
</div>
</div>
</div>
</div>
</div>
<!--
Mobile menu, toggle classes based on menu state.
Menu open: "block", Menu closed: "hidden"
-->
<div id="resultnav" class="hidden sm:hidden">
<div class="px-2 pt-2 pb-3">
Dashboard
Team
Projects
Calendar
</div>
</div>
</nav>

I tried using a click event listener and toggle the tooltip off when
the event listener fired but that didn't work.
This is exactly what you need, event listener on all elements:
const toggleprofile = document.getElementById("toggleprofile");
const resultprofile = document.getElementById("resultprofile");
[...document.querySelectorAll('body')].forEach(el => {
//in order to get all elements
el.addEventListener('click', event => {
//add click event to all of them
if (event.target.parentElement.id !== "toggleprofile") {
// if element is not profile picture - parent button has id, easier to target
console.clear();
console.log(event.target.parentElement.id)
resultprofile.classList.add("hidden")
//add class
}else{
resultprofile.classList.toggle("hidden")}
//if it is profile, toggle class
})
})
Keep in mind now you have click event listener on all elements on page, so if you need something else with other element, just expand this.
Working example:
document.getElementById('togglemebutton').onclick = function() {
document.getElementById("resultnav").classList.toggle("hidden");
}
//document.getElementById('togglemebutton').onclick = function () {
// document.getElementById("toggleme").classList.toggle("hidden");
//}
const toggleprofile = document.getElementById("toggleprofile");
const resultprofile = document.getElementById("resultprofile");
[...document.querySelectorAll('body')].forEach(el => {
el.addEventListener('click', event => {
if (event.target.parentElement.id !== "toggleprofile") {
console.clear();
console.log(event.target.parentElement.id)
resultprofile.classList.add("hidden")
}else{
resultprofile.classList.toggle("hidden")}
})
})
body{
height:300px}
<link href="https://unpkg.com/tailwindcss#^1.0/dist/tailwind.min.css" rel="stylesheet">
<nav class="bg-gray-800">
<div class="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
<div class="relative flex items-center justify-between h-16">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<!-- Mobile menu button-->
<button id="togglemebutton" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:bg-gray-700 focus:text-white transition duration-150 ease-in-out" aria-label="Main menu"
aria-expanded="false">
<!-- Icon when menu is closed. -->
<!-- Menu open: "hidden", Menu closed: "block" -->
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<!-- Icon when menu is open. -->
<!-- Menu open: "block", Menu closed: "hidden" -->
<svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
<div class="flex-shrink-0">
<img class="block lg:hidden h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-on-dark.svg" alt="Workflow logo">
<img class="hidden lg:block h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-logo-on-dark.svg" alt="Workflow logo">
</div>
<div class="hidden sm:block sm:ml-6">
<div class="flex">
Dashboard
Team
Projects
Calendar
</div>
</div>
</div>
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
<button class="p-1 border-2 border-transparent text-gray-400 rounded-full hover:text-white focus:outline-none focus:text-white focus:bg-gray-700 transition duration-150 ease-in-out" aria-label="Notifications">
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<!-- Profile dropdown -->
<div class="ml-3 relative">
<div>
<button id="toggleprofile" class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-white transition duration-150 ease-in-out" id="user-menu" aria-label="User menu" aria-haspopup="true">
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
</button>
</div>
<!--
Profile dropdown panel, show/hide based on dropdown state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<div id="resultprofile" class="hidden z-40 origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg">
<div class="py-1 rounded-md bg-white shadow-xs" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
Your Profile
Settings
Sign out
</div>
</div>
</div>
</div>
</div>
</div>
<!--
Mobile menu, toggle classes based on menu state.
Menu open: "block", Menu closed: "hidden"
-->
<div id="resultnav" class="hidden sm:hidden">
<div class="px-2 pt-2 pb-3">
Dashboard
Team
Projects
Calendar
</div>
</div>
</nav>
Or as mentioned in comment:
window.addEventListener('click', event => {
if (event.target.parentElement.id !== "toggleprofile") {
console.clear();
console.log(event.target.parentElement.id);
resultprofile.classList.add("hidden")
} else {
resultprofile.classList.toggle("hidden")
}
})

I'll try to improve this others are requested to do the same

Related

Unable to use Javascript functionality in tailwind css with vite in reactjs

I am working on a react project using vite and for css I am using tailwind css. From the component section of tailwind css website I have copied template, and I am unable to get responsive functionality and show/hide menu on click
below is my header code
<nav class="bg-gray-800">
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div class="relative flex h-16 items-center justify-between">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<button type="button" class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" aria-controls="mobile-menu" aria-expanded="false">
<span class="sr-only">Open main menu</span>
<svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
<svg class="hidden h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<div class="flex flex-shrink-0 items-center">
<img class="block h-8 w-auto lg:hidden" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company" />
<img class="hidden h-8 w-auto lg:block" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company"/>
</div>
<div class="hidden sm:ml-6 sm:block">
<div class="flex space-x-4">
Dashboard
Team
Projects
Calendar
</div>
</div>
</div>
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
<button type="button" class="rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
<span class="sr-only">View notifications</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
</svg>
</button>
<div class="relative ml-3">
<div>
<button type="button" class="flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
<span class="sr-only">Open user menu</span>
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
</button>
</div>
<div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
Your Profile
Settings
Sign out
</div>
</div>
</div>
</div>
</div>
<div class="sm:hidden" id="mobile-menu">
<div class="space-y-1 px-2 pt-2 pb-3">
Dashboard
Team
Projects
Calendar
</div>
</div>
</nav>
everything is working fine but by running the above code I am getting only ui and not getting click function on menu bars or other
see the image below
[
let menuMovilButton = document.getElementById('menu-movil-button');
let userMenuButton = document.getElementById('user-menu-button');
let userMenu = document.getElementById('user-menu');
let menuMovil = document.getElementById('menu-movil');
menuMovilButton.addEventListener('click', () =>{
menuMovil.classList.toggle('hidden');
});
userMenuButton.addEventListener('click', () =>{
userMenu.classList.toggle('hidden');
});`

How do i get this container to align right?

I want to get these elements to move over to the right. The name is in the correct spot I just want the 4 elements to the right to move over with some slight padding on the outside. Thanks.
here is the code snippet:
<!-- Header/top nav bar -->
<header class="py-6">
<nav class="container flex justify-between items-center mx-auto px-8 md:px-14 lg:px-10 w-full">
<div class="me-auto text-lg font-bold"> Jordan DeGiacomo </div>
<button class="hidden" id="hamburger">
<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 17.5H0.25V14.6667H13V17.5ZM25.75 10.4167H0.25V7.58333H25.75V10.4167ZM25.75 3.33333H13V0.5H25.75V3.33333Z" fill="white"/></svg>
</button>
<ul class="hidden md:flex space-x-12 items-center" id="nav-ul">
<li>Home</li>
<li>Languages</li>
<li>Projects</li>
<li><button class="px-6 py-2 bg-theme font-bold"> Hire Me </button></li>
</ul>
<button class="px-4 py-1 font-bold bg-theme md:hidden"> Hire Me </button>
<!-- <div class="md:hidden">
<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13 17.5H0.25V14.6667H13V17.5ZM25.75 10.4167H0.25V7.58333H25.75V10.4167ZM25.75 3.33333H13V0.5H25.75V3.33333Z" fill="white"/></svg>
</div> -->
</nav>
<!-- side nav bar -->
<div class="container mt-16 flex justify-between items-center mx-auto px-8 md:px-14 lg:px-10 w-full">
<div class="flex flex-wrap md:flex-nowrap">
<nav class="inline-block lg:mr-24 lg:w-4 fixed left-percentage hidden xl:block">
<div class="absolute left-50 transform -translate-x-1/2 space-y-6 mt-36">
<a href="#" class="nav-dot selected-circle block w-7 h-7 rounded-full border-4 border-nav bg-body">
<span class="bg-black px-2 py-1 rounded-md ml-10 opacity-0">Home</span>
</a>
<a href="#languages" class="nav-dot block w-7 h-7 rounded-full border-4 border-nav bg-body">
<span class="bg-black px-2 py-1 rounded-md ml-10 opacity-0">Languaages</span>
</a>
<a href="#projects" class="nav-dot block w-7 h-7 rounded-full border-4 border-nav bg-body">
<span class="bg-black px-2 py-1 rounded-md ml-10 opacity-0">Projects</span>
</a>
<a href="#hire" class="nav-dot block w-7 h-7 rounded-full border-4 border-nav bg-body">
<span class="bg-black px-2 py-1 rounded-md ml-10 opacity-0">Hire</span>
</a>
</nav>
Here is a screenshot of the nav bar
Since you already have the justify-between just wrap the stuff you want moved to the right inside a div as follows:
<nav class="container flex justify-between items-center mx-auto px-8 md:px-14 lg:px-10 w-full">
<!-- left side div -->
<div class="me-auto text-lg font-bold"> Jordan DeGiacomo </div>
<!-- right side div -->
<div>
<button class="hidden" id="hamburger">
<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M13 17.5H0.25V14.6667H13V17.5ZM25.75 10.4167H0.25V7.58333H25.75V10.4167ZM25.75 3.33333H13V0.5H25.75V3.33333Z"
fill="white" />
</svg>
</button>
<ul class="hidden md:flex space-x-12 items-center" id="nav-ul">
<li>Home</li>
<li>Languages</li>
<li>Projects</li>
<li><button class="px-6 py-2 bg-theme font-bold"> Hire Me </button></li>
</ul>
<button class="px-4 py-1 font-bold bg-theme md:hidden"> Hire Me </button>
</div>
</nav>
Try using CSS to style the element -
/* for float alignment */
element {
float: right;
}
Or for absolute positioning
element {
position: absolute;
right: 0;
}

Responsive navbar in tailwind, replace hover event with tap on tablet using javascript

I have created a responsive navbar for a website using tailwind CSS. It is basically a CSS menu. With a desktop browser, when hovering over the Company menu item, the sub menu items are displayed in a drop down menu. This does not work on a tablet because there is no hover event. I was thinking about adding this feature using javascript. How to I go about adding a click/tap event to the Company menu item for touch devices so that the Company menu is displayed by a tap on a tablet device? The codepen demo of the current navbar is here.
const toggleNav = document.querySelector(".nav-list");
const toggleBtn = document.querySelector(".btn-toggle");
const overlay = document.querySelector(".overlay");
const body = document.querySelector("body");
toggleBtn.addEventListener("click", () => {
toggleNav.classList.toggle("active-nav");
body.classList.toggle("no-scroll");
overlay.classList.toggle("active");
toggleBtn.classList.toggle("active-toggle");
});
overlay.addEventListener("click", () => {
toggleNav.classList.remove("active-nav");
body.classList.remove("no-scroll");
overlay.classList.remove("active");
toggleBtn.classList.remove("active-toggle");
});
// [Dropdown]
const dropdownTrigger = document.querySelector(".has-dropdown");
const dropdownMenu = document.querySelector(".sub-menu");
dropdownTrigger.addEventListener("click", (event) => {
event.preventDefault();
dropdownTrigger.querySelector("svg").classList.toggle("active");
dropdownMenu.classList.toggle("active-sub");
});
<body>
<!-- [Backgoround layer] -->
<span class="overlay"></span>
<!-- [Navbar] -->
<nav class="relative z-50 bg-dark">
<div class="mx-auto flex h-20 w-full max-w-[92%] items-center justify-between py-4 sm:h-28 sm:py-6">
<div class="">
<a href="#" class="flex items-center gap-3 font-primary text-3xl font-medium sm:text-5xl lg:text-[55px]">
To the Moon
</a>
</div>
<div class="nav-list lg:mt-5">
<ul class="!xl:justify-end relative flex flex-col space-y-2 md:flex-row md:items-center md:justify-center md:space-y-0 md:py-0">
<li class="px-4 py-2 md:py-4 lg:px-8">
<a href="#" class="relative font-primary text-base text-light transition-all duration-200 md:text-xl">
Home
<span class="inline-block; absolute -bottom-1 left-0 right-0 h-1 w-full bg-primary sm:h-1"></span>
</a>
</li>
<li class="px-4 py-2 md:py-4 lg:px-8">
Services
</li>
<li class="group relative px-4 py-2 transition-all duration-300 md:py-4 md:hover:bg-primary md:hover:bg-opacity-60 lg:px-8">
<a href="#" class="has-dropdown flex items-center gap-3 font-primary text-base leading-6 text-light transition-all duration-200 md:text-xl">
Company
<svg class="sub-caret h-2.5 w-2.5 transform fill-current transition-all duration-200 sm:h-4 sm:w-4 md:group-hover:rotate-180" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background: new 0 0 386.257 386.257" viewBox="0 0 386.257 386.257">
<path d="m0 96.879 193.129 192.5 193.128-192.5z" />
</svg>
</a>
<ul class="sub-menu pl-3 md:pl-0">
<li class="px-4 pb-2 pt-4 md:py-3 lg:px-8">
<a href="#" class="border-b-transparent font-primary text-base text-light transition-all duration-200 hover:border-b-light md:border-b-2 md:text-xl">
<span class="md:hidden">-</span>
Portfolio
</a>
</li>
<li class="px-4 pt-2 md:py-3 lg:px-8">
<a href="#" class="border-b-transparent font-primary text-base text-light transition-all duration-200 hover:border-b-light md:border-b-2 md:text-xl">
<span class="md:hidden">-</span>
About
</a>
</li>
</ul>
</li>
<li class="px-4 pb-6 pt-2 pr-0 md:py-4 lg:pl-8">
Contact
</li>
</ul>
</div>
<button class="btn-toggle md:hidden">
<svg class="icon-bars h-6 w-6 fill-current" viewBox="0 0 55 50" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule: evenodd; clip-rule: evenodd; stroke-linejoin: round; stroke-miterlimit: 1.5">
<path d="M0,25l55,0" style="fill: none; stroke: #fff; stroke-width: 8.33px" />
<path d="M0,46l55,0" style="fill: none; stroke: #fff; stroke-width: 8.33px" />
<path d="M-0,4l55,0" style="fill: none; stroke: #fff; stroke-width: 8.33px" />
</svg>
<svg class="icon-cross h-7 w-7 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M312.1 375c9.369 9.369 9.369 24.57 0 33.94s-24.57 9.369-33.94 0L160 289.9l-119 119c-9.369 9.369-24.57 9.369-33.94 0s-9.369-24.57 0-33.94L126.1 256L7.027 136.1c-9.369-9.369-9.369-24.57 0-33.94s24.57-9.369 33.94 0L160 222.1l119-119c9.369-9.369 24.57-9.369 33.94 0s9.369 24.57 0 33.94L193.9 256L312.1 375z" /></svg>
</button>
</div>
</nav>
<!-- [Header] -->
<header class="relative flex h-[60vh] justify-center bg-header bg-cover bg-center bg-no-repeat sm:h-[600px] sm:min-h-[calc(100vh-112px)]">
</header>
<!-- [JAVASCRIPT] ------------ -->
<script src="assets/js/script.js"></script>
</body>

Updating tailwindCSS class attributes on button click

I'm working on a project that uses pre-made TailwindUI component code. If you refer to this gif, you can see that the code on the site is responsive to mobile design and the hamburger menu toggles on button click.
However, the code given for this does not include the necessary JS, so the toggling of the hamburger menu does not work.
I am trying to fix this, this is what i've done so far:
I've wrapped the flyout menu code in a div and gave it an id 'mobile-menu' and a state of 'hidden'. Inside this menu is the X button, which i gave an id 'menu-toggle' since i want this button and the hamburger button to toggle the flyout menu. Below is not the whole code but just the relevant parts
<div class="absolute z-30 top-0 inset-x-0 p-2 transition transform origin-top-right md:hidden">
<div class="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
<div class="pt-5 pb-6 px-5">
<div class="flex items-center justify-between">
<div>
<img class="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg" alt="Workflow">
</div>
<div class="-mr-2">
<button id="menu-toggle" onclick="" type="button" class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<span class="sr-only">Close menu</span>
<!-- Heroicon name: outline/x -->
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
Outside of this div and elsewhere in the code is the hamburger menu button, which i also gave an id 'menu-toggle'
<div class="-mr-2 -my-2 md:hidden">
<button id="menu-toggle" type="button" class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" aria-expanded="false">
<span class="sr-only">Open menu</span>
<!-- Heroicon name: outline/menu -->
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
Finally i've added a script tag to the whole .html file (the file does not contain HTML boilerplate because it is a 'partial' in a Hugo project, similar to a component in React) and that looks like this:
<script>
let menuButton = document.getElementById('menu-toggle');
menuButton.addEventListener('click', function () {
let flyout = document.getElementById('mobile-menu').classList
flyout.toggle('hidden')
flyout.toggle('block')
})
</script>
but this JS doesn't work at all. Looking for insight on how to pull this off properly. Thank you!!
I have written a little code to do the work around. Perhaps it is not the effect you want for your final result, but it is a start. The aproach here is that you can't apply a toggle function for the same button and the same element toggling diferent class, without use some css at least. Besides, there are so many code errors to explain one by one. Here I let you the code that allows to you open with burger button and close with cross button.
If you need to toggle with the same button just use the menuButtonBurger event and add flyout.classlist.toggle('visible), and remove menuButtonCross. Combined with the css I wrote you this must work.
let menuButtonBurger = document.getElementById('menu-toggle-burger');
let menuButtonCross = document.getElementById('menu-toggle-cross');
menuButtonBurger.addEventListener('click', function () {
let flyout = document.getElementById('mobile-menu');
flyout.classList.add('visible');
});
menuButtonCross.addEventListener('click', function () {
let flyout = document.getElementById('mobile-menu');
flyout.classList.remove('visible');
});
#mobile-menu {
display: none;
}
#mobile-menu.visible {
display: block;
}
<div class="mr-2 my-2 d-md-hidden">
<button id="menu-toggle-burger" type="button" class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" aria-expanded="false">
<span class="sr-only">Open menu</span>
<!-- Heroicon name: outline/menu -->
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div id="mobile-menu"class="absolute z-30 top-0 inset-x-0 p-2 transition transform origin-top-right d-hidden">
<div class="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
<div class="pt-5 pb-6 px-5">
<div class="flex items-center justify-between">
<div>
<img class="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg" alt="Workflow">
</div>
<div class="-mr-2">
<button id="menu-toggle-cross" onclick="" type="button" class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<span class="sr-only">Close menu</span>
<!-- Heroicon name: outline/x -->
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
</div>
</div>

Mega Menu with Alpinejs - Hover is Buggy

I'm trying to create a Mega Menu that triggers on Hover, using Tailwind CSS and Alpinejs. I kind of having it working, but it's really buggy.
I've tried adding x-on:mouseleave to different elements but it will either flicker constantly or only disappear when moving away from certain areas. So it will either disappear when moving below the menu and not when moving above and vice versa.
Any insight would be much appreciated!
https://codepen.io/kennyk3/pen/yLJmzYJ
<div class="bg-blue-800 hidden md:block">
<div class="max-w-screen-xl mx-auto">
<nav class="flex items-center justify-between flex-wrap">
<div class="w-full block flex-grow md:flex md:items-center md:w-auto">
<div class="font-bold md:flex-grow">
<ul class="flex justify-between">
<li>
LINK
</li>
<li>
LINK
</li>
<li>
LINK
</li>
<li>
LINK
</li>
<li class="group hover:bg-white">
<div x-data="{ resourcesMenu: false }" x-on:mouseover="resourcesMenu = !resourcesMenu" x-on:mouseleave="resourcesMenu = !resourcesMenu">
MEGA MENU
<div x-show="resourcesMenu" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 -translate-y-1" x-transition:enter-end="opacity-100 translate-y-0" x-transition:leave="transition ease-in duration-75" x-transition:leave-start="opacity-100 translate-y-0" x-transition:leave-end="opacity-0 -translate-y-1" class="absolute inset-x-0 transform shadow-lg -mt-1 z-10">
<div class="bg-white">
<div class="max-w-7xl mx-auto grid gap-y-6 px-4 py-6 sm:grid-cols-2 sm:gap-8 sm:px-6 sm:py-8 lg:grid-cols-4 lg:px-8 lg:py-12 xl:py-16">
<a href="#" class="-m-3 p-3 flex flex-col justify-between rounded-lg hover:bg-gray-50 transition ease-in-out duration-150">
<div class="flex md:h-full lg:flex-col">
<div class="flex-shrink-0">
<div class="inline-flex items-center justify-center h-10 w-10 rounded-md bg-indigo-500 text-white sm:h-12 sm:w-12">
<svg class="h-6 w-6" x-description="Heroicon name: chart-bar" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
</svg>
</div>
</div>
<div class="ml-4 md:flex-1 md:flex md:flex-col md:justify-between lg:ml-0 lg:mt-4">
<div>
<p class="text-base font-medium text-gray-900">
Analytics
</p>
<p class="mt-1 text-sm text-gray-500">
Get a better understanding of where your traffic is coming from.
</p>
</div>
<p class="mt-2 text-sm font-medium text-indigo-600 lg:mt-4">Learn more <span aria-hidden="true">→</span></p>
</div>
</div>
</a>
<a href="#" class="-m-3 p-3 flex flex-col justify-between rounded-lg hover:bg-gray-50 transition ease-in-out duration-150">
<div class="flex md:h-full lg:flex-col">
<div class="flex-shrink-0">
<div class="inline-flex items-center justify-center h-10 w-10 rounded-md bg-indigo-500 text-white sm:h-12 sm:w-12">
<svg class="h-6 w-6" x-description="Heroicon name: cursor-click" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"></path>
</svg>
</div>
</div>
<div class="ml-4 md:flex-1 md:flex md:flex-col md:justify-between lg:ml-0 lg:mt-4">
<div>
<p class="text-base font-medium text-gray-900">
Engagement
</p>
<p class="mt-1 text-sm text-gray-500">
Speak directly to your customers in a more meaningful way.
</p>
</div>
<p class="mt-2 text-sm font-medium text-indigo-600 lg:mt-4">Learn more <span aria-hidden="true">→</span></p>
</div>
</div>
</a>
<a href="#" class="-m-3 p-3 flex flex-col justify-between rounded-lg hover:bg-gray-50 transition ease-in-out duration-150">
<div class="flex md:h-full lg:flex-col">
<div class="flex-shrink-0">
<div class="inline-flex items-center justify-center h-10 w-10 rounded-md bg-indigo-500 text-white sm:h-12 sm:w-12">
<svg class="h-6 w-6" x-description="Heroicon name: shield-check" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
</svg>
</div>
</div>
<div class="ml-4 md:flex-1 md:flex md:flex-col md:justify-between lg:ml-0 lg:mt-4">
<div>
<p class="text-base font-medium text-gray-900">
Security
</p>
<p class="mt-1 text-sm text-gray-500">
Your customers' data will be safe and secure.
</p>
</div>
<p class="mt-2 text-sm font-medium text-indigo-600 lg:mt-4">Learn more <span aria-hidden="true">→</span></p>
</div>
</div>
</a>
<a href="#" class="-m-3 p-3 flex flex-col justify-between rounded-lg hover:bg-gray-50 transition ease-in-out duration-150">
<div class="flex md:h-full lg:flex-col">
<div class="flex-shrink-0">
<div class="inline-flex items-center justify-center h-10 w-10 rounded-md bg-indigo-500 text-white sm:h-12 sm:w-12">
<svg class="h-6 w-6" x-description="Heroicon name: view-grid" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"></path>
</svg>
</div>
</div>
<div class="ml-4 md:flex-1 md:flex md:flex-col md:justify-between lg:ml-0 lg:mt-4">
<div>
<p class="text-base font-medium text-gray-900">
Integrations
</p>
<p class="mt-1 text-sm text-gray-500">
Connect with third-party tools that you're already using.
</p>
</div>
<p class="mt-2 text-sm font-medium text-indigo-600 lg:mt-4">Learn more <span aria-hidden="true">→</span></p>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</li>
<li>
LINK
</li>
<li class="md:hidden lg:inline-block">
LINK
</li>
<li class="md:hidden">
LINK
</li>
<li>
LINK
</li>
<li class="md:hidden lg:inline-block">
LINK
</li>
</ul>
</div>
</div>
</nav>
</div>
</div>
Change your trigger event from mouseover to mouseenter. The problem you're having is mouseover is triggered for the parent and its child elements.
See: https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseover_event
The mouseover event is fired at an Element when a pointing device (such as a mouse or trackpad) is used to move the cursor onto the element or one of its child elements.
Wheres mouseenter will be triggered once.

Categories

Resources