I have a webpage using Alpine.js with Focus Plugin to open a modal when an item is clicked, I also want to be able to open the modal with the space bar and enter key
It works, but when using the enter key it seems to trigger again the click to the modal and it reopens at the moment
This is the code:
<div x-data="{ open: false }">
<div class="mt-8 grid grid-cols-3 gap-8 mx-auto max-w-4xl">
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 1"
@keyup.enter="open = 1"
@keyup.space="open = 1"
tabindex="0"
>1</div>
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 2"
@keyup.enter="open = 2"
@keyup.space="open = 2"
tabindex="0"
>2</div>
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 3"
@keyup.enter="open = 3"
@keyup.space="open = 3"
tabindex="0"
>3</div>
</div>
<div
id="modal"
class="bg-black/50 fixed top-0 left-0 w-full h-full p-4 grid place-items-center z-10"
x-show="open"
x-cloak
x-trap.inert="open != 0"
x-transition.opacity
>
<div class="modal__body bg-white max-w-[760px] p-8 relative" x-transition.delay.50ms>
<button
type="button"
class="font-bold uppercase"
@click="open = false"
@keyup.enter="open = false"
@keyup.space="open = false"
tabindex="0"
>
Close
</button>
<div>Modal content</div>
</div>
</div>
</div>
I've prepared a simple CodePen to see the issue, just tab to any element and hit enter to open modal, then hit enter to close
<button>
elements automatically fire click
events for Enter or Space keypresses, on the keydown
of the keypress.
Thus, when Enter or Space is pressed down on the close button of the modal, the modal closes. However, focus is then returned the <div>
and when one releases the Enter or Space key, this activates the keyup
event listener.
To work around this, you could consider listening for keydown
instead on the <div>
elements:
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.13.0/dist/cdn.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.13.0/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com/3.3.3"></script>
<div x-data="{ open: false }">
<div class="mt-8 grid grid-cols-3 gap-8 mx-auto max-w-4xl">
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 1"
@keydown.enter="open = 1"
@keydown.space="open = 1"
tabindex="0"
>1</div>
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 2"
@keydown.enter="open = 2"
@keydown.space="open = 2"
tabindex="0"
>2</div>
<div
class="aspect-square rounded bg-gray-300 grid place-items-center font-bold text-3xl"
@click="open = 3"
@keydown.enter="open = 3"
@keydown.space="open = 3"
tabindex="0"
>3</div>
</div>
<div
id="modal"
class="bg-black/50 fixed top-0 left-0 w-full h-full p-4 grid place-items-center z-10"
x-show="open"
x-cloak
x-trap.inert="open != 0"
x-transition.opacity
>
<div class="modal__body bg-white max-w-[760px] p-8 relative" x-transition.delay.50ms>
<button
type="button"
class="font-bold uppercase"
@click="open = false"
tabindex="0"
>
Close
</button>
<div>Modal content</div>
</div>
</div>
</div>