Commit 082e1835 authored by Eric Eastwood's avatar Eric Eastwood
parent a1c5e146
<script>
/* This is a re-usable vue component for rendering a button
that will probably be sending off ajax requests and need
to show the loading status by setting the `loading` option.
This can also be used for initial page load when you don't
know the action of the button yet by setting
`loading: true, label: undefined`.
Sample configuration:
<loading-button
:loading="true"
:label="Hello"
@click="..."
/>
*/
import loadingIcon from './loading_icon.vue';
export default {
props: {
loading: {
type: Boolean,
required: false,
default: false,
},
label: {
type: String,
required: false,
},
},
components: {
loadingIcon,
},
methods: {
onClick(e) {
this.$emit('click', e);
},
},
};
</script>
<template>
<button
class="btn btn-align-content"
@click="onClick"
type="button"
:disabled="loading"
>
<transition name="fade">
<loading-icon
v-if="loading"
:inline="true"
class="js-loading-button-icon"
:class="{
'append-right-5': label
}"
/>
</transition>
<transition name="fade">
<span
v-if="label"
class="js-loading-button-label"
>
{{ label }}
</span>
</transition>
</button>
</template>
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
@import 'framework/tw_bootstrap'; @import 'framework/tw_bootstrap';
@import "framework/layout"; @import "framework/layout";
@import "framework/animations"; @import "framework/animations";
@import "framework/vue_transitions";
@import "framework/avatar"; @import "framework/avatar";
@import "framework/asciidoctor"; @import "framework/asciidoctor";
@import "framework/banner"; @import "framework/banner";
......
...@@ -296,6 +296,11 @@ ...@@ -296,6 +296,11 @@
} }
} }
.btn-align-content {
display: flex;
align-items: center;
}
.btn-group { .btn-group {
&.btn-grouped { &.btn-grouped {
@include btn-with-margin; @include btn-with-margin;
......
.fade-enter-active,
.fade-leave-active {
transition: opacity $sidebar-transition-duration $general-hover-transition-curve;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity $sidebar-transition-duration;
}
.monaco-loader { .monaco-loader {
position: absolute; position: absolute;
top: 0; top: 0;
......
---
title: Add loading button for new UX paradigm
merge_request: 14883
author:
type: added
import Vue from 'vue';
import loadingButton from '~/vue_shared/components/loading_button.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
const LABEL = 'Hello';
describe('LoadingButton', function () {
let vm;
let LoadingButton;
beforeEach(() => {
LoadingButton = Vue.extend(loadingButton);
});
afterEach(() => {
vm.$destroy();
});
describe('loading spinner', () => {
it('shown when loading', () => {
vm = mountComponent(LoadingButton, {
loading: true,
});
expect(vm.$el.querySelector('.js-loading-button-icon')).toBeDefined();
});
});
describe('disabled state', () => {
it('disabled when loading', () => {
vm = mountComponent(LoadingButton, {
loading: true,
});
expect(vm.$el.disabled).toEqual(true);
});
it('not disabled when normal', () => {
vm = mountComponent(LoadingButton, {
loading: false,
});
expect(vm.$el.disabled).toEqual(false);
});
});
describe('label', () => {
it('shown when normal', () => {
vm = mountComponent(LoadingButton, {
loading: false,
label: LABEL,
});
const label = vm.$el.querySelector('.js-loading-button-label');
expect(label.textContent.trim()).toEqual(LABEL);
});
it('shown when loading', () => {
vm = mountComponent(LoadingButton, {
loading: true,
label: LABEL,
});
const label = vm.$el.querySelector('.js-loading-button-label');
expect(label.textContent.trim()).toEqual(LABEL);
});
});
describe('click callback prop', () => {
it('calls given callback when normal', () => {
vm = mountComponent(LoadingButton, {
loading: false,
});
spyOn(vm, '$emit');
vm.$el.click();
expect(vm.$emit).toHaveBeenCalledWith('click', jasmine.any(Object));
});
it('does not call given callback when disabled because of loading', () => {
vm = mountComponent(LoadingButton, {
loading: true,
indeterminate: true,
});
spyOn(vm, '$emit');
vm.$el.click();
expect(vm.$emit).not.toHaveBeenCalled();
});
});
});
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