134 lines
3.1 KiB
Vue
134 lines
3.1 KiB
Vue
<template>
|
|
<div class="fab-button" :id="`fab-${uniqueId}`">
|
|
<router-link
|
|
v-if="to"
|
|
class="button is-primary is-large is-fab"
|
|
:class="getClass"
|
|
:style="buttonStyle"
|
|
:to="to"
|
|
@click.native="valid"
|
|
>
|
|
<span class="icon is-medium">
|
|
<slot>
|
|
<awe-icon icon="plus" />
|
|
</slot>
|
|
</span>
|
|
<span class="fulltext" v-if="$slots.fulltext">
|
|
<slot name="fulltext"></slot>
|
|
</span>
|
|
</router-link>
|
|
<button
|
|
v-else
|
|
type="submit"
|
|
class="button is-primary is-large is-fab"
|
|
:class="getClass"
|
|
:style="buttonStyle"
|
|
@click="valid"
|
|
>
|
|
<span class="icon is-medium">
|
|
<slot>
|
|
<awe-icon icon="plus" />
|
|
</slot>
|
|
</span>
|
|
<span class="fulltext" v-if="$slots.fulltext">
|
|
<slot name="fulltext"></slot>
|
|
</span>
|
|
</button>
|
|
<div class="fab-margin" v-if="margin"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue, Prop } from 'vue-property-decorator'
|
|
import { throttle } from 'lodash-es'
|
|
|
|
@Component
|
|
export default class FabButton extends Vue {
|
|
@Prop({ type: Boolean, default: false })
|
|
public margin!: boolean
|
|
@Prop({ type: Object, default: () => null })
|
|
public to!: any | null
|
|
@Prop({ type: Object, required: false, default: () => ({}) })
|
|
public buttonStyle!: any
|
|
public uniqueId: string = Date.now().toString()
|
|
public isLoading: boolean = false
|
|
public showFull: boolean = true
|
|
|
|
public mounted(): void {
|
|
if (!this.$slots.fulltext) {
|
|
return
|
|
}
|
|
const main = document.getElementById('main')
|
|
const fabElm = document.getElementById(`fab-${this.uniqueId}`)
|
|
if (main && fabElm) {
|
|
document.addEventListener(
|
|
'scroll',
|
|
throttle((evt) => {
|
|
this.showFull = main.getBoundingClientRect().top > 0
|
|
if (this.showFull) {
|
|
fabElm.classList.remove('small')
|
|
} else {
|
|
fabElm.classList.add('small')
|
|
}
|
|
}, 150)
|
|
)
|
|
}
|
|
}
|
|
|
|
public loading(): void {
|
|
this.isLoading = true
|
|
}
|
|
public valid(): void {
|
|
this.isLoading = true
|
|
this.$emit('valid', () => {
|
|
this.isLoading = false
|
|
})
|
|
}
|
|
|
|
public get getClass(): any {
|
|
return { 'is-loading': this.isLoading }
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import '../styles/variables';
|
|
|
|
$padding-fab: 24px;
|
|
.fab-button {
|
|
.button {
|
|
transition: padding-right 0.3s cubic-bezier(0.55, 0, 0.1, 1);
|
|
}
|
|
.fulltext {
|
|
display: inline-block;
|
|
max-width: 450px;
|
|
opacity: 1;
|
|
transition: max-width 0.3s cubic-bezier(0.55, 0, 0.1, 1),
|
|
opacity 0.3s cubic-bezier(0.55, 0, 0.1, 1);
|
|
}
|
|
&.small {
|
|
.button {
|
|
padding-right: 0.2em;
|
|
transition: padding-right 0.3s cubic-bezier(0.55, 0, 0.1, 1);
|
|
}
|
|
.fulltext {
|
|
max-width: 0;
|
|
opacity: 0;
|
|
transition: max-width 0.3s cubic-bezier(0.55, 0, 0.1, 1),
|
|
opacity 0.3s cubic-bezier(0.55, 0, 0.1, 1);
|
|
}
|
|
}
|
|
}
|
|
.is-fab {
|
|
bottom: $padding-fab;
|
|
position: fixed;
|
|
right: $padding-fab;
|
|
z-index: 5;
|
|
border: 2px solid $white;
|
|
}
|
|
|
|
.fab-margin {
|
|
margin: calc(#{$padding-fab} * 2 + 30px) 0 calc(#{$padding-fab} * 2);
|
|
}
|
|
</style>
|