@cloudmesh.dev/alpine-lightbox
Version:
A dynamic lightbox using AlpineJS and TailwindCSS
60 lines (56 loc) • 3.02 kB
JavaScript
export default function (Alpine) {
document.addEventListener('alpine:init', () => {
let body = document.querySelector('body');
body.insertAdjacentHTML('afterbegin', `<div
style="display: none;"
class="fixed inset-0 z-50 grid w-screen h-screen max-h-dvh gap-2 px-4 bg-slate-200/70 dark:bg-slate-800/70 backdrop-blur-xl sm:px-12 place-items-center transform transition-all alpine-lightbox"
aria-labelledby="modal-title"
role="dialog"
aria-modal="true"
x-data
x-bind:class="$store.lightbox.show ? '' : 'hidden'"
x-show="$store.lightbox.show"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="transform opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="transform opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="transform opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="transform opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
<div class="block box-border max-w-full max-h-svh ">
<img x-on:click="$store.lightbox.toggle()" @click.away="$store.lightbox.show = false" class="block sm:p-12 box-border object-contain w-auto h-auto max-w-full max-h-svh alpine-lightbox-image" x-bind:src="$store.lightbox.src"
x-transition:enter="transition ease-out duration-300 delay-150"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0" /></div>
<div class="hidden sm:block absolute top-4 right-4">
<button x-on:click="$store.lightbox.toggle()" type="button" class="text-slate-700 hover:text-slate-900 dark:text-slate-300 hover:dark:text-slate-100 focus:outline-none focus:ring-none">
<span class="sr-only">Close</span>
<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>
`);
document.addEventListener('keyup', (e) => {
if (e.key === 'Escape') {
Alpine.store('lightbox').show = false;
}
})
Alpine.store('lightbox', {
show: false,
src: null,
toggle() {
this.show = !this.show;
}
});
Alpine.directive('lightbox', (el, { expression }) => {
el.addEventListener('click', () => {
Alpine.store('lightbox').toggle();
Alpine.store('lightbox').src = expression;
});
});
});
}