diff --git a/src/constants/button-sizes.js b/src/constants/button-sizes.js new file mode 100644 index 00000000..d4f46ecc --- /dev/null +++ b/src/constants/button-sizes.js @@ -0,0 +1,8 @@ +const buttonSizes = Object.freeze({ + xs: 'xs', + sm: 'sm', + md: 'md', + lg: 'lg' +}); + +export default buttonSizes; diff --git a/src/constants/button-variants.js b/src/constants/button-variants.js new file mode 100644 index 00000000..cf73718a --- /dev/null +++ b/src/constants/button-variants.js @@ -0,0 +1,9 @@ +const buttonVariants = Object.freeze({ + primary: 'primary', + secondary: 'secondary', + success: 'success', + link: 'link', + navigation: 'navigation' +}); + +export default buttonVariants; diff --git a/src/digital-components/modal/modal.spec.js b/src/digital-components/modal/modal.spec.js index 4c130e08..fd05174d 100644 --- a/src/digital-components/modal/modal.spec.js +++ b/src/digital-components/modal/modal.spec.js @@ -81,7 +81,6 @@ describe('modal.vue', () => { validate: mockValidate(true) }); - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -89,7 +88,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Act const buttonMain = wrapper.findComponent({ ref: 'modalButtonMain' }); @@ -112,8 +110,6 @@ describe('modal.vue', () => { meta: mockMeta(fakeMeta), validate: mockValidate(false) }); - - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -121,7 +117,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Act const buttonMain = wrapper.findComponent({ ref: 'modalButtonMain' }); @@ -144,8 +139,6 @@ describe('modal.vue', () => { meta: mockMeta(fakeMeta), validate: mockValidate(true) }); - - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -153,7 +146,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Assert expect(wrapper.vm.isFooterButtonDisabled).toBe(true); @@ -172,8 +164,6 @@ describe('modal.vue', () => { meta: mockMeta(fakeMeta), validate: mockValidate(true) }); - - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -181,7 +171,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Assert expect(wrapper.vm.isFooterButtonDisabled).toBe(true); @@ -202,8 +191,6 @@ describe('modal.vue', () => { }); const showMock = jest.spyOn(Modal.prototype, 'show'); - - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -211,7 +198,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Act wrapper.vm.openModal(); @@ -234,8 +220,6 @@ describe('modal.vue', () => { validate: mockValidate(true) }); const hideMock = jest.spyOn(Modal.prototype, 'hide'); - - const resetButtonStyle = jest.fn(); const wrapper = shallowMount(modal, { props: { footerButtonText, @@ -243,7 +227,6 @@ describe('modal.vue', () => { }, attachTo: document.body }); - wrapper.vm.resetButtonStyle = resetButtonStyle; // Act wrapper.vm.openModal(); diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue index 8a4664e7..1677aedd 100644 --- a/src/digital-components/modal/modal.vue +++ b/src/digital-components/modal/modal.vue @@ -11,7 +11,11 @@ 'hidden.bs.modal': onModalClosed, 'shown.bs.modal': onModalOpened }"> - @@ -65,7 +57,7 @@ diff --git a/src/iss-components/continue-modal/continue-modal.vue b/src/iss-components/continue-modal/continue-modal.vue index 15c0fbb2..1627e509 100644 --- a/src/iss-components/continue-modal/continue-modal.vue +++ b/src/iss-components/continue-modal/continue-modal.vue @@ -7,19 +7,19 @@ ref="continueModal" :headerText="modalHeaderText" :footerButtonText="modalFooterText" + buttonVariant="primary" @isModalOpened="setModalStatus" @footerButtonEvent="startNewReferral">

{{ modalSubHeaderText }}

- + variant="success" + class="mt-2 w-100" + :buttonText="modalBodyText" + @click-event="continueReferral"> + @@ -28,10 +28,12 @@ diff --git a/src/iss-components/site-footer/site-footer.vue b/src/iss-components/site-footer/site-footer.vue index 81cb42f6..b73ab67a 100644 --- a/src/iss-components/site-footer/site-footer.vue +++ b/src/iss-components/site-footer/site-footer.vue @@ -16,7 +16,7 @@
- + variant="success" + :buttonText="modalBodyText2" + class="mt-4 w-100" + @clickEvent="returnToClaim"> +
@@ -29,10 +26,12 @@ diff --git a/src/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue b/src/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue index cc427f09..5f811333 100644 --- a/src/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue +++ b/src/layouts/policy-vehicles/policy-vehicles-question/policy-vehicles-question.vue @@ -2,7 +2,6 @@
+ + :validationRules="rules.optionRequired" + class="mb-2"/> + ({ jest.mock('@/digital-components/modal/modal', () => ({ methods: { - closeModal: jest.fn(), - resetButtonStyle: jest.fn() + closeModal: jest.fn() } })); diff --git a/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue b/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue index c0cd4da3..9202fa0b 100644 --- a/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue +++ b/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue @@ -15,6 +15,7 @@ :onModalOpenedCallback="onModalOpened" :onModalClosedCallback="onModalClosed" :footerButtonText="modalFooterText" + :modalPosition="'center'" @footerButtonEvent="setZipCode"> { // 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'); }); diff --git a/src/layouts/tpa-submit/tpa-submit.vue b/src/layouts/tpa-submit/tpa-submit.vue index 5b3b223a..181fa0aa 100644 --- a/src/layouts/tpa-submit/tpa-submit.vue +++ b/src/layouts/tpa-submit/tpa-submit.vue @@ -32,7 +32,7 @@ class="mb-4 small text-color--darker-gray" /> diff --git a/src/styles/client-customizations.scss b/src/styles/client-customizations.scss index 26beae9f..487a63ae 100644 --- a/src/styles/client-customizations.scss +++ b/src/styles/client-customizations.scss @@ -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 \ No newline at end of file diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss index 01208d7f..d60114d6 100644 --- a/src/styles/common-styles.scss +++ b/src/styles/common-styles.scss @@ -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: 600; + 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); + @include heritage-btn-size('md', 7px, 15px); + @include heritage-btn-size('sm', 3px, 6px); + @include heritage-btn-size('xs', 1px, 5px); + + &.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; + } } \ No newline at end of file diff --git a/src/styles/mixins/customMixins.scss b/src/styles/mixins/customMixins.scss index cd3555cc..80cf5b8c 100644 --- a/src/styles/mixins/customMixins.scss +++ b/src/styles/mixins/customMixins.scss @@ -8,3 +8,53 @@ @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 + ); + } +} + +@mixin heritage-btn-size($size, $y-padding, $x-padding) { + &.btn-#{$size} { + @include button-size($y-padding, $x-padding, $font-size-base, $heritage-btn-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}; + } +} \ No newline at end of file diff --git a/src/styles/shared-input-button-styles.scss b/src/styles/shared-input-button-styles.scss index 9af066bb..1179dd6b 100644 --- a/src/styles/shared-input-button-styles.scss +++ b/src/styles/shared-input-button-styles.scss @@ -5,7 +5,7 @@ &.list-button, &.list-button-horizontal, &.list-card { - &:not(.selected) { + &:not(.selected):not(.no-hover) { position: relative; z-index: 5; @include box-shadow-hover($blue-300); diff --git a/src/styles/ux-variables.scss b/src/styles/ux-variables.scss index d34f8d8b..41cd8269 100644 --- a/src/styles/ux-variables.scss +++ b/src/styles/ux-variables.scss @@ -216,4 +216,8 @@ $enable-important-utilities: false; $letter-spacing-primary: 0.03em; // Borders $border-input: 1px solid rgba(179, 180, 181); -$border-input-focus: 2.5px solid $blue; \ No newline at end of file +$border-input-focus: 2.5px solid $blue; + +//Heritage +$heritage-blue-primary: #0070D1; +$heritage-blue-secondary: #167cac; \ No newline at end of file diff --git a/src/ux-components/button-main/button-main.spec.js b/src/ux-components/button-main/button-main.spec.js index 95664421..e0c8a993 100644 --- a/src/ux-components/button-main/button-main.spec.js +++ b/src/ux-components/button-main/button-main.spec.js @@ -1,6 +1,8 @@ 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'; +import buttonSizes from '@/constants/button-sizes'; /** @ignore */ function setupMocks(mountOptionsMockData = {}) { @@ -12,13 +14,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([...Object.keys(buttonSizes)])('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 +91,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 +111,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-event').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-event')).toBeUndefined(); + }); + + 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(); + }); }); diff --git a/src/ux-components/button-main/button-main.vue b/src/ux-components/button-main/button-main.vue index 6000a9f2..cf5f03e7 100644 --- a/src/ux-components/button-main/button-main.vue +++ b/src/ux-components/button-main/button-main.vue @@ -1,31 +1,50 @@ diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 88afc125..47bf1f1b 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -2,7 +2,7 @@ + buttonWrapperClasses="list-group base-input-button list-button no-hover d-flex flex-column w-100 mb-2">
@@ -67,6 +67,12 @@ export default {