I need the x-on:mouseenter="itemActive = {{ index }}"
and x-on:mouseleave="itemActive = false"
states to be x-on:click="itemActive = {{ index }}"
and x-on:click.away="itemActive = false"
on screen smaller than 768px. The code below works perfectly with the hover part for larger screens but can't seem to figure out how to make it work with different screen sizes.
I am using Twig, Tailwind and Alpine.JS.
<div x-data="{itemActive: false}" class="w-full pb-12 mt-5 overflow-x-hidden overflow-y-scroll md:flex md:flex-wrap md:w-auto md:mt-0 md:pb-0 md:overflow-visible">
{% for item in menu.items %} {% set index = loop.index0 %}
<div x-on:mouseenter="itemActive = {{ index }}" x-on:mouseleave="itemActive = false" class="flex flex-wrap w-full md:block md:w-auto {{ item.classes|join(' ') }}">
<a :class="{'bg-gray-900' : itemActive === {{ index }}}" class="flex flex-wrap items-center justify-between w-full h-10 px-4 cursor-pointer md:h-14 md:justify-start md:w-auto" href="{{ item.link }}">
{{ item.title }}
{% if item.children %}
<span><i class="pl-2 fa fa-caret-down"></i></span>
{% endif %}
</a>
{% if item.children %}
<div x-show="itemActive === {{ index }}" class="absolute z-10 w-48 bg-gray-900">
{% for child in item.children %}
<a class="flex flex-wrap items-center h-12 px-4 transition-colors cursor-pointer md:h-14 hover:bg-gray-700" href="{{ child.link }}" >
{{ child.title }}
</a>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
Any suggestions?
I came across with the same problem last night and I used the following approach:
<div
x-data="{ open: false, timeout: null}"
x-on:mouseenter="
width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if (width > 640) {
open = true; clearTimeout(timeout)
}
"
x-on:mouseleave="
width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if (width > 640) {
timeout = setTimeout(() => { open = false }, 100)
}
"
@resize.window="
width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if (width > 640) {
open = false
}
"
class="flex flex-col items-start justify-start sm:items-center w-full sm:relative sm:w-3/12 font-bold"
>
<div
@click="open = !open"
x-bind:class="open ? 'border-black border-b sm:border-0' : ''"
class=" p-2 sm:p-0 w-full text-left sm:text-center hover:text-primary-light"
>
ABOUT US
</div>
<div x-show="open" class="flex flex-col items-start sm:items-center bg-white sm:border sm:border-black sm:rounded-lg w-full static sm:absolute sm:shadow-xl mx-auto top-0 mt-0 sm:mt-6 font-light pb-2">
<a href={Routes.page_path(Endpoint, :index)} class="pl-4 sm:pl-0 w-full text-left sm:text-center pt-2 pb-2 border-b sm:border-b-0 sm:rounded-t-lg hover:bg-gray-100">
Our Mission
</a>
<a href={Routes.page_path(Endpoint, :index)} class="pl-4 sm:pl-0 w-full text-left sm:text-center pt-2 pb-2 border-b sm:border-b-0 hover:bg-gray-100">
Our Team
</a>
<a href={Routes.page_path(Endpoint, :index)} class="pl-4 sm:pl-0 w-full text-left sm:text-center pt-2 pb-2 border-b sm:border-b-0 hover:bg-gray-100">
Join Us
</a>
<a href={Routes.page_path(Endpoint, :index)} class="pl-4 sm:pl-0 w-full text-left sm:text-center pt-2 pb-2 border-b sm:border-b-0 sm:rounded-b-lg hover:bg-gray-100">
Contact Us
</a>
</div>
</div>
The key parts are the code inside the x-on:mouseenter
, x-on:mouseleave
, and @resize.window
. We specify that the event is only be triggered when the width > 640. The @resize.windows
is important when you expand the browser and reach a breakpoint, so we can reset the open
variable, otherwise the state is dragged.