Commit 89356357 authored by Diana Zubova's avatar Diana Zubova Committed by Miguel Rincon

Add transition between invite members modal

Smooth UX transition

EE: true
parent d94c5986
...@@ -131,10 +131,13 @@ export default { ...@@ -131,10 +131,13 @@ export default {
return this.glFeatures.overageMembersModal; return this.glFeatures.overageMembersModal;
}, },
modalInfo() { modalInfo() {
if (this.totalUserCount) {
const infoText = this.$options.i18n.infoText(this.subscriptionSeats); const infoText = this.$options.i18n.infoText(this.subscriptionSeats);
const infoWarning = this.$options.i18n.infoWarning(this.totalUserCount, this.name); const infoWarning = this.$options.i18n.infoWarning(this.totalUserCount, this.name);
return `${infoText} ${infoWarning}`; return `${infoText} ${infoWarning}`;
}
return '';
}, },
modalTitleLabel() { modalTitleLabel() {
return this.showOverageModal ? this.$options.i18n.OVERAGE_MODAL_TITLE : this.modalTitle; return this.showOverageModal ? this.$options.i18n.OVERAGE_MODAL_TITLE : this.modalTitle;
...@@ -243,7 +246,13 @@ export default { ...@@ -243,7 +246,13 @@ export default {
@close="reset" @close="reset"
@hide="reset" @hide="reset"
> >
<div v-show="!showOverageModal"> <div class="gl-display-grid">
<transition name="invite-modal-transition">
<div
v-show="!showOverageModal"
class="invite-modal-content"
data-testid="invite-modal-initial-content"
>
<div class="gl-display-flex" data-testid="modal-base-intro-text"> <div class="gl-display-flex" data-testid="modal-base-intro-text">
<slot name="intro-text-before"></slot> <slot name="intro-text-before"></slot>
<p> <p>
...@@ -320,12 +329,20 @@ export default { ...@@ -320,12 +329,20 @@ export default {
</div> </div>
<slot name="form-after"></slot> <slot name="form-after"></slot>
</div> </div>
<div v-if="showOverageModal"> </transition>
<transition name="invite-modal-transition">
<div
v-show="showOverageModal"
class="invite-modal-content"
data-testid="invite-modal-overage-content"
>
{{ modalInfo }} {{ modalInfo }}
<gl-link :href="$options.i18n.OVERAGE_MODAL_LINK" target="_blank">{{ <gl-link :href="$options.i18n.OVERAGE_MODAL_LINK" target="_blank">{{
$options.i18n.OVERAGE_MODAL_LINK_TEXT $options.i18n.OVERAGE_MODAL_LINK_TEXT
}}</gl-link> }}</gl-link>
</div> </div>
</transition>
</div>
<template #modal-footer> <template #modal-footer>
<template v-if="!showOverageModal"> <template v-if="!showOverageModal">
<gl-button data-testid="cancel-button" @click="closeModal"> <gl-button data-testid="cancel-button" @click="closeModal">
......
...@@ -42,3 +42,34 @@ ...@@ -42,3 +42,34 @@
svg g { fill: $gray-600; } svg g { fill: $gray-600; }
} }
} }
.invite-modal-content {
grid-row: 1;
grid-column: 1;
}
$max-invite-modal-height: 600px;
// Custom styles for invite-modal-transition
// Used by Vue Transition API
.invite-modal-transition-enter-active,
.invite-modal-transition-leave-active {
transition-property: max-height, opacity;
transition-timing-function: ease-in-out;
@include gl-transition-slow;
overflow: hidden;
}
.invite-modal-transition-enter,
.invite-modal-transition-leave-to {
max-height: 0;
opacity: 0;
}
.invite-modal-transition-enter-to,
.invite-modal-transition-leave {
max-height: px-to-rem($max-invite-modal-height);
}
...@@ -16,7 +16,6 @@ import { ...@@ -16,7 +16,6 @@ import {
OVERAGE_MODAL_CONTINUE_BUTTON, OVERAGE_MODAL_CONTINUE_BUTTON,
OVERAGE_MODAL_BACK_BUTTON, OVERAGE_MODAL_BACK_BUTTON,
} from 'ee/invite_members/constants'; } from 'ee/invite_members/constants';
import waitForPromises from 'helpers/wait_for_promises';
import { propsData } from 'jest/invite_members/mock_data/modal_base'; import { propsData } from 'jest/invite_members/mock_data/modal_base';
describe('InviteModalBase', () => { describe('InviteModalBase', () => {
...@@ -63,6 +62,8 @@ describe('InviteModalBase', () => { ...@@ -63,6 +62,8 @@ describe('InviteModalBase', () => {
const findInviteButton = () => wrapper.findByTestId('invite-button'); const findInviteButton = () => wrapper.findByTestId('invite-button');
const findBackButton = () => wrapper.findByTestId('overage-back-button'); const findBackButton = () => wrapper.findByTestId('overage-back-button');
const findOverageInviteButton = () => wrapper.findByTestId('invite-with-overage-button'); const findOverageInviteButton = () => wrapper.findByTestId('invite-with-overage-button');
const findInitialModalContent = () => wrapper.findByTestId('invite-modal-initial-content');
const findOverageModalContent = () => wrapper.findByTestId('invite-modal-overage-content');
const clickInviteButton = () => findInviteButton().vm.$emit('click'); const clickInviteButton = () => findInviteButton().vm.$emit('click');
const clickBackButton = () => findBackButton().vm.$emit('click'); const clickBackButton = () => findBackButton().vm.$emit('click');
...@@ -102,25 +103,23 @@ describe('InviteModalBase', () => { ...@@ -102,25 +103,23 @@ describe('InviteModalBase', () => {
}); });
}); });
describe('rendering the help link', () => {
it('renders the correct link', () => { it('renders the correct link', () => {
expect(findLink().attributes('href')).toBe(propsData.helpLink); expect(findLink().attributes('href')).toBe(propsData.helpLink);
}); });
});
describe('rendering the access expiration date field', () => {
it('renders the datepicker', () => { it('renders the datepicker', () => {
expect(findDatepicker().exists()).toBe(true); expect(findDatepicker().exists()).toBe(true);
}); });
it("doesn't show the overage content", () => {
expect(findOverageModalContent().isVisible()).toBe(false);
}); });
}); });
describe('displays overage modal', () => { describe('displays overage modal', () => {
beforeEach(async () => { beforeEach(() => {
createComponent({}, {}, { glFeatures: { overageMembersModal: true } }); createComponent({}, {}, { glFeatures: { overageMembersModal: true } });
clickInviteButton(); clickInviteButton();
await waitForPromises();
}); });
it('renders the modal with the correct title', () => { it('renders the modal with the correct title', () => {
...@@ -141,11 +140,21 @@ describe('InviteModalBase', () => { ...@@ -141,11 +140,21 @@ describe('InviteModalBase', () => {
); );
}); });
it('switches back to the intial modal', async () => { it('doesn\t show the initial modal content', () => {
clickBackButton(); expect(findInitialModalContent().isVisible()).toBe(false);
await waitForPromises(); });
describe('when switches back to the initial modal', () => {
beforeEach(() => clickBackButton());
it('shows the initial modal', () => {
expect(wrapper.findComponent(GlModal).props('title')).toBe('_modal_title_'); expect(wrapper.findComponent(GlModal).props('title')).toBe('_modal_title_');
expect(findInitialModalContent().isVisible()).toBe(true);
});
it("doesn't show the overage content", () => {
expect(findOverageModalContent().isVisible()).toBe(false);
});
}); });
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment