iceshrimp/src/client/app/common/views/components/menu.vue

208 lines
4.3 KiB
Vue
Raw Normal View History

2018-06-06 05:18:08 +09:00
<template>
2018-12-02 14:26:30 +09:00
<div class="onchrpzrvnoruiaenfcqvccjfuupzzwv" :class="{ big: $root.isMobile }">
2018-06-06 05:18:08 +09:00
<div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ hukidasi }" ref="popover">
2018-09-18 16:45:20 +09:00
<template v-for="item, i in items">
<div v-if="item === null"></div>
<button v-if="item" @click="clicked(item.action)" :tabindex="i">
<fa v-if="item.icon" :icon="item.icon"/>{{ item.text }}
</button>
</template>
2018-06-06 05:18:08 +09:00
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as anime from 'animejs';
export default Vue.extend({
2018-06-10 03:27:10 +09:00
props: {
source: {
required: true
},
items: {
type: Array,
required: true
},
compact: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
hukidasi: !this.compact
};
},
2018-06-06 05:18:08 +09:00
mounted() {
this.$nextTick(() => {
const popover = this.$refs.popover as any;
const rect = this.source.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
let left;
let top;
2018-06-06 05:18:08 +09:00
if (this.compact) {
const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
const y = rect.top + window.pageYOffset + (this.source.offsetHeight / 2);
left = (x - (width / 2));
top = (y - (height / 2));
2018-06-06 05:18:08 +09:00
} else {
const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
const y = rect.top + window.pageYOffset + this.source.offsetHeight;
left = (x - (width / 2));
top = y;
}
2018-06-10 03:27:10 +09:00
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset;
this.hukidasi = false;
2018-06-06 05:18:08 +09:00
}
2018-06-10 03:27:10 +09:00
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset;
this.hukidasi = false;
}
popover.style.left = left + 'px';
popover.style.top = top + 'px';
2018-06-06 05:18:08 +09:00
anime({
targets: this.$refs.backdrop,
opacity: 1,
duration: 100,
easing: 'linear'
});
anime({
targets: this.$refs.popover,
opacity: 1,
scale: [0.5, 1],
duration: 500
});
});
},
methods: {
clicked(fn) {
fn();
this.close();
},
close() {
(this.$refs.backdrop as any).style.pointerEvents = 'none';
anime({
targets: this.$refs.backdrop,
opacity: 0,
duration: 200,
easing: 'linear'
});
(this.$refs.popover as any).style.pointerEvents = 'none';
anime({
targets: this.$refs.popover,
opacity: 0,
scale: 0.5,
duration: 200,
easing: 'easeInBack',
complete: () => {
this.$emit('closed');
2018-09-15 21:53:04 +09:00
this.destroyDom();
2018-06-06 05:18:08 +09:00
}
});
}
}
});
</script>
<style lang="stylus" scoped>
2018-09-27 01:32:04 +09:00
.onchrpzrvnoruiaenfcqvccjfuupzzwv
$bg-color = var(--popupBg)
2018-09-02 17:56:20 +09:00
$border-color = rgba(27, 31, 35, 0.15)
2018-06-06 05:18:08 +09:00
position initial
2018-12-02 14:26:30 +09:00
&.big
> .popover
> button
font-size 15px
2018-06-06 05:18:08 +09:00
> .backdrop
position fixed
top 0
left 0
z-index 10000
width 100%
height 100%
2018-09-27 01:32:04 +09:00
background var(--modalBackdrop)
2018-06-06 05:18:08 +09:00
opacity 0
> .popover
position absolute
z-index 10001
padding 8px 0
2018-09-02 17:56:20 +09:00
background $bg-color
2018-06-06 05:18:08 +09:00
border 1px solid $border-color
border-radius 4px
box-shadow 0 3px 12px rgba(27, 31, 35, 0.15)
transform scale(0.5)
opacity 0
$balloon-size = 16px
&.hukidasi
2018-06-06 05:18:08 +09:00
margin-top $balloon-size
transform-origin center -($balloon-size)
&:before
2018-06-10 03:27:10 +09:00
&:after
2018-06-06 05:18:08 +09:00
content ""
display block
position absolute
2018-06-10 03:27:10 +09:00
pointer-events none
&:before
2018-06-06 05:18:08 +09:00
top -($balloon-size * 2)
left s('calc(50% - %s)', $balloon-size)
border-top solid $balloon-size transparent
border-left solid $balloon-size transparent
border-right solid $balloon-size transparent
border-bottom solid $balloon-size $border-color
&:after
top -($balloon-size * 2) + 1.5px
left s('calc(50% - %s)', $balloon-size)
border-top solid $balloon-size transparent
border-left solid $balloon-size transparent
border-right solid $balloon-size transparent
2018-09-02 17:56:20 +09:00
border-bottom solid $balloon-size $bg-color
2018-06-06 05:18:08 +09:00
> button
display block
padding 8px 16px
width 100%
2018-09-27 01:32:04 +09:00
color var(--popupFg)
white-space nowrap
2018-06-06 05:18:08 +09:00
&:hover
2018-09-26 20:19:35 +09:00
color var(--primaryForeground)
background var(--primary)
2018-06-06 05:18:08 +09:00
text-decoration none
&:active
2018-09-26 20:19:35 +09:00
color var(--primaryForeground)
background var(--primaryDarken10)
2018-06-06 05:18:08 +09:00
> [data-icon]
margin-right 4px
> div
margin 8px 0
height 1px
2018-09-27 01:32:04 +09:00
background var(--faceDivider)
2018-06-06 05:18:08 +09:00
</style>