Skip to content
This repository was archived by the owner on Jul 19, 2019. It is now read-only.

Commit 559eda4

Browse files
committed
feat(loading): add component loading
1 parent 2cb103f commit 559eda4

File tree

14 files changed

+646
-1
lines changed

14 files changed

+646
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"@nuxtjs/pwa": "^3.0.0-beta.12",
7171
"@vue/test-utils": "^1.0.0-beta.29",
7272
"autoprefixer": "^9.5.0",
73+
"babel-core": "^7.0.0-bridge.0",
7374
"babel-eslint": "^10.0.1",
7475
"babel-jest": "^24.7.0",
7576
"clean-css-cli": "^4.2.1",

src/_variables.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,10 @@
66
// Avatar
77

88
$avatar-size: 2.5rem !default;
9+
10+
// Loading
11+
12+
$loading-padding-y: 1rem !default;
13+
$loading-padding-x: 0 !default;
14+
$loading-transition: $transition-fade !default;
15+
$loading-fixed-background-color: $white !default;

src/components/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
import Avatar from './avatar'
2+
import Loading from './loading'
23

3-
export { Avatar }
4+
export {
5+
Avatar,
6+
Loading
7+
}

src/components/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
@import "avatar/index";
2+
@import "loading/index";

src/components/loading/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Loading
2+
3+
> The `<b-loading>` component is display loading state icon. Default wrapper is the BootstrapVue [<b-spinner>](https://bootstrap-vue.js.org/docs/components/spinner) component.
4+
5+
```html
6+
<template>
7+
<div>
8+
<b-form-checkbox v-model="loading" switch>
9+
Switch Loading Status
10+
</b-form-checkbox>
11+
<div v-if="!loading" class="py-3">
12+
<h3>Loading</h3>
13+
<p>Loading can show the loading state icon.</p>
14+
</div>
15+
<b-loading :show="loading"></b-loading>
16+
</div>
17+
</template>
18+
19+
<script>
20+
export default {
21+
data() {
22+
return {
23+
loading: true
24+
}
25+
}
26+
}
27+
</script>
28+
29+
<!-- b-loading.vue -->
30+
```
31+
32+
## Loading contextual variations
33+
34+
Add any of the following variants via the `variant` prop to change the appearance of a `<b-loading>`:
35+
`primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, and `dark`. If no variant
36+
is specified `primary` will be used.
37+
38+
```html
39+
<template>
40+
<b-loading :show="true" variant="primary"></b-loading>
41+
<b-loading :show="true" variant="secondary"></b-loading>
42+
<b-loading :show="true" variant="success"></b-loading>
43+
<b-loading :show="true" variant="danger"></b-loading>
44+
<b-loading :show="true" variant="warning"></b-loading>
45+
<b-loading :show="true" variant="info"></b-loading>
46+
<b-loading :show="true" variant="light"></b-loading>
47+
<b-loading :show="true" variant="dark"></b-loading>
48+
</template>
49+
50+
<!-- b-loading-variations.vue -->
51+
```
52+
53+
## Loading type
54+
55+
Via the `type` prop to set loading type. [Bootstrap](https://bootstrap-vue.js.org) includes two types of spinners. The default spinner type is called `border` (spinning circle border), and the optional type `grow` (a throbber style indicator).
56+
57+
```html
58+
<template>
59+
<b-loading :show="true" type="grow"></b-loading>
60+
</template>
61+
62+
<!-- b-loading-type.vue -->
63+
```
64+
65+
## Loading size
66+
67+
Via the `size` prop to set size loading.
68+
69+
```html
70+
<template>
71+
<b-loading :show="true"></b-loading>
72+
<b-loading :show="true" small></b-loading>
73+
</template>
74+
75+
<!-- b-loading-size.vue -->
76+
```
77+
78+
## Fixed loading
79+
80+
Via the `fixed` prop to enable fixed loading.
81+
82+
```html
83+
<template>
84+
<div class="position-relative">
85+
<div class="p-3">
86+
<h3>Loading</h3>
87+
<p>Loading can show the loading state icon.</p>
88+
<button @click="startLoading" class="btn btn-primary">Start loading 2 seconds</button>
89+
</div>
90+
<b-loading :show="loading" fixed></b-loading>
91+
</div>
92+
</template>
93+
94+
<script>
95+
export default {
96+
data() {
97+
return {
98+
loading: false
99+
}
100+
},
101+
methods: {
102+
startLoading() {
103+
this.loading = true
104+
setTimeout(() => {
105+
this.loading = false
106+
}, 2000)
107+
}
108+
}
109+
}
110+
</script>
111+
112+
<!-- b-loading-fixed.vue -->
113+
```
114+
115+
## Fading loading
116+
117+
Use the `fade` prop to enable animation. By default loading are not animated.
118+
It is recommended to attach `fixed` prop when using.
119+
120+
```html
121+
<template>
122+
<div class="position-relative">
123+
<div class="p-3">
124+
<h3>Loading</h3>
125+
<p>Loading can show the loading state icon.</p>
126+
<button @click="startLoading" class="btn btn-primary">Start loading 2 seconds</button>
127+
</div>
128+
<b-loading :show="loading" fixed fade></b-loading>
129+
</div>
130+
</template>
131+
132+
<script>
133+
export default {
134+
data() {
135+
return {
136+
loading: false
137+
}
138+
},
139+
methods: {
140+
startLoading() {
141+
this.loading = true
142+
setTimeout(() => {
143+
this.loading = false
144+
}, 2000)
145+
}
146+
}
147+
}
148+
</script>
149+
150+
<!-- b-loading-fading.vue -->
151+
```
152+
153+
## Set global render loading content
154+
155+
Set global config render loading content use string.
156+
157+
```js
158+
Vue.use(Loading, {
159+
BLoading: {
160+
slot: 'Loading...'
161+
}
162+
})
163+
```
164+
165+
Or set Vue component.
166+
167+
```js
168+
import CustomLoadingComponent from './components/custom-loading.vue'
169+
170+
Vue.use(Loading, {
171+
BLoading: {
172+
slot: CustomLoadingComponent
173+
}
174+
})
175+
```

src/components/loading/_loading.scss

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Base style
2+
.loading {
3+
padding: $loading-padding-y $loading-padding-x;
4+
text-align: center;
5+
6+
&.fade-enter-active,
7+
&.fade-leave-active {
8+
transition: $loading-transition;
9+
}
10+
11+
&.fade-enter,
12+
&.fade-leave-to {
13+
opacity: 0;
14+
}
15+
}
16+
17+
// Fixed loading
18+
19+
.loading-fixed {
20+
position: absolute;
21+
top: 0;
22+
left: 0;
23+
width: 100%;
24+
height: 100%;
25+
background-color: $loading-fixed-background-color;
26+
display: flex;
27+
justify-content: center;
28+
align-items: center;
29+
padding: 0;
30+
}

src/components/loading/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import BLoading from './loading'
2+
import { installFactory } from '../../utils/plugins'
3+
4+
const components = {
5+
BLoading
6+
}
7+
8+
export default {
9+
install: installFactory({ components })
10+
}

src/components/loading/index.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "loading";

src/components/loading/loading.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { getComponentConfig } from '../../utils/config'
2+
import { requestAF } from '../../utils/dom'
3+
4+
const NAME = 'BLoading'
5+
6+
export default {
7+
name: NAME,
8+
model: {
9+
prop: 'show',
10+
event: 'input'
11+
},
12+
props: {
13+
variant: {
14+
type: String,
15+
default: () => getComponentConfig(NAME, 'variant')
16+
},
17+
show: {
18+
type: Boolean,
19+
default: false
20+
},
21+
type: {
22+
type: String,
23+
default: () => getComponentConfig(NAME, 'type')
24+
},
25+
small: {
26+
type: Boolean,
27+
default: false
28+
},
29+
fade: {
30+
type: Boolean,
31+
default: () => getComponentConfig(NAME, 'fade')
32+
},
33+
fixed: {
34+
type: Boolean,
35+
default: () => getComponentConfig(NAME, 'fixed')
36+
}
37+
},
38+
data() {
39+
return {
40+
showClass: this.fade && this.show
41+
}
42+
},
43+
watch: {
44+
show(val) {
45+
if (val) {
46+
this.$emit('started')
47+
} else {
48+
this.$emit('ended')
49+
}
50+
}
51+
},
52+
methods: {
53+
onBeforeEnter() {
54+
if (this.fade) {
55+
requestAF(() => {
56+
this.showClass = true
57+
})
58+
}
59+
},
60+
onBeforeLeave() {
61+
this.showClass = false
62+
}
63+
},
64+
render(h) {
65+
let $loading
66+
let $spinner
67+
const slot = getComponentConfig(NAME, 'slot')
68+
if (this.show) {
69+
if (this.$slots.default) {
70+
$spinner = this.$slots.default
71+
} else if (slot && typeof slot === 'string') {
72+
// slot is pure text
73+
// _v is createTextVNode method
74+
$spinner = this._v(slot)
75+
} else if (typeof slot === 'object') {
76+
// slot is Vue component
77+
$spinner = h(slot)
78+
} else {
79+
$spinner = h('b-spinner', {
80+
props: {
81+
type: this.type,
82+
label: 'Loading...',
83+
variant: this.variant || 'primary',
84+
small: this.small
85+
}
86+
})
87+
}
88+
89+
$loading = h(
90+
'div',
91+
{
92+
class: {
93+
loading: true,
94+
fade: this.fade,
95+
show: this.showClass,
96+
'loading-fixed': this.fixed
97+
}
98+
},
99+
[$spinner]
100+
)
101+
$loading = [$loading]
102+
}
103+
return h(
104+
'transition',
105+
{
106+
props: {
107+
'enter-class': '',
108+
'enter-active-class': '',
109+
'enter-to-class': '',
110+
'leave-class': 'show',
111+
'leave-active-class': '',
112+
'leave-to-class': ''
113+
},
114+
on: {
115+
beforeEnter: this.onBeforeEnter,
116+
beforeLeave: this.onBeforeLeave
117+
}
118+
},
119+
$loading
120+
)
121+
}
122+
}

0 commit comments

Comments
 (0)