Before merging from develop
This commit is contained in:
parent
d704eee8e8
commit
2fd0ce5f21
8 changed files with 379 additions and 55 deletions
|
|
@ -79,7 +79,7 @@ const endpoints = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
GetServiceabilityDetails: {
|
GetServiceabilityDetails: {
|
||||||
url: "/location/serviceability-details",
|
url: "/location/api/v1/location/serviceability-details",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
GetSupportingItems: {
|
GetSupportingItems: {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer px-5 py-4">
|
<div class="modal-footer px-5 py-4">
|
||||||
<buttonMain
|
<modalButtonMain
|
||||||
isPrimary
|
isPrimary
|
||||||
class="w-100"
|
class="w-100"
|
||||||
ref="buttonMain"
|
ref="buttonMain"
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import buttonMain from "@/ux-components/button-main/button-main";
|
import modalButtonMain from "@/ux-components/modal-button-main/modal-button-main";
|
||||||
import { Modal } from "bootstrap";
|
import { Modal } from "bootstrap";
|
||||||
import { useForm, useIsFormTouched, useIsFormDirty, useIsFormValid } from "vee-validate";
|
import { useForm, useIsFormTouched, useIsFormDirty, useIsFormValid } from "vee-validate";
|
||||||
|
|
||||||
|
|
@ -60,14 +60,14 @@ export default {
|
||||||
setup() {
|
setup() {
|
||||||
const modalId = `modal-${crypto.randomUUID()}`;
|
const modalId = `modal-${crypto.randomUUID()}`;
|
||||||
|
|
||||||
const form = useForm();
|
const { validate } = useForm();
|
||||||
const isFormTouched = useIsFormTouched();
|
const isFormTouched = useIsFormTouched();
|
||||||
const isFormDirty = useIsFormDirty();
|
const isFormDirty = useIsFormDirty();
|
||||||
const isFormValid = useIsFormValid();
|
const isFormValid = useIsFormValid();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modalId,
|
modalId,
|
||||||
form,
|
validate,
|
||||||
isFormTouched,
|
isFormTouched,
|
||||||
isFormDirty,
|
isFormDirty,
|
||||||
isFormValid,
|
isFormValid,
|
||||||
|
|
@ -75,7 +75,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async validateAndEmit() {
|
async validateAndEmit() {
|
||||||
const validationResult = await this.form.validate();
|
const validationResult = await this.validate();
|
||||||
if (validationResult.valid) {
|
if (validationResult.valid) {
|
||||||
this.$emit("footer-button-event");
|
this.$emit("footer-button-event");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -110,7 +110,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
buttonMain,
|
modalButtonMain,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
:isGlassServiceableMobile="isGlassServiceableMobile"
|
:isGlassServiceableMobile="isGlassServiceableMobile"
|
||||||
:isRecalibrationServiceableMobile="isRecalibrationServiceableMobile"
|
:isRecalibrationServiceableMobile="isRecalibrationServiceableMobile"
|
||||||
ref="serviceTypeQuestion"
|
ref="serviceTypeQuestion"
|
||||||
groupName="ServiceTypeQuestion"
|
groupName="serviceTypeQuestion"
|
||||||
cmsWidgetName="ServiceTypeQuestionWidget"
|
cmsWidgetName="ServiceTypeQuestionWidget"
|
||||||
validationRules="option-required" />
|
validationRules="option-required" />
|
||||||
<mobileLocationModalQuestions
|
<mobileLocationModalQuestions
|
||||||
|
|
@ -96,11 +96,7 @@ export default {
|
||||||
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
|
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
|
||||||
const getZipCodeData = baseMixin.methods.getZipCodeData(serviceZipCode);
|
const getZipCodeData = baseMixin.methods.getZipCodeData(serviceZipCode);
|
||||||
|
|
||||||
const lineItems = store.getters.order.lineItems;
|
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
||||||
const serviceabilityDetailsPromise = getServiceabilityDetails({
|
|
||||||
serviceZipCode: serviceZipCode,
|
|
||||||
lineItems: lineItems,
|
|
||||||
});
|
|
||||||
|
|
||||||
const serviceType = store.getters.damage.isRepair ? "Repair" : "Replace";
|
const serviceType = store.getters.damage.isRepair ? "Repair" : "Replace";
|
||||||
const parentAccountNumber = store.getters.payment.parentAccountNumber;
|
const parentAccountNumber = store.getters.payment.parentAccountNumber;
|
||||||
|
|
@ -256,11 +252,8 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const lineItems = store.getters.order.lineItems;
|
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
|
||||||
const serviceabilityDetails = await getServiceabilityDetails({
|
const serviceabilityDetails = await getServiceabilityDetails(serviceZipCode);
|
||||||
serviceZipCode: newValue,
|
|
||||||
lineItems: lineItems,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setServiceabilityDetails(serviceabilityDetails.data);
|
this.setServiceabilityDetails(serviceabilityDetails.data);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -55,34 +55,17 @@ export default {
|
||||||
return filteredAnswers;
|
return filteredAnswers;
|
||||||
},
|
},
|
||||||
serviceability() {
|
serviceability() {
|
||||||
|
const mobileAvailable = this.isGlassServiceableMobile && this.isRecalibrationServiceableMobile;
|
||||||
|
const inshopAvailable = this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop;
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
if (
|
if (inshopAvailable && mobileAvailable) {
|
||||||
this.isGlassServiceableMobile &&
|
|
||||||
this.isRecalibrationServiceableMobile &&
|
|
||||||
this.isGlassServiceableInshop &&
|
|
||||||
this.isRecalibrationServiceableInshop
|
|
||||||
) {
|
|
||||||
result = "All";
|
result = "All";
|
||||||
} else if (
|
} else if (inshopAvailable && !mobileAvailable) {
|
||||||
!this.isGlassServiceableInshop &&
|
|
||||||
!this.isRecalibrationServiceableInshop &&
|
|
||||||
this.isGlassServiceableMobile &&
|
|
||||||
this.isRecalibrationServiceableMobile
|
|
||||||
) {
|
|
||||||
result = "MobileOnly";
|
|
||||||
} else if (
|
|
||||||
this.isGlassServiceableInshop &&
|
|
||||||
this.isRecalibrationServiceableInshop &&
|
|
||||||
!this.isGlassServiceableMobile &&
|
|
||||||
!this.isRecalibrationServiceableMobile
|
|
||||||
) {
|
|
||||||
result = "InshopOnly";
|
result = "InshopOnly";
|
||||||
} else if (
|
} else if (!inshopAvailable && mobileAvailable) {
|
||||||
!this.isGlassServiceableInshop &&
|
result = "MobileOnly";
|
||||||
!this.isRecalibrationServiceableInshop &&
|
} else if (!inshopAvailable && !mobileAvailable) {
|
||||||
!this.isGlassServiceableMobile &&
|
|
||||||
!this.isRecalibrationServiceableMobile
|
|
||||||
) {
|
|
||||||
result = "None";
|
result = "None";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,11 +82,9 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
serviceability: {
|
serviceability: {
|
||||||
handler(newValue, oldValue) {
|
handler(newValue) {
|
||||||
if (newValue == "MobileOnly") {
|
if (newValue == "MobileOnly") {
|
||||||
this.selectedValues = "Mobile";
|
this.selectedValues = "Mobile";
|
||||||
} else {
|
|
||||||
this.selectedValues = null;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
@footer-button-event="setZipCode">
|
@footer-button-event="setZipCode">
|
||||||
<serviceZipQuestion
|
<serviceZipQuestion
|
||||||
ref="serviceZipQuestion"
|
ref="serviceZipQuestion"
|
||||||
|
customInputId="serviceZipCode"
|
||||||
v-model="internalModel.zipCode"
|
v-model="internalModel.zipCode"
|
||||||
v-on="{ 'textboxQuestionEvent.inputIdAssigned': onInputIdAssigned }"
|
v-on="{ 'textboxQuestionEvent.inputIdAssigned': onInputIdAssigned }"
|
||||||
:cmsWidgetName="textboxQuestionWidgetName" />
|
:cmsWidgetName="textboxQuestionWidgetName" />
|
||||||
|
|
@ -49,6 +50,7 @@ export default {
|
||||||
internalModel: this.copyModel(this.modelValue),
|
internalModel: this.copyModel(this.modelValue),
|
||||||
serviceZipCodeTextInputId: "",
|
serviceZipCodeTextInputId: "",
|
||||||
displayInvalidZipAlert: false,
|
displayInvalidZipAlert: false,
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
||||||
|
|
@ -926,14 +926,13 @@ export const actions = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getServiceabilityDetails(context, { serviceZipCode, lineItems }) {
|
getServiceabilityDetails(context, { serviceZipCode }) {
|
||||||
return globalMethods.callMockHttpClient({
|
const lineItems = context.getters.order.lineItems;
|
||||||
|
const lineItemsToSend = [...lineItems.supportingItems];
|
||||||
|
const encodedLineItems = encodeURIComponent(JSON.stringify(lineItemsToSend))
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetServiceabilityDetails.method,
|
method: endpoints.GetServiceabilityDetails.method,
|
||||||
//TODO: Remove Mocky Endpoints
|
endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&lineItems=${encodedLineItems}`,
|
||||||
//endpoint: "https://run.mocky.io/v3/59e1a644-cf16-4f08-8069-1ab2a1e38f79", // NoShopsAvailable
|
|
||||||
//endpoint: "https://run.mocky.io/v3/4fe1fb89-dd56-4e4a-9af2-96bd1ab77847", // ForcedInshop
|
|
||||||
//endpoint: "https://run.mocky.io/v3/e2eaa097-6ea5-4906-af53-901edaa94939", // ForcedMobile
|
|
||||||
endpoint: "https://run.mocky.io/v3/1811a1fe-12a7-48f3-939e-d10a9b77dd25", // All Options
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1664,3 +1663,12 @@ function getLineItemQueryStringForPricing(lineItems) {
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLineItemQueryStringForServiceability(lineItems) {
|
||||||
|
return lineItems
|
||||||
|
.map((lineItem) => {
|
||||||
|
let queryStringSnippet = `&lineItems=${lineItem.partNumber}`;
|
||||||
|
return queryStringSnippet;
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
|
||||||
187
src/ux-components/modal-button-main/modal-button-main.spec.js
Normal file
187
src/ux-components/modal-button-main/modal-button-main.spec.js
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import buttonMain from "./button-main";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
|
describe("buttonMain.vue", () => {
|
||||||
|
it("Should return btn-primary class", () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
isPrimary: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const button = wrapper.find("button");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(button.attributes("class")).toContain("btn-primary");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return aria-disabled state", () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
isDisabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const button = wrapper.find("button");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(button.attributes()["aria-disabled"]).toEqual("true");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader color", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderColor: "blue",
|
||||||
|
loaderEnabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.clicked();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
expect(loader.attributes("class")).toContain("blue");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should return loader position", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.clicked();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
expect(loader.attributes("class")).toContain("right");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should set 'isLoaderDisplayed' to false when calling 'removeLoader'", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.setData({
|
||||||
|
isLoaderDisplayed: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.removeLoader();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const loader = wrapper.find("loader-stub");
|
||||||
|
expect(wrapper.vm.isLoaderDisplayed).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should set 'isLoaderDisplayed' to false when calling 'resetButtonStyle'", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.setData({
|
||||||
|
isLoaderDisplayed: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.resetButtonStyle();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.isLoaderDisplayed).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should emit 'click-event' event when clicking if the button is enabled", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true,
|
||||||
|
isDisabled: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonElement = wrapper.find("button");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
buttonElement.trigger("click");
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.emitted("click-event")).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should not emit 'click-event' event when clicking if the button is disabled", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(
|
||||||
|
buttonMain,
|
||||||
|
setupMocks({
|
||||||
|
props: {
|
||||||
|
loaderPosition: "right",
|
||||||
|
loaderEnabled: true,
|
||||||
|
isDisabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttonElement = wrapper.find("button");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
buttonElement.trigger("click");
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.emitted("click-event")).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks(mountOptionsMockData = {}) {
|
||||||
|
const defaultMountOptions = { route: { query: { fmgPage: "page-name" } } };
|
||||||
|
const baseMountOptions = getMountOptions(
|
||||||
|
Object.assign(defaultMountOptions, mountOptionsMockData)
|
||||||
|
);
|
||||||
|
const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions);
|
||||||
|
|
||||||
|
return allMountOptions;
|
||||||
|
}
|
||||||
153
src/ux-components/modal-button-main/modal-button-main.vue
Normal file
153
src/ux-components/modal-button-main/modal-button-main.vue
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
<template>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
:aria-disabled="isDisabled"
|
||||||
|
class="btn d-flex align-items-center justify-content-center py-3 px-4 delay"
|
||||||
|
:class="[
|
||||||
|
isPrimary ? 'btn-primary' : 'btn-secondary',
|
||||||
|
isFloat ? 'float-end' : '',
|
||||||
|
isLoaderDisplayed ? 'has-loader' : '',
|
||||||
|
]"
|
||||||
|
@click="clicked">
|
||||||
|
<span class="m-0">{{ this.buttonText }}</span>
|
||||||
|
<loader
|
||||||
|
class="ms-2"
|
||||||
|
v-if="isLoaderDisplayed && !suppressLoader"
|
||||||
|
v-bind:class="[this.loaderColor, this.loaderPosition]" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import loader from "@/ux-components/loader/loader";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "modalButtonMain",
|
||||||
|
props: {
|
||||||
|
isPrimary: Boolean,
|
||||||
|
buttonText: String,
|
||||||
|
isDisabled: Boolean,
|
||||||
|
loaderColor: String,
|
||||||
|
loaderPosition: String,
|
||||||
|
isFloat: Boolean,
|
||||||
|
suppressLoader: Boolean,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoaderDisplayed: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
removeLoader() {
|
||||||
|
this.isLoaderDisplayed = false;
|
||||||
|
},
|
||||||
|
clicked() {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
|
this.GaActions.CLICKED,
|
||||||
|
this.buttonText,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
if (!this.isDisabled) {
|
||||||
|
this.isLoaderDisplayed = true;
|
||||||
|
this.$emit("click-event");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetButtonStyle() {
|
||||||
|
this.isLoaderDisplayed = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
loader,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.btn {
|
||||||
|
&.btn-primary {
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
color: $white;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 500;
|
||||||
|
@media (hover: hover) {
|
||||||
|
background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700;
|
||||||
|
}
|
||||||
|
&:focus, // Mouse, touch, stylus focus
|
||||||
|
&:focus-visible {
|
||||||
|
// Keyboard focus for accessibility
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700;
|
||||||
|
color: $white;
|
||||||
|
background: linear-gradient(270deg, rgba(6, 87, 124, 1) 0%, rgba(6, 87, 124, 1) 100%);
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
background: $gray-200 !important;
|
||||||
|
background: linear-gradient(270deg, $gray-200 0%, $gray-200 100%) !important;
|
||||||
|
color: $gray-600 !important;
|
||||||
|
font-weight: 400;
|
||||||
|
height: 48px;
|
||||||
|
border: none;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
&.has-loader {
|
||||||
|
color: $white;
|
||||||
|
background: $blue-700;
|
||||||
|
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
&.delay {
|
||||||
|
// fixes flicker while transitioning between states
|
||||||
|
transition: background 0s 0s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.btn-secondary {
|
||||||
|
position: relative;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid $blue;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
color: $blue;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
height: 3rem;
|
||||||
|
&:hover {
|
||||||
|
color: $white;
|
||||||
|
@include blue-gradient;
|
||||||
|
}
|
||||||
|
&:focus, // Mouse, touch, stylus focus
|
||||||
|
&:focus-visible {
|
||||||
|
// Keyboard focus for accessibility
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $blue-700;
|
||||||
|
color: $white;
|
||||||
|
@include blue-gradient;
|
||||||
|
}
|
||||||
|
&:disabled {
|
||||||
|
background: transparent;
|
||||||
|
color: $gray-550 !important;
|
||||||
|
font-weight: 400;
|
||||||
|
height: 48px;
|
||||||
|
border: 1px solid $gray-550;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
&.has-loader {
|
||||||
|
color: $white;
|
||||||
|
@include blue-gradient;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
&.delay {
|
||||||
|
// fixes flicker while transitioning between states
|
||||||
|
transition: background 0s 0s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in a new issue