Mega Menu with Alpinejs - Hover is Buggy - javascript

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.

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;
}

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>

Keep buttons from different parent divs active at the same time

I want to keep buttons from different parent divs active at the same time, just like:
On my project, I can't select Limit and Cross 3x at the same time, for example. When one button gets focused, the other from another parent div does not remain active.
Is there a way to do that? I'm using TailwindCSS and AlpineJS on this project.
Here's my code:
<div class="px-16 py-6 mt-2 bg-white shadow-sm">
<div>
<div class="sm:hidden">
<select aria-label="Selected tab" class="block w-full form-select">
<option selected>Spot</option>
<option>Cross 3x</option>
<option>Isolada 10x</option>
</select>
</div>
<div class="hidden sm:block md:flex md:flex-row md:justify-between">
<nav class="flex">
<button type="button" class="px-4 py-1 text-sm font-medium leading-5 text-gray-500 active:text-indigo-700 focus:no-underline hover:no-underline hover:text-gray-700 focus:outline-none focus:text-indigo-600 focus:bg-indigo-100 bg-indigo-50" autofocus aria-current="page">
Spot
</button>
<button type="button" class="px-4 py-1 text-sm font-medium leading-5 text-gray-500 active:text-indigo-700 focus:no-underline hover:no-underline hover:text-gray-700 focus:outline-none focus:text-indigo-600 focus:bg-indigo-100 bg-indigo-50">
Cross 3x
</button>
<button type="button" class="px-4 py-1 text-sm font-medium leading-5 text-gray-500 active:text-indigo-700 focus:no-underline hover:no-underline hover:text-gray-700 focus:outline-none focus:text-indigo-600 focus:bg-indigo-100 bg-indigo-50">
Isolada 10x
</button>
</nav>
<!-- Dots Vertical -->
<div class="hidden md:flex" id="nav-heading" aria-labelledby="nav-heading" x-data="{ dotsOpen: false }" :aria-expanded="dotsOpen">
<button type="button" :aria-expanded="dotsOpen" aria-controls="nav-list" #mouseenter="dotsOpen = !dotsOpen" #click.away="dotsOpen = false">
<svg class="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"></path>
</svg>
</button>
<div x-show.transition.in.duration.100ms.origin.top.left.opacity.scale.10.out.duration.100ms.origin.bottom.right.opacity.scale.10="dotsOpen" id="nav-list" class="absolute z-10 w-auto mt-8 -ml-8 origin-right rounded-md shadow-lg">
<!--
Dots dropdown panel, show/hide based on dropdown state.
-->
<div #mouseleave="dotsOpen = !dotsOpen" class="py-1 bg-white rounded-md shadow-xs" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
<button type="button" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 hover:no-underline focus:no-underline focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
<p class="flex justify-start font-medium">Regras de Trading</p>
</button>
<a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 hover:no-underline focus:no-underline focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
<p class="flex justify-start font-medium">FAQ</p>
</a>
<button type="button" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 hover:no-underline focus:no-underline focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
<p class="flex justify-start font-medium">Spot Tutorial</p>
</button>
</div>
</div>
</div>
</div>
</div>
<div>
<div class="sm:hidden">
<select aria-label="Selected tab" class="block w-full py-2 pl-3 pr-10 mt-2 text-base leading-6 transition duration-150 ease-in-out border-gray-300 form-select focus:outline-none focus:shadow-outline-blue focus:border-blue-300 sm:text-sm sm:leading-5">
<option selected>Limit</option>
<option>Make Order</option>
<option>Stop-limit</option>
</select>
</div>
<div class="hidden sm:block">
<div class="border-b border-gray-200">
<nav class="flex mt-1 -mb-px">
<button type="button" class="px-1 py-2 ml-8 text-sm font-medium leading-5 text-gray-500 whitespace-no-wrap border-b-2 border-transparent hover:no-underline focus:no-underline hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-indigo-500 focus:border-indigo-500 active:text-indigo-500" autofocus aria-current="page">
Limit
</button>
<button type="button" class="px-1 py-2 ml-8 text-sm font-medium leading-5 text-gray-500 whitespace-no-wrap border-b-2 border-transparent hover:no-underline focus:no-underline hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-indigo-500 focus:border-indigo-500 active:text-indigo-500">
Make Order
</button>
<div class="flex flex-row items-center justify-center ml-8" id="nav-heading" aria-labelledby="nav-heading" x-data="{ stopLimitOpen: false }" :aria-expanded="stopLimitOpen">
<svg class="pb-0.5 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<button type="button" class="px-1 py-2 text-sm font-medium leading-5 text-gray-500 whitespace-no-wrap border-b-2 border-transparent hover:no-underline focus:no-underline hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-indigo-500 focus:border-indigo-500 active:text-indigo-500">
Stop-limit
</button>
<button class="pb-0.5 focus:outline-none" type="button" :aria-expanded="stopLimitOpen" aria-controls="nav-list" #mouseenter="stopLimitOpen = !stopLimitOpen" #click.away="stopLimitOpen = false">
<svg class="w-3 h-3 ml-1 cursor-pointer" fill="currentColor" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show.transition.in.duration.100ms.origin.top.left.opacity.scale.10.out.duration.100ms.origin.bottom.right.opacity.scale.10="stopLimitOpen" id="nav-list" class="absolute z-10 w-auto origin-center rounded-md shadow-lg mt-28">
<!--
Stop Limit dropdown panel, show/hide based on dropdown state.
-->
<div #mouseleave="stopLimitOpen = !stopLimitOpen" class="py-1 bg-white rounded-md shadow-xs" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
<button type="button" class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 hover:no-underline focus:no-underline focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
<p class="flex justify-start font-medium">Stop-Limit</p>
</button>
<button type="button" class="block w-full px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 hover:no-underline focus:no-underline focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
<p class="flex justify-start font-medium">OCO</p>
</button>
</div>
</div>
</div>
</nav>
</div>
</div>
</div>
<!-- Buy/Sell Bitcoin Table -->
<div class="grid grid-cols-2 gap-16 mt-4">
<div class="col-span-1">
<div class="flex flex-row items-center justify-between">
<h4>Comprar BTC</h4>
<div class="flex flex-row items-center justify-center">
<svg aria-label="Lista" data-balloon-pos="up" id="show-tip" class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"></path>
</svg>
<p class="text-gray-600">- USDT</p>
</div>
</div>
</div>
<div class="col-span-1">
<div class="flex flex-row items-center justify-between">
<h4>Vender BTC</h4>
<div class="flex flex-row items-center justify-center">
<svg aria-label="Lista" data-balloon-pos="up" id="show-tip" class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"></path>
</svg>
<p class="text-gray-600">- USDT</p>
</div>
</div>
</div>
</div>
</div>

How to toggle class when click outside element with 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

Categories

Resources