<template>
<div
class="c-modal-dialog"
role="dialog"
aria-labelledby="dialog-title"
:class="[opened ? 'opened' : '']"
@keydown.esc="closeModalDialog()"
>
<div class="c-modal-dialog__window">
<div class="c-modal-dialog-content">
<div class="c-modal-dialog-header">
<h2 id="dialog-title" class="c-modal-dialog-title">
<slot name="header"></slot>
</h2>
</div>
<div class="c-modal-dialog-body">
<slot name="body"></slot>
<div class="c-modal-dialog-actions">
<c-button
ref="cancel"
text="Cancel"
intent="secondary"
type="button"
class="c-modal-dialog-action-cancel"
@click.native="closeModalDialog()"
/>
<slot name="ok"></slot>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import CButton from "~/components/cartier/CButton";
export default {
components: {
CButton: CButton,
},
data() {
return {
opened: false,
previousActiveElement: null,
};
},
watch: {
"$store.state.dialog.opened": function() {
this.opened = this.$store.state.dialog.opened;
},
},
methods: {
getFocusableElements(node) {
return node.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
},
getFocusableElementsDialog() {
return this.getFocusableElements(
document.querySelector(".c-modal-dialog")
);
},
getFocusableElementsPage() {
return this.getFocusableElements(document);
},
openModalDialog() {
// Grab a reference to the previous activeElement
// We'll want to restore this when we close the dialog
this.previousActiveElement = document.activeElement;
// While Open, Prevent Tabbing to Outside the Dialog
const elementsPage = Array.from(this.getFocusableElementsPage());
const elementsDialog = Array.from(
this.getFocusableElementsDialog()
);
elementsPage.forEach(child => {
if (!elementsDialog.includes(child)) {
child.setAttribute("tabindex", "-1");
}
});
// Make the dialog visible
this.$store.commit("dialog/openDialog");
// Move focus into the button cancel in the dialog
this.$nextTick(() => this.$refs.cancel.$el.focus());
},
closeModalDialog() {
// Close dialog
this.$store.commit("dialog/closeDialog");
// Allow Tabbing to Outside the Dialog
const elementsPage = Array.from(this.getFocusableElementsPage());
const elementsDialog = Array.from(
this.getFocusableElementsDialog()
);
elementsPage.forEach(child => {
if (!elementsDialog.includes(child)) {
child.setAttribute("tabindex", "0");
}
});
// Restore focus to the previous active element
if (this.previousActiveElement) {
this.previousActiveElement.focus();
}
},
},
};
</script>
<style scope lang="scss">
@import "~/assets/scss/variables";
.c-modal-dialog {
display: none;
&.opened {
display: block;
}
&__window {
display: inline-block;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
border-radius: 4px;
padding: 2rem;
z-index: 101;
}
&-title {
font-family: $font-secondary;
font-size: 2.5rem;
font-weight: 400;
padding: 2rem 0;
}
&-actions {
padding-top: 3rem;
display: flex;
justify-content: flex-end;
}
&-action-cancel {
margin-right: 1rem;
}
}
</style>