Modal
#
JavaScript setuplet modal = () => ({ open: false,
modalClose: { ["x-on:click"]() { this.open = false } },
modalOverlay: { ["x-transition:enter"]: "ease-out duration-300", ["x-transition:enter-start"]: "opacity-0", ["x-transition:enter-end"]: "opacity-100", ["x-transition:leave"]: "ease-in duration-200", ["x-transition:leave-start"]: "opacity-100", ["x-transition:leave-end"]: "opacity-0", ["x-show"]() { return this.open }, },
modalContent: { ["x-transition:enter"]: "ease-out duration-300", ["x-transition:enter-start"]: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95", ["x-transition:enter-end"]: "opacity-100 translate-y-0 sm:scale-100", ["x-transition:leave"]: "ease-in duration-200", ["x-transition:leave-start"]: "opacity-100 translate-y-0 sm:scale-100", ["x-transition:leave-end"]: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95", ["x-on:click.outside"]: "open = false", ["x-show"]() { return this.open }, }})
window.addEventListener("DOMContentLoaded", (event) => { document.querySelectorAll("[x-data='modal']").forEach(el => { let id = el.id el.setAttribute(`x-on:open-modal-${id}.window`, "open = true") el.setAttribute("x-show", "open")
document.querySelectorAll(`[data-modal-id="${id}"]`).forEach(el => { el.setAttribute("x-on:click", `$dispatch('open-modal-${id}')`) }) })
Alpine.data("modal", modal)})
#
How it works<button data-modal-id="<modal-id>"></button>
: Modal trigger. Must containdata-modal-id
.x-data="modal"
: Modal root element that stores the state. Must haveid
attribute.x-cloak
: Used to hide modal content before Alpine loads. https://alpinejs.dev/directives/cloakx-bind="modalOverlay"
: Modal overlay/backdrop.x-bind="modalPanel"
: Used to place modal content.x-bind="modalClose"
: Used to close modal.
<button data-modal-id="<modal-id>" type="button"></button>
<div x-data="modal" x-cloak id="<modal-id>"> <div x-bind="modalOverlay"></div>
<div x-bind="modalContent"> <button x-bind="modalClose"></button> </div></div>
#
Examples- Preview
- HTML
<button data-modal-id="modal-1" type="button" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> Button text</button>
<div x-data="modal" x-cloak id="modal-1" class="fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true"> <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> <div x-bind="modalOverlay" class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
<!-- This element is to trick the browser into centering the modal contents. --> <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div x-bind="modalContent" class="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6"> <div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4"> <button x-bind="modalClose" type="button" class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> <span class="sr-only">Close</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 class="sm:flex sm:items-start"> <div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10"> <!-- Heroicon name: outline/exclamation --> <svg class="h-6 w-6 text-red-600" 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="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> </svg> </div> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title"> Deactivate account </h3> <div class="mt-2"> <p class="text-sm text-gray-500"> Are you sure you want to deactivate your account? All of your data will be permanently removed from our servers forever. This action cannot be undone. </p> </div> </div> </div> <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse"> <button type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"> Deactivate </button> <button x-bind="modalClose" type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"> Cancel </button> </div> </div> </div></div>