Files
vaquant/src/components/FabButton.vue
2020-08-27 21:54:33 +02:00

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>