diff options
author | Winnie Hellmann <winnie@gitlab.com> | 2018-02-16 11:30:55 +0100 |
---|---|---|
committer | Winnie Hellmann <winnie@gitlab.com> | 2018-02-19 21:04:22 +0100 |
commit | 2ec44372ebaaa2a5544f28ecfbe41f62093becf7 (patch) | |
tree | afc31e092976232f138f3872a9c4b69f677950b9 | |
parent | 0b032daa11d5ea140f2eea99fa10b21da4b50f0b (diff) | |
download | gitlab-ce-winh-more-modal-components.tar.gz |
Add secondary button to gl-modal componentwinh-more-modal-components
-rw-r--r-- | app/assets/javascripts/vue_shared/components/gl_modal.vue | 56 | ||||
-rw-r--r-- | app/assets/javascripts/vue_shared/components/modal_button.vue | 32 | ||||
-rw-r--r-- | changelogs/unreleased/winh-more-modal-components.yml | 5 | ||||
-rw-r--r-- | doc/development/fe_guide/components.md | 21 | ||||
-rw-r--r-- | doc/development/fe_guide/img/gl-modal-secondary.png | bin | 0 -> 30994 bytes | |||
-rw-r--r-- | spec/javascripts/vue_shared/components/gl_modal_spec.js | 54 |
6 files changed, 148 insertions, 20 deletions
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue index 67c9181c7b1..3520f984083 100644 --- a/app/assets/javascripts/vue_shared/components/gl_modal.vue +++ b/app/assets/javascripts/vue_shared/components/gl_modal.vue @@ -1,14 +1,13 @@ <script> - const buttonVariants = [ - 'danger', - 'primary', - 'success', - 'warning', - ]; + import ModalButton from './modal_button.vue'; export default { name: 'GlModal', + components: { + ModalButton, + }, + props: { id: { type: String, @@ -24,19 +23,37 @@ type: String, required: false, default: 'primary', - validator: value => buttonVariants.indexOf(value) !== -1, }, footerPrimaryButtonText: { type: String, required: false, default: '', }, + footerSecondaryButtonVariant: { + type: String, + required: false, + default: 'default', + }, + footerSecondaryButtonText: { + type: String, + required: false, + default: '', + }, + }, + + computed: { + hasSecondaryButton() { + return this.footerSecondaryButtonText && this.footerSecondaryButtonText !== ''; + }, }, methods: { emitCancel(event) { this.$emit('cancel', event); }, + emitSecondaryAction(event) { + this.$emit('secondaryAction', event); + }, emitSubmit(event) { this.$emit('submit', event); }, @@ -81,23 +98,22 @@ <div class="modal-footer"> <slot name="footer"> - <button - type="button" - class="btn" - data-dismiss="modal" - @click="emitCancel($event)" - > + <modal-button @click="emitCancel($event)"> {{ s__('Modal|Cancel') }} - </button> - <button - type="button" - class="btn" - :class="`btn-${footerPrimaryButtonVariant}`" - data-dismiss="modal" + </modal-button> + <modal-button + v-if="hasSecondaryButton" + :variant="footerSecondaryButtonVariant" + @click="emitSecondaryAction($event)" + > + {{ footerSecondaryButtonText }} + </modal-button> + <modal-button + :variant="footerPrimaryButtonVariant" @click="emitSubmit($event)" > {{ footerPrimaryButtonText }} - </button> + </modal-button> </slot> </div> </div> diff --git a/app/assets/javascripts/vue_shared/components/modal_button.vue b/app/assets/javascripts/vue_shared/components/modal_button.vue new file mode 100644 index 00000000000..f22e740d568 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/modal_button.vue @@ -0,0 +1,32 @@ +<script> + const buttonVariants = [ + 'danger', + 'default', + 'primary', + 'success', + 'warning', + ]; + + export default { + name: 'ModalButton', + + props: { + variant: { + type: String, + required: false, + default: 'default', + validator: value => buttonVariants.indexOf(value) !== -1, + }, + }, + }; +</script> + +<template> + <button + type="button" + class="btn" + :class="`btn-${variant}`" + data-dismiss="modal"> + <slot></slot> + </button> +</template> diff --git a/changelogs/unreleased/winh-more-modal-components.yml b/changelogs/unreleased/winh-more-modal-components.yml new file mode 100644 index 00000000000..8c1b6a8da62 --- /dev/null +++ b/changelogs/unreleased/winh-more-modal-components.yml @@ -0,0 +1,5 @@ +--- +title: Add secondary button to gl-modal component +merge_request: 17172 +author: +type: changed diff --git a/doc/development/fe_guide/components.md b/doc/development/fe_guide/components.md index 66a8abe42f7..255f92e8fbb 100644 --- a/doc/development/fe_guide/components.md +++ b/doc/development/fe_guide/components.md @@ -59,3 +59,24 @@ Here is an example of how to use it: ``` ![example modal](img/gl-modal.png) + +### Modals with secondary action + +You can also add a secondary button to modals: + +```html + <gl-modal + id="dogs-out-modal" + :header-title-text="s__('ModalExample|Let the dogs out?')" + footer-primary-button-variant="danger" + :footer-primary-button-text="s__('ModalExample|Let them out')" + footer-secondary-button-variant="success" + :footer-secondary-button-text="s__('ModalExample|Call Ghostbusters')" + @submit="letOut(theDogs)" + @secondaryAction="Ghostbusters.call()" + > + {{ s__('ModalExample|You’re about to let the dogs out.') }} + </gl-modal> +``` + +![example modal with secondary action](img/gl-modal-secondary.png) diff --git a/doc/development/fe_guide/img/gl-modal-secondary.png b/doc/development/fe_guide/img/gl-modal-secondary.png Binary files differnew file mode 100644 index 00000000000..e34309935ff --- /dev/null +++ b/doc/development/fe_guide/img/gl-modal-secondary.png diff --git a/spec/javascripts/vue_shared/components/gl_modal_spec.js b/spec/javascripts/vue_shared/components/gl_modal_spec.js index d6148cb785b..2b2115041c0 100644 --- a/spec/javascripts/vue_shared/components/gl_modal_spec.js +++ b/spec/javascripts/vue_shared/components/gl_modal_spec.js @@ -80,6 +80,52 @@ describe('GlModal', () => { expect(primaryButton.innerHTML.trim()).toBe(props.footerPrimaryButtonText); }); }); + + describe('with footerSecondaryButtonVariant', () => { + const props = { + footerSecondaryButtonText: 'something to make the button visible', + footerSecondaryButtonVariant: 'danger', + }; + + beforeEach(() => { + vm = mountComponent(modalComponent, props); + }); + + it('sets the secondary button class', () => { + const secondaryButton = vm.$el.querySelector('.modal-footer button:nth-of-type(2)'); + expect(secondaryButton.classList).toContain(`btn-${props.footerSecondaryButtonVariant}`); + }); + }); + + describe('with footerSecondaryButtonText', () => { + const props = { + footerSecondaryButtonText: 'my second button text', + }; + + beforeEach(() => { + vm = mountComponent(modalComponent, props); + }); + + it('sets the secondary button text', () => { + const secondaryButton = vm.$el.querySelector('.modal-footer button:nth-of-type(2)'); + expect(secondaryButton.innerHTML.trim()).toBe(props.footerSecondaryButtonText); + }); + }); + + describe('without footerSecondaryButtonText', () => { + const props = { + footerSecondaryButtonText: null, + }; + + beforeEach(() => { + vm = mountComponent(modalComponent, props); + }); + + it('does not render a secondary button', () => { + const buttons = vm.$el.querySelectorAll('.modal-footer button'); + expect(buttons.length).toBe(2); + }); + }); }); it('works with data-toggle="modal"', (done) => { @@ -114,6 +160,14 @@ describe('GlModal', () => { }); }); + describe('emitSecondaryAction', () => { + it('emits a secondaryAction event', () => { + vm.emitSecondaryAction(dummyEvent); + + expect(vm.$emit).toHaveBeenCalledWith('secondaryAction', dummyEvent); + }); + }); + describe('emitSubmit', () => { it('emits a submit event', () => { vm.emitSubmit(dummyEvent); |