Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
{# v6 #}
{# USAGE:
{% embed '_components/modal' with {
modalHandle: 'exampleHandle'
} %}
{% block modalContent %}
SOMETHING INSIDE
{% endblock %}
{% endembed %}
#}
{% html at endBody %}
<div
x-data="modalComponent{{modalHandle}}()"
x-init="onStart()"
class="modal-component modal-component--{{modalHandle}}"
data-modal-handle="{{modalHandle}}"
>
<template x-if="open">
<div
class="modal-component__transition"
x-transition:enter-start="modal-component-hidden"
x-transition:enter-end="modal-component-visible"
x-transition:leave-start="modal-component-visible"
x-transition:leave-end="modal-component-hidden"
>
<div class="modal-component__blocker">
<div
class="modal-component__container"
@mousedown.away="closeModal()"
@keydown.window.escape="closeModal()"
>
<button
class="modal-component__close"
@click="closeModal()"
aria-label="{{'Close'|t('app')}}"
title="{{'Close'|t('app')}}"
</button>
<div
class="modal-component__content"
data-modal-content
>
{% block modalContent %}{% endblock %}
</div>
</div>
</div>
</div>
</template>
</div>
{% endhtml %}
{% js %}
function alpineModalOpen(handle, options){
document.querySelector('[data-modal-handle="'+handle+'"]').__x.$data.openModal(options);
}
function alpineModalClose(handle){
document.querySelector('[data-modal-handle="'+handle+'"]').__x.$data.closeModal();
}
function alpineModalCloseAll(){
document.querySelector('[data-modal-handle]').__x.$data.closeModal();
}
function modalComponent{{modalHandle}}(){
return{
onStart: function(){
var instance = this;
this.$watch('open', function(value){
if(instance.open == false) {
document.getElementsByTagName('html')[0].classList.remove('html-modal-opened');
} else {
document.getElementsByTagName('html')[0].classList.add('html-modal-opened');
}
});
},
closeModal: function(){
this.open = false;
},
openModal: function(options){
this.open = true;
this.$nextTick(function(){
if(typeof options != 'undefined' && typeof options.onOpen == 'function'){
options.onOpen();
}
})
},
open: false,
}
}
{% endjs %}
{% js 'https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js' with {
type: 'module',
} %}
{% js 'https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine-ie11.min.js' with {
defer: true,
nomodule: true,
} %}
{% css %}
.html-modal-opened{
overflow: hidden;
}
.modal-component-visible{
opacity: 1;
}
.modal-component-hidden{
opacity: 0;
}
.modal-component{
--modal-background-outside: rgba(0,0,0,0.8);
--modal-background-inside: white;
--modal-width: 40rem;
--modal-padding: 1rem;
}
.modal-component__blocker{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
z-index: 9999;
padding: 1rem;
box-sizing: border-box;
background-color: var(--modal-background-outside);
text-align: center;
}
@media (max-width: 1023px){
.modal-component__blocker{
padding-left: 0rem;
padding-right: 0rem;
}
}
.modal-component__blocker:before{
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.05em;
}
.modal-component__container{
text-align: initial;
display: inline-block;
vertical-align: middle;
position: relative;
box-sizing: border-box;
outline: none;
width: 90%;
max-width: var(--modal-width);
background: var(--modal-background-inside);
padding: var(--modal-padding);
padding-top: 2rem;
}
.modal-component__close{
position: absolute;
font-size: 1.75rem;
z-index: 2;
background: none;
border: none;
opacity: 0.5;
top: 0px;
right: 0px;
padding-left: 0.5rem;
padding-right: 0.5rem;
cursor: pointer;
touch-action: manipulation;
}
.modal-component__close:hover{
opacity: 1;
}
{% endcss %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment