Initial work on moving heritage button styles to NextGen button component
Added button variant support Added button size support Merged button features from modal button to button component Removed modal button component Created button mixins for creating buttons Created initial button variants using mixins Moved client button customizations to mixins
This commit is contained in:
parent
e679c02582
commit
fa965468b4
16 changed files with 342 additions and 555 deletions
8
src/constants/button-sizes.js
Normal file
8
src/constants/button-sizes.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
const buttonSizes = Object.freeze({
|
||||
xs: 'xs',
|
||||
sm: 'sm',
|
||||
md: 'md',
|
||||
lg: 'lg'
|
||||
});
|
||||
|
||||
export default buttonSizes;
|
||||
9
src/constants/button-variants.js
Normal file
9
src/constants/button-variants.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
const buttonVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
secondary: 'secondary',
|
||||
success: 'success',
|
||||
link: 'link',
|
||||
navigation: 'navigation'
|
||||
});
|
||||
|
||||
export default buttonVariants;
|
||||
|
|
@ -34,30 +34,18 @@
|
|||
<slot></slot>
|
||||
</div>
|
||||
<div class="modal-footer px-5 py-4">
|
||||
<modalButtonMain
|
||||
v-if="useDefaultButton"
|
||||
<buttonMain
|
||||
id="modalbtn"
|
||||
ref="modalButtonMain"
|
||||
isPrimary
|
||||
:variant="buttonVariant"
|
||||
class="w-100"
|
||||
:buttonText="footerButtonText"
|
||||
pushToGA
|
||||
:class="[
|
||||
(isButtonDisabled || isFooterButtonDisabled) &&
|
||||
'form-test-invalid',
|
||||
additionalClassesString
|
||||
'form-test-invalid'
|
||||
]"
|
||||
@clickEvent="validateAndEmit" />
|
||||
<button
|
||||
v-if="!useDefaultButton"
|
||||
class="w-100 btn d-flex align-items-center justify-content-center delay"
|
||||
:class="[
|
||||
(isButtonDisabled || isFooterButtonDisabled) &&
|
||||
'form-test-invalid',
|
||||
additionalClassesString
|
||||
]"
|
||||
@click="validateAndEmit">
|
||||
<span class="m-0">{{ footerButtonText }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -65,7 +53,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import modalButtonMain from '@/ux-components/modal-button-main/modal-button-main.vue';
|
||||
import ButtonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import { Modal } from 'bootstrap';
|
||||
import { useForm } from 'vee-validate';
|
||||
|
||||
|
|
@ -73,7 +61,7 @@ export default {
|
|||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
name: 'modal',
|
||||
components: {
|
||||
modalButtonMain
|
||||
ButtonMain
|
||||
},
|
||||
props: {
|
||||
modalId: String,
|
||||
|
|
@ -86,13 +74,9 @@ export default {
|
|||
type: Function
|
||||
},
|
||||
isButtonDisabled: Boolean,
|
||||
useDefaultButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
additionalClassesString: {
|
||||
buttonVariant: {
|
||||
type: String,
|
||||
default: null
|
||||
default: 'success'
|
||||
}
|
||||
},
|
||||
emits: ['footer-button-event', 'isModalOpened'],
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@
|
|||
<buttonMain
|
||||
ref="buttonMain"
|
||||
class="w-100"
|
||||
isPrimary
|
||||
suppressLoader
|
||||
variant="success"
|
||||
:buttonText="ModalSelectButtonText"
|
||||
data-bs-dismiss="modal"
|
||||
@clickEvent="buttonClick" />
|
||||
|
|
|
|||
|
|
@ -7,19 +7,19 @@
|
|||
ref="continueModal"
|
||||
:headerText="modalHeaderText"
|
||||
:footerButtonText="modalFooterText"
|
||||
buttonVariant="primary"
|
||||
@isModalOpened="setModalStatus"
|
||||
@footerButtonEvent="startNewReferral">
|
||||
<p class="mb-2 subheader-text text-center">
|
||||
{{ modalSubHeaderText }}
|
||||
</p>
|
||||
<button
|
||||
<buttonMain
|
||||
id="btnContinueReferral"
|
||||
type="button"
|
||||
class="btn btn-white-blue continue-referral
|
||||
align-items-center justify-content-center d-inline-flex mt-2 py-3 px-4 delay w-100"
|
||||
variant="success"
|
||||
class="mt-2 w-100"
|
||||
:buttonText="modalBodyText"
|
||||
@click="continueReferral">
|
||||
{{ modalBodyText }}
|
||||
</button>
|
||||
</buttonMain>
|
||||
</modal>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -28,10 +28,12 @@
|
|||
<script>
|
||||
import modal from '@/digital-components/modal/modal.vue';
|
||||
import { getISSCookie } from '@/helpers/cookie-helper.js';
|
||||
import ButtonMain from '@/ux-components/button-main/button-main.vue';
|
||||
|
||||
export default {
|
||||
name: 'continue-modal',
|
||||
components: {
|
||||
ButtonMain,
|
||||
modal
|
||||
},
|
||||
emits: ['continue-previous-referral', 'start-new-referral'],
|
||||
|
|
@ -80,16 +82,5 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn-white-blue {
|
||||
border-radius: 0.5rem;
|
||||
border-color: $blue;
|
||||
color: $blue;
|
||||
font-size: 1rem;
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: 1.5rem;
|
||||
background-color: #ffffff;
|
||||
|
||||
--bs-btn-focus-shadow-rgb: 218, 72, 62;
|
||||
--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<buttonMain
|
||||
v-if="!isForwardButtonHidden"
|
||||
ref="buttonMain"
|
||||
isPrimary
|
||||
variant="navigation"
|
||||
:buttonText="buttonText"
|
||||
:class="
|
||||
(disableForwardAction || isForwardActionDisabled) &&
|
||||
|
|
@ -136,7 +136,7 @@ export default {
|
|||
width: auto;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.btn-primary {
|
||||
.btn-navigation {
|
||||
width: auto;
|
||||
}
|
||||
a {
|
||||
|
|
@ -149,7 +149,7 @@ export default {
|
|||
overflow-x: visible; // needed to fix hidden footer on some iphones
|
||||
}
|
||||
div.flex-column {
|
||||
.btn-primary {
|
||||
.btn-navigation {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,20 +8,17 @@
|
|||
ref="cancelClaimModal"
|
||||
:headerText="modalHeaderText"
|
||||
:footerButtonText="modalFooterText"
|
||||
additionalClassesString="navigation-link"
|
||||
:useDefaultButton="false"
|
||||
buttonVariant="link"
|
||||
@isModalOpened="setModalStatus"
|
||||
@footerButtonEvent="cancelClaimConfirmation">
|
||||
<div v-html="modalBodyText"></div>
|
||||
<button
|
||||
<buttonMain
|
||||
id="btnContinueReferral"
|
||||
type="button"
|
||||
:aria-disabled="false"
|
||||
class="btn btn-primary btn-override
|
||||
align-items-center justify-content-center d-inline-flex mt-4 py-3 px-4 delay w-100"
|
||||
@click="returnToClaim">
|
||||
{{ modalBodyText2 }}
|
||||
</button>
|
||||
variant="success"
|
||||
:buttonText="modalBodyText2"
|
||||
class="mt-4 w-100"
|
||||
@clickEvent="returnToClaim">
|
||||
</buttonMain>
|
||||
</modal>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -29,10 +26,12 @@
|
|||
|
||||
<script>
|
||||
import modal from '@/digital-components/modal/modal.vue';
|
||||
import ButtonMain from '@/ux-components/button-main/button-main.vue';
|
||||
|
||||
export default {
|
||||
name: 'cancel-claim-modal',
|
||||
components: {
|
||||
ButtonMain,
|
||||
modal
|
||||
},
|
||||
emits: ['cancel-claim-confirmation', 'return-to-claim'],
|
||||
|
|
@ -76,19 +75,5 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.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: $font-weight-bold;
|
||||
letter-spacing: inherit;
|
||||
@media (hover: hover) {
|
||||
background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
expect(mainButton.exists()).toBeTruthy();
|
||||
expect(mainButton.props().isPrimary).toBe(true);
|
||||
expect(mainButton.props().variant).toBe('success');
|
||||
expect(mainButton.classes()).toContain('w-100');
|
||||
expect(mainButton.classes()).toContain('mb-5');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
class="mb-4 small text-color--darker-gray" />
|
||||
<buttonMain
|
||||
ref="buttonMainOne"
|
||||
isPrimary
|
||||
variant="success"
|
||||
:buttonText="forwardButtonText"
|
||||
class="w-100 mb-5"
|
||||
@clickEvent="forwardButtonAction" />
|
||||
|
|
|
|||
|
|
@ -86,52 +86,14 @@
|
|||
.btn-link {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-open {
|
||||
.modal {
|
||||
.modal-body {
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
.btn:not(.navigation-link) {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&.btn-override {
|
||||
@include heritage-btn-variant('success', $button-text-color, $button-color, transparent, true);
|
||||
@include heritage-btn-variant('navigation', $button-text-color, $button-color, transparent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Amica
|
||||
|
|
@ -171,52 +133,14 @@
|
|||
a.new-window-link {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-open {
|
||||
.modal {
|
||||
.modal-body {
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
.btn:not(.navigation-link) {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&.btn-override {
|
||||
@include heritage-btn-variant('success', $button-text-color, $button-color, transparent, true);
|
||||
@include heritage-btn-variant('navigation', $button-text-color, $button-color, transparent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Nationwide
|
||||
|
|
@ -256,52 +180,14 @@
|
|||
a.new-window-link {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-open {
|
||||
.modal {
|
||||
.modal-body {
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
.btn:not(.navigation-link) {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&.btn-override {
|
||||
@include heritage-btn-variant('success', $button-text-color, $button-color, transparent, true);
|
||||
@include heritage-btn-variant('navigation', $button-text-color, $button-color, transparent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Country Financial
|
||||
|
|
@ -341,52 +227,14 @@
|
|||
a.new-window-link {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.modal-open {
|
||||
.modal {
|
||||
.modal-body {
|
||||
.btn {
|
||||
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
|
||||
&.btn-primary {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
.btn:not(.navigation-link) {
|
||||
background: $button-color;
|
||||
color: $button-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&.btn-override {
|
||||
@include heritage-btn-variant('success', $button-text-color, $button-color, transparent, true);
|
||||
@include heritage-btn-variant('navigation', $button-text-color, $button-color, transparent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End Travelers
|
||||
|
|
@ -182,4 +182,50 @@ body {
|
|||
|
||||
:root {
|
||||
--iss-loader-color: white;
|
||||
}
|
||||
|
||||
//Button Styles
|
||||
$heritage-btn-border-radius: 1.40625rem; // 22.5px
|
||||
$heritage-btn-height: 2.8125rem; // 45px
|
||||
$heritage-btn-width: 9.0625rem; // 145px
|
||||
|
||||
.btn {
|
||||
position: relative;
|
||||
--bs-btn-font-weight: #{$font-weight-bolder};
|
||||
min-height: $heritage-btn-height;
|
||||
min-width: $heritage-btn-width;
|
||||
letter-spacing: inherit;
|
||||
line-height: .94;
|
||||
|
||||
@include heritage-btn-variant('primary', $white, $heritage-blue-primary, transparent, true);
|
||||
@include heritage-btn-variant('success', $white, $green, transparent, true);
|
||||
@include heritage-btn-variant('navigation', $white, $green, transparent, true);
|
||||
@include heritage-btn-variant('secondary', $white, $heritage-blue-secondary, transparent, true);
|
||||
@include heritage-btn-link('link', $blue, transparent, $heritage-blue-secondary);
|
||||
|
||||
@include heritage-btn-size('lg', 0.625rem, 1.25rem, 20px, $heritage-btn-border-radius);
|
||||
@include heritage-btn-size('md', 7px, 15px, 15px, $heritage-btn-border-radius);
|
||||
@include heritage-btn-size('sm', 3px, 6px, 12px, $heritage-btn-border-radius);
|
||||
@include heritage-btn-size('xs', 1px, 5px, 12px, $heritage-btn-border-radius);
|
||||
|
||||
&.btn-link {
|
||||
--bs-btn-padding-x: 0px;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&[disabled],
|
||||
fieldset[disabled] {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.delay {
|
||||
// fixes flicker while transitioning between states
|
||||
transition: background 0s 0s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,3 +8,54 @@
|
|||
@mixin box-shadow-hover($color) {
|
||||
box-shadow: 0 0 0 4px $color;
|
||||
}
|
||||
|
||||
@mixin heritage-btn-box-shadow($color) {
|
||||
box-shadow:0 0 0 3px $white,0 0 0 5.5px $color
|
||||
}
|
||||
|
||||
@mixin heritage-btn-variant($name, $color, $background, $border-color, $box-shadow) {
|
||||
&.btn-#{$name} {
|
||||
@include button-variant($background,
|
||||
$border-color,
|
||||
$color,
|
||||
#{darken($background, 10%)},
|
||||
$border-color,
|
||||
$color,
|
||||
$background,
|
||||
$border-color,
|
||||
$color,
|
||||
$background,
|
||||
$border-color,
|
||||
$color
|
||||
);
|
||||
@if($box-shadow) {
|
||||
&:focus, &:active, &:active:focus {
|
||||
@include heritage-btn-box-shadow($background);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-outline-#{$name} {
|
||||
@include button-outline-variant($background,
|
||||
$color,
|
||||
$background,
|
||||
$color,
|
||||
$background
|
||||
$color,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin heritage-btn-size($size, $y-padding, $x-padding, $font-size, $border-radius) {
|
||||
&.btn-#{$size} {
|
||||
@include button-size($y-padding, $x-padding, $font-size, $border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin heritage-btn-link($name, $color, $background, $hover-color) {
|
||||
&.btn-#{$name} {
|
||||
--bs-btn-color: #{$color};
|
||||
--bs-btn-bg: #{$background};
|
||||
--bs-btn-hover-color: #{$hover-color};
|
||||
--bs-btn-active-color: #{$hover-color};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
|
||||
/** @ignore */
|
||||
function setupMocks(mountOptionsMockData = {}) {
|
||||
|
|
@ -12,13 +13,75 @@ function setupMocks(mountOptionsMockData = {}) {
|
|||
}
|
||||
|
||||
describe('buttonMain.vue', () => {
|
||||
it('Should return btn-primary class', async () => {
|
||||
describe.each([...Object.keys(buttonVariants)])('Button Variants', (variant) => {
|
||||
test(`Should return btn-${variant} class`, () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
variant
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
|
||||
// Expect
|
||||
expect(button.attributes('class')).toContain(`btn-${variant}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe.each([...Object.keys(buttonVariants)])('Button Outline Variants', (variant) => {
|
||||
test(`Should return btn-outline-${variant} class`, () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
variant,
|
||||
isOutline: true
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
|
||||
// Expect
|
||||
expect(button.attributes('class')).toContain(`btn-outline-${variant}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(['', 'sm', 'lg'])('Button Sizes', (size) => {
|
||||
test(`Should return btn-${size} class`, () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
size
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
|
||||
// Expect
|
||||
expect(button.attributes('class')).toContain(`btn-${size}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should return button text', async () => {
|
||||
// Act
|
||||
const buttonText = 'Test Text';
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
isPrimary: true
|
||||
buttonText
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
@ -27,10 +90,10 @@ describe('buttonMain.vue', () => {
|
|||
const button = wrapper.find('button');
|
||||
|
||||
// Expect
|
||||
expect(button.attributes('class')).toContain('btn-primary');
|
||||
expect(button.text()).toContain(buttonText);
|
||||
});
|
||||
|
||||
it('Should return aria-disabled state', async () => {
|
||||
it('Should return disabled state', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
|
|
@ -47,4 +110,85 @@ describe('buttonMain.vue', () => {
|
|||
// Expect
|
||||
expect(button.attributes()['aria-disabled']).toEqual('true');
|
||||
});
|
||||
|
||||
it('Should emit click-event', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
isDisabled: false
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
await button.trigger('click');
|
||||
|
||||
// Expect
|
||||
expect(wrapper.emitted('click').length).toBe(1);
|
||||
});
|
||||
|
||||
it('Should not emit click-event when disabled', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
isDisabled: true
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
await button.trigger('click');
|
||||
|
||||
// Expect
|
||||
expect(wrapper.emitted('click').length).toBe(1);
|
||||
});
|
||||
|
||||
it('Should emit GA event when clicked', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
pushToGA: true
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const spy = jest.spyOn(wrapper.vm, 'pushEventToGA');
|
||||
|
||||
// Assert
|
||||
|
||||
const button = wrapper.find('button');
|
||||
await button.trigger('click');
|
||||
|
||||
// Expect
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should not emit GA event when clicked', async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(
|
||||
buttonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
pushToGA: false
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const spy = jest.spyOn(wrapper.vm, 'pushEventToGA');
|
||||
|
||||
// Assert
|
||||
const button = wrapper.find('button');
|
||||
await button.trigger('click');
|
||||
|
||||
// Expect
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,30 +1,49 @@
|
|||
<template>
|
||||
<button
|
||||
:aria-disabled="isDisabled"
|
||||
class="btn d-flex btn-override align-items-center justify-content-center py-3 px-4 delay"
|
||||
:class="[
|
||||
isPrimary ? 'btn-primary' : 'btn-secondary',
|
||||
isFloat ? 'float-end' : '',
|
||||
]"
|
||||
class="btn d-flex align-items-center justify-content-center delay"
|
||||
:class="[getVariant, `btn-${size}`, canOverride ? 'btn-override' : '']"
|
||||
@click="clicked">
|
||||
<span class="m-0">{{ buttonText }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import buttonSizes from '@/constants/button-sizes';
|
||||
|
||||
export default {
|
||||
name: 'button-main',
|
||||
props: {
|
||||
isPrimary: Boolean,
|
||||
variant: { type: String, default: 'primary', validator: (val) => Object.keys(buttonVariants).includes(val) },
|
||||
size: { type: String, default: 'md', validator: (val) => Object.keys(buttonSizes).includes(val) },
|
||||
buttonText: String,
|
||||
isDisabled: Boolean,
|
||||
loaderPosition: String,
|
||||
isFloat: Boolean,
|
||||
suppressLoader: Boolean
|
||||
isOutline: Boolean,
|
||||
pushToGA: Boolean,
|
||||
canOverride: { type: Boolean, required: false, default: true }
|
||||
},
|
||||
emits: ['click-event'],
|
||||
computed: {
|
||||
getVariant() {
|
||||
if (this.isOutline) {
|
||||
return `btn-outline-${this.variant}`;
|
||||
}
|
||||
|
||||
return `btn-${this.variant}`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clicked() {
|
||||
if (this.pushToGA) {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.GaActions.CLICKED,
|
||||
this.buttonText,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.isDisabled) {
|
||||
this.$emit('click-event');
|
||||
}
|
||||
|
|
@ -34,86 +53,5 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$border-radius-heritage: 1.40625rem; // 22.5px
|
||||
$button-height-heritage: 2.8125rem; // 45px
|
||||
$button-width-heritage: 9.0625rem; // 145px
|
||||
|
||||
.btn {
|
||||
&.btn-primary {
|
||||
position: relative;
|
||||
background: #0c7e47;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
min-height: $button-height-heritage;
|
||||
min-width: $button-width-heritage;
|
||||
border: none;
|
||||
border-radius: $border-radius-heritage;
|
||||
color: $white;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
letter-spacing: inherit;
|
||||
&:focus {
|
||||
// Keyboard focus for accessibility
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px #fff, 0 0 0 5.5px #0c7e47;
|
||||
}
|
||||
&:hover {
|
||||
// Keyboard focus for accessibility
|
||||
color: #fff;
|
||||
background-color: #084f2d;
|
||||
border-color: #042f1a;
|
||||
}
|
||||
&:active {
|
||||
outline: none;
|
||||
background-color: #0c7e47;
|
||||
box-shadow: 0 0 0 3px #fff, 0 0 0 5.5px #0c7e47;
|
||||
}
|
||||
&:disabled {
|
||||
background: red;
|
||||
color: $gray-600 !important;
|
||||
border: none;
|
||||
border-radius: $border-radius-heritage;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
&.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-heritage;
|
||||
color: $blue;
|
||||
font-weight: 500;
|
||||
transition: all 150ms linear;
|
||||
&: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;
|
||||
border: 1px solid $gray-550;
|
||||
border-radius: $border-radius-heritage;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
&.delay {
|
||||
// fixes flicker while transitioning between states
|
||||
transition: background 0s 0s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { nextTick } from 'vue';
|
||||
import modalButtonMain from '@/ux-components/modal-button-main/modal-button-main.vue';
|
||||
|
||||
/** @ignore */
|
||||
function setupMocks(mountOptionsMockData = {}) {
|
||||
const defaultMountOptions = { route: { query: { issPage: 'page-name' } } };
|
||||
const baseMountOptions = getMountOptions(Object.assign(defaultMountOptions, mountOptionsMockData));
|
||||
const allMountOptions = Object.assign(defaultMountOptions, baseMountOptions);
|
||||
|
||||
return allMountOptions;
|
||||
}
|
||||
|
||||
describe('modal-button-main.vue', () => {
|
||||
it('Should return btn-primary class', () => {
|
||||
// Arrange/Act
|
||||
const wrapper = shallowMount(
|
||||
modalButtonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
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(
|
||||
modalButtonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
isDisabled: true
|
||||
}
|
||||
})
|
||||
);
|
||||
const button = wrapper.find('button');
|
||||
|
||||
// Assert
|
||||
expect(button.attributes()['aria-disabled']).toEqual('true');
|
||||
});
|
||||
|
||||
it("Should emit 'click-event' event when clicking if the button is enabled", async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(
|
||||
modalButtonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
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(
|
||||
modalButtonMain,
|
||||
setupMocks({
|
||||
propsData: {
|
||||
loaderPosition: 'right',
|
||||
loaderEnabled: true,
|
||||
isDisabled: true
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const buttonElement = wrapper.find('button');
|
||||
|
||||
// Act
|
||||
buttonElement.trigger('click');
|
||||
|
||||
await nextTick();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted('click-event')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<template>
|
||||
<button
|
||||
type="button"
|
||||
:aria-disabled="isDisabled"
|
||||
class="btn d-flex btn-override align-items-center justify-content-center py-3 px-4 delay"
|
||||
:class="[
|
||||
isPrimary ? 'btn-primary' : 'btn-secondary',
|
||||
isFloat ? 'float-end' : '',
|
||||
]"
|
||||
@click="clicked">
|
||||
<span class="m-0">{{ buttonText }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'modal-button-main',
|
||||
props: {
|
||||
isPrimary: Boolean,
|
||||
buttonText: String,
|
||||
isDisabled: Boolean,
|
||||
loaderColor: String,
|
||||
loaderPosition: String,
|
||||
isFloat: Boolean,
|
||||
suppressLoader: Boolean
|
||||
},
|
||||
emits: ['click-event'],
|
||||
methods: {
|
||||
clicked() {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.GaActions.CLICKED,
|
||||
this.buttonText,
|
||||
true
|
||||
);
|
||||
if (!this.isDisabled) {
|
||||
this.$emit('click-event');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.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;
|
||||
letter-spacing: inherit;
|
||||
@media (hover: hover) {
|
||||
background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
&.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;
|
||||
}
|
||||
&.delay {
|
||||
// fixes flicker while transitioning between states
|
||||
transition: background 0s 0s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue