Merge pull request #526 from Safelite/CSR-544-footer-modal

CSR 544 footer modal
This commit is contained in:
bmauger 2022-05-31 17:02:43 -04:00 committed by GitHub
commit 2b27eca24c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 151 additions and 107 deletions

View file

@ -27,6 +27,7 @@ module.exports = {
"!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue",
"!src/ux-components/alert\alert.vue",
"!src/helpers/validation-rules.js",
"!src/common-components/menu-modal/menu-modal.vue",
// END
], // ! means exclude from coverage.
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],

View file

@ -3,30 +3,6 @@ import funnelFooter from "./funnel-footer";
describe("funnel-footer.vue", () => {
it("Should return footer-link class", async () => {
// Act
const r = {
test:"testing",
clientHeight: 10,
offsetHeight: 24,
};
global.document.querySelector = jest.fn().mockImplementation(()=> {
return r;
});
const wrapper = mount(funnelFooter, {
mixins: [mockMixin]
});
// Assert
const link = wrapper.find("a");
// Expect
expect(link.attributes('class')).toContain("footer");
});
it("Should emit ForwardClicked on button click", async () => {
// Act
const wrapper = mount(funnelFooter, {
@ -53,7 +29,7 @@ describe("funnel-footer.vue", () => {
mixins: [mockMixin]
});
wrapper.vm.updateButtonText('newText');
// Assert
expect(wrapper.componentVM.customButtontext).toBe('newText');
});
@ -65,4 +41,4 @@ const mockMixin = {
getCmsContent: jest.fn(),
getFooterInfoBoxHeight: jest.fn(()=>80)
}
}
}

View file

@ -1,21 +1,6 @@
<template>
<div class="footer pt-4">
<div class="container-fluid g-2">
<div class="row">
<div class="col-12 d-flex justify-content-center pb-2 fs-7">
&copy;&nbsp;{{new Date().getFullYear()}}&nbsp;Safelite Group
</div>
</div>
<div class="row" :style="`padding-bottom: ${paddingHeight}px`">
<div class="col d-flex justify-content-center justify-content-around text-center">
<textLink linkType="footer" text="Terms of use" href="https://www.safelite.com/terms-of-use" />
<textLink linkType="footer" text="Privacy policy" href="https://www.safelite.com/safelite-group-privacy-policy" />
<textLink linkType="footer" text="Do not sell my information" href="https://privacyportal-cdn.onetrust.com/dsarwebform/d3b95a93-e22e-4d4d-a806-482052406557/9e371601-eae3-4338-9430-b90b9036022b.html" />
</div>
</div>
</div>
<div class="container-fluid fixed-bottom g-5 bg-light py-4" id="infoBox">
<div class="row d-flex flex-row-reverse align-items-center">
<footer class="footer container-fluid fixed-bottom g-5 bg-light py-4" id="infoBox">
<div class="row d-flex flex-row-reverse align-items-center vw-100">
<div class="col button-col d-flex" id="stacked">
<buttonMain
ref="buttonMain"
@ -26,6 +11,8 @@
:aria-disabled="isForwardActionDisabled"
:isDisabled="isForwardActionDisabled"
@click-event="buttonClick"
data-bs-target="#footerModal"
data-bs-dismiss="modal"
/>
</div>
<div v-if="!isBackButtonHidden" class="col-auto link-col py-1 text-break">
@ -34,11 +21,12 @@
:text="backLink"
@click-event="linkClick"
href="javascript:void(0)"
data-bs-target="#footerModal"
data-bs-dismiss="modal"
/>
</div>
</div>
</div>
</div>
</footer>
</template>
<script>
@ -80,7 +68,7 @@ export default {
},
buttonText(){
return this.customButtontext ? this.customButtontext : this.getCmsContent(this.cmsWidgetName, 'ForwardButtonText');
}
},
},
methods: {
onResize() {
@ -112,7 +100,6 @@ export default {
<style lang="scss" scoped>
.footer {
display: flex;
margin-top: auto;
a {
display: flex;
justify-content: center;

View file

@ -4,6 +4,7 @@
v-if="imageSrc"
>
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
<menuModal/>
</div>
<alert
class="position-absolute rounded-0 w-100 border-0 shadow-sm"
@ -19,6 +20,7 @@
import alert from "@/ux-components/alert/alert";
import eventBus from "@/helpers/event-bus/event-bus";
import { globalEvents } from "@/constants/events";
import menuModal from "@/common-components/menu-modal/menu-modal";
export default {
name: "funnel-header",
@ -43,6 +45,7 @@ export default {
},
components: {
alert,
menuModal,
},
mounted() {
// Check if alert event is on the bus
@ -50,7 +53,6 @@ export default {
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.PAGE_NOT_FOUND
);
// If alert event is on the bus, then display the alert
if (alertEvent !== undefined) {
this.displayGlobalAlert = true;
@ -70,5 +72,6 @@ export default {
}
.alert {
left: 0;
top: 72px;
}
</style>

View file

@ -1,53 +0,0 @@
<template>
<div class="menu-button" :class="[isActive ? 'active' : '']" @click="toggleClass()">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</template>
<script>
export default {
name: 'menuButton',
data() {
return {
isActive: false,
};
},
methods: {
toggleClass: function(event){
this.isActive = !this.isActive;
}
}
}
</script>
<style lang="scss">
.menu-button {
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
box-shadow: 0px 0px 8px 2px rgba(0,0,0,0.2);
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.bar1,
.bar2,
.bar3 {
width: 14px;
height: 2px;
background-color: $blue-400;
margin: 1px 0;
transition: 0.25s;
}
&.active .bar1 {
transform: rotate(-45deg) translate(-3px, 3px);
}
&.active .bar2 {opacity: 0;}
&.active .bar3 {
transform: rotate(45deg) translate(-3px, -3px);
}
}
</style>

View file

@ -0,0 +1,116 @@
<template>
<div class="menu-modal-container">
<button class="menu-button" type="button" :class="[isActive ? 'active' : '']" data-bs-toggle="modal" data-bs-target="#footerModal">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</button>
</div>
<!-- Modal -->
<div class="modal fade" id="footerModal" tabindex="-1" aria-labelledby="footerModalLabel" aria-hidden="true" :style="`height: calc(100% - ${currentFooterAndHeaderHeight}px);`">
<div class="modal-dialog modal-fullscreen">
<div class="modal-content">
<div class="modal-header visually-hidden">
<h5 class="modal-title" id="footerModalLabel">Footer Navigation</h5>
</div>
<div class="modal-body d-flex flex-column">
<textLink linkType="navigation" text="Terms of use" href="https://www.safelite.com/terms-of-use" />
<textLink linkType="navigation" text="Privacy policy" href="https://www.safelite.com/safelite-group-privacy-policy" />
<textLink linkType="navigation" text="Do not sell my information" href="https://privacyportal-cdn.onetrust.com/dsarwebform/d3b95a93-e22e-4d4d-a806-482052406557/9e371601-eae3-4338-9430-b90b9036022b.html" />
</div>
<div class="modal-footer d-flex justify-content-start">
&copy; {{new Date().getFullYear()}} Safelite Group
</div>
</div>
</div>
</div>
</template>
<script>
import textLink from "@/ux-components/text-link/text-link";
export default {
name: 'menuModal',
data() {
return {
isActive: false,
currentFooterAndHeaderHeight: 0,
};
},
mounted() {
const myModalEl = document.getElementById('footerModal');
var self = this;
myModalEl.addEventListener('hide.bs.modal', function (event) {
self.isActive = false;
});
myModalEl.addEventListener('show.bs.modal', function (event) {
self.currentFooterAndHeaderHeight = self.getFooterInfoBoxHeight() + 72;
self.isActive = true;
})
},
components: {
textLink,
}
}
</script>
<style lang="scss">
.menu-modal-container {
position: absolute;
padding: 1.47rem 1rem 1.47rem 1.47rem;
right: 0;
button {
border: none;
&.menu-button {
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
box-shadow: 0 2px 8px 0 rgba(0,0,0,0.2);
background-color: $white;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1056;
.bar1,
.bar2,
.bar3 {
width: 14px;
height: 2px;
background-color: $blue-400;
margin: 1px 0;
transition: 0.25s;
}
&.active .bar1 {
transform: rotate(-45deg) translate(-3px, 3px);
}
&.active .bar2 {opacity: 0;}
&.active .bar3 {
transform: rotate(45deg) translate(-3px, -3px);
}
}
}
}
.modal {
max-width: 576px;
left: auto;
height: calc(100% - 72px);
top: 72px;
border-top: 1px solid $gray-300;
.modal-body {
padding: 2rem;
}
.modal-fullscreen {
width: 100vw;
max-width: 576px;
}
.navigation-link {
margin-bottom: 1.5rem;
}
.modal-footer {
border-top: none;
padding: 2rem;
}
//.modal-backdrop styles are in common-styles.scss
}
</style>

View file

@ -7,7 +7,7 @@
</div>
<div class="row my-2">
<div class="col">
<menuButton/>
<menuModal/>
</div>
</div>
<div class="row my-4">
@ -1089,7 +1089,7 @@
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
import dropdownQuestion from "@/common-components/dropdown-question/dropdown-question";
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
import menuButton from "@/common-components/menu-button/menu-button";
import menuModal from "@/common-components/menu-modal/menu-modal";
export default {
name: "App",
components: {
@ -1104,7 +1104,7 @@
textboxQuestion,
dropdownQuestion,
vinInformation,
menuButton,
menuModal,
},
data() {
return {

View file

@ -43,9 +43,9 @@ export default {
}
},
getFooterInfoBoxHeight() {
const footerInfoBox = document.querySelector(".footer #infoBox");
const footerInfoBox = document.querySelector(".footer#infoBox");
return footerInfoBox ? footerInfoBox.offsetHeight : 0;
}
},
},
computed: {
storeActions() {

View file

@ -47,4 +47,14 @@ body {
.page-container-grouped-styles {
@extend .container-fluid, .shadow, .rounded-3, .p-2, .position-relative, .make-tall, .px-5;
}
}
//Footer modal backdrop adjustments for positioning
.modal-backdrop {
left: 50%;
transform: translateX(-50%);
max-width: 576px;
height: calc(100% - 152px);
top: 72px;
}
}

View file

@ -180,3 +180,7 @@ $box-shadow-inset: inset 0 1px 2px rgba($black, .075);
$alert-bg-scale: -90%;
$alert-border-scale: -100%;
$alert-color-scale: 40%;
//Modal animation
$modal-fade-transform: translate(0, 0);
$modal-backdrop-opacity: 0;