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

Commit

Permalink
feat(loading): add component loading
Browse files Browse the repository at this point in the history
  • Loading branch information
ycs77 committed Apr 11, 2019
1 parent 2cb103f commit 559eda4
Show file tree
Hide file tree
Showing 14 changed files with 646 additions and 1 deletion.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -70,6 +70,7 @@
"@nuxtjs/pwa": "^3.0.0-beta.12",
"@vue/test-utils": "^1.0.0-beta.29",
"autoprefixer": "^9.5.0",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.7.0",
"clean-css-cli": "^4.2.1",
Expand Down
7 changes: 7 additions & 0 deletions src/_variables.scss
Expand Up @@ -6,3 +6,10 @@
// Avatar

$avatar-size: 2.5rem !default;

// Loading

$loading-padding-y: 1rem !default;
$loading-padding-x: 0 !default;
$loading-transition: $transition-fade !default;
$loading-fixed-background-color: $white !default;
6 changes: 5 additions & 1 deletion src/components/index.js
@@ -1,3 +1,7 @@
import Avatar from './avatar'
import Loading from './loading'

export { Avatar }
export {
Avatar,
Loading
}
1 change: 1 addition & 0 deletions src/components/index.scss
@@ -1 +1,2 @@
@import "avatar/index";
@import "loading/index";
175 changes: 175 additions & 0 deletions src/components/loading/README.md
@@ -0,0 +1,175 @@
# Loading

> 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.
```html
<template>
<div>
<b-form-checkbox v-model="loading" switch>
Switch Loading Status
</b-form-checkbox>
<div v-if="!loading" class="py-3">
<h3>Loading</h3>
<p>Loading can show the loading state icon.</p>
</div>
<b-loading :show="loading"></b-loading>
</div>
</template>

<script>
export default {
data() {
return {
loading: true
}
}
}
</script>

<!-- b-loading.vue -->
```

## Loading contextual variations

Add any of the following variants via the `variant` prop to change the appearance of a `<b-loading>`:
`primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, and `dark`. If no variant
is specified `primary` will be used.

```html
<template>
<b-loading :show="true" variant="primary"></b-loading>
<b-loading :show="true" variant="secondary"></b-loading>
<b-loading :show="true" variant="success"></b-loading>
<b-loading :show="true" variant="danger"></b-loading>
<b-loading :show="true" variant="warning"></b-loading>
<b-loading :show="true" variant="info"></b-loading>
<b-loading :show="true" variant="light"></b-loading>
<b-loading :show="true" variant="dark"></b-loading>
</template>

<!-- b-loading-variations.vue -->
```

## Loading type

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).

```html
<template>
<b-loading :show="true" type="grow"></b-loading>
</template>

<!-- b-loading-type.vue -->
```

## Loading size

Via the `size` prop to set size loading.

```html
<template>
<b-loading :show="true"></b-loading>
<b-loading :show="true" small></b-loading>
</template>

<!-- b-loading-size.vue -->
```

## Fixed loading

Via the `fixed` prop to enable fixed loading.

```html
<template>
<div class="position-relative">
<div class="p-3">
<h3>Loading</h3>
<p>Loading can show the loading state icon.</p>
<button @click="startLoading" class="btn btn-primary">Start loading 2 seconds</button>
</div>
<b-loading :show="loading" fixed></b-loading>
</div>
</template>

<script>
export default {
data() {
return {
loading: false
}
},
methods: {
startLoading() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 2000)
}
}
}
</script>

<!-- b-loading-fixed.vue -->
```

## Fading loading

Use the `fade` prop to enable animation. By default loading are not animated.
It is recommended to attach `fixed` prop when using.

```html
<template>
<div class="position-relative">
<div class="p-3">
<h3>Loading</h3>
<p>Loading can show the loading state icon.</p>
<button @click="startLoading" class="btn btn-primary">Start loading 2 seconds</button>
</div>
<b-loading :show="loading" fixed fade></b-loading>
</div>
</template>

<script>
export default {
data() {
return {
loading: false
}
},
methods: {
startLoading() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 2000)
}
}
}
</script>

<!-- b-loading-fading.vue -->
```

## Set global render loading content

Set global config render loading content use string.

```js
Vue.use(Loading, {
BLoading: {
slot: 'Loading...'
}
})
```

Or set Vue component.

```js
import CustomLoadingComponent from './components/custom-loading.vue'

Vue.use(Loading, {
BLoading: {
slot: CustomLoadingComponent
}
})
```
30 changes: 30 additions & 0 deletions src/components/loading/_loading.scss
@@ -0,0 +1,30 @@
// Base style
.loading {
padding: $loading-padding-y $loading-padding-x;
text-align: center;

&.fade-enter-active,
&.fade-leave-active {
transition: $loading-transition;
}

&.fade-enter,
&.fade-leave-to {
opacity: 0;
}
}

// Fixed loading

.loading-fixed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: $loading-fixed-background-color;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
}
10 changes: 10 additions & 0 deletions src/components/loading/index.js
@@ -0,0 +1,10 @@
import BLoading from './loading'
import { installFactory } from '../../utils/plugins'

const components = {
BLoading
}

export default {
install: installFactory({ components })
}
1 change: 1 addition & 0 deletions src/components/loading/index.scss
@@ -0,0 +1 @@
@import "loading";
122 changes: 122 additions & 0 deletions src/components/loading/loading.js
@@ -0,0 +1,122 @@
import { getComponentConfig } from '../../utils/config'
import { requestAF } from '../../utils/dom'

const NAME = 'BLoading'

export default {
name: NAME,
model: {
prop: 'show',
event: 'input'
},
props: {
variant: {
type: String,
default: () => getComponentConfig(NAME, 'variant')
},
show: {
type: Boolean,
default: false
},
type: {
type: String,
default: () => getComponentConfig(NAME, 'type')
},
small: {
type: Boolean,
default: false
},
fade: {
type: Boolean,
default: () => getComponentConfig(NAME, 'fade')
},
fixed: {
type: Boolean,
default: () => getComponentConfig(NAME, 'fixed')
}
},
data() {
return {
showClass: this.fade && this.show
}
},
watch: {
show(val) {
if (val) {
this.$emit('started')
} else {
this.$emit('ended')
}
}
},
methods: {
onBeforeEnter() {
if (this.fade) {
requestAF(() => {
this.showClass = true
})
}
},
onBeforeLeave() {
this.showClass = false
}
},
render(h) {
let $loading
let $spinner
const slot = getComponentConfig(NAME, 'slot')
if (this.show) {
if (this.$slots.default) {
$spinner = this.$slots.default
} else if (slot && typeof slot === 'string') {
// slot is pure text
// _v is createTextVNode method
$spinner = this._v(slot)
} else if (typeof slot === 'object') {
// slot is Vue component
$spinner = h(slot)
} else {
$spinner = h('b-spinner', {
props: {
type: this.type,
label: 'Loading...',
variant: this.variant || 'primary',
small: this.small
}
})
}

$loading = h(
'div',
{
class: {
loading: true,
fade: this.fade,
show: this.showClass,
'loading-fixed': this.fixed
}
},
[$spinner]
)
$loading = [$loading]
}
return h(
'transition',
{
props: {
'enter-class': '',
'enter-active-class': '',
'enter-to-class': '',
'leave-class': 'show',
'leave-active-class': '',
'leave-to-class': ''
},
on: {
beforeEnter: this.onBeforeEnter,
beforeLeave: this.onBeforeLeave
}
},
$loading
)
}
}

0 comments on commit 559eda4

Please sign in to comment.