Stimulus Discourse

Mouseover/out mega-menu controller

#1

I’m trying to develop a “mega-menu” using Stimulus, similar to the Series link on this page: https://laracasts.com/series?curated

If I mouseover one of the links, it’ll display the correct sub menu. If I mouseout the sub menu goes away. The issue I’m having is getting the sub menu to stay open if the user’s cursor continues down to the sub menu element.

.subitem { width: 100%; z-index: 1000; position: absolute; opacity: 0; visibility: visible; }
.active { opacity: 1; visibility: visible; }
<div data-controller="megamenu">
	<div>
		<a href="#" data-action="mouseover->megamenu#here mouseout->megamenu#gone" data-submenu-index="0">Link 1</a>
		<a href="#" data-action="mouseover->megamenu#here mouseout->megamenu#gone" data-submenu-index="0">Link 2</a>
	</div>
	<div class="subitem" data-target="megamenu.submenu">
		<h2>Sub Menu 1</h2>
		<ul>
			<li>Item 1</li>
			<li>Item 2</li>
		</ul>
	</div>
	<div class="subitem" data-target="megamenu.submenu">
		<h2>Sub Menu 2</h2>
		<ul>
			<li>Item 3</li>
			<li>Item 4</li>
		</ul>
	</div>
</div>
import { Controller } from "stimulus"

export default class extends Controller {
	
	static targets = ['submenu']
	
	here() {
		const element = event.target

		this.submenuTargets.forEach((el, i) => {
			element.dataset.submenuIndex == i ? el.classList.add('active') : ''
		})
	}

	gone() {
		const element = event.target

		this.submenuTargets.forEach((el, i) => {
			element.dataset.submenuIndex == i ? el.classList.remove('active') : ''
		})
	}
}
#2

Just as a follow-up, I think I have it working. I had to change mouseover and mouseout to mouseenter and mouseleave.

Then for each sub menu I added the same actions and passed through the submenu-index. So:

<div data-controller="megamenu">
	<div>
		<a href="#" data-action="mouseenter->megamenu#here mouseleave->megamenu#gone" data-submenu-index="0">Link 1</a>
		<a href="#" data-action="mouseenter->megamenu#here mouseleave->megamenu#gone" data-submenu-index="0">Link 2</a>
	</div>
	<div class="subitem" data-target="megamenu.submenu" data-action="mouseenter->megamenu#here mouseleave->megamenu#gone" data-submenu-index="0">
		<h2>Sub Menu 1</h2>
		<ul>
			<li>Item 1</li>
			<li>Item 2</li>
		</ul>
	</div>
	<div class="subitem" data-target="megamenu.submenu" data-action="mouseenter->megamenu#here mouseleave->megamenu#gone" data-submenu-index="1">
		<h2>Sub Menu 2</h2>
		<ul>
			<li>Item 3</li>
			<li>Item 4</li>
		</ul>
	</div>
</div>

I also added a click toggle on the main menu items for accessibility purposes.