rudeshark.net/src/client/app/common/views/components/reaction-picker.vue

231 lines
6.2 KiB
Vue
Raw Normal View History

2018-02-07 07:16:01 +01:00
<template>
2018-02-13 00:11:10 +01:00
<div class="mk-reaction-picker">
2018-02-07 07:16:01 +01:00
<div class="backdrop" ref="backdrop" @click="close"></div>
2018-06-26 11:25:27 +02:00
<div class="popover" :class="{ compact, big }" ref="popover">
2018-02-07 07:34:08 +01:00
<p v-if="!compact">{{ title }}</p>
2018-02-07 07:16:01 +01:00
<div>
<button @click="react('like')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="1" title="%i18n:common.reactions.like%"><mk-reaction-icon reaction='like'/></button>
<button @click="react('love')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="2" title="%i18n:common.reactions.love%"><mk-reaction-icon reaction='love'/></button>
<button @click="react('laugh')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="3" title="%i18n:common.reactions.laugh%"><mk-reaction-icon reaction='laugh'/></button>
<button @click="react('hmm')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="4" title="%i18n:common.reactions.hmm%"><mk-reaction-icon reaction='hmm'/></button>
<button @click="react('surprise')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="5" title="%i18n:common.reactions.surprise%"><mk-reaction-icon reaction='surprise'/></button>
<button @click="react('congrats')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="6" title="%i18n:common.reactions.congrats%"><mk-reaction-icon reaction='congrats'/></button>
2018-08-11 14:08:34 +02:00
<button @click="react('angry')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="7" title="%i18n:common.reactions.angry%"><mk-reaction-icon reaction='angry'/></button>
<button @click="react('confused')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="8" title="%i18n:common.reactions.confused%"><mk-reaction-icon reaction='confused'/></button>
<button @click="react('rip')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="9" title="%i18n:common.reactions.rip%"><mk-reaction-icon reaction='rip'/></button>
<button @click="react('pudding')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="10" title="%i18n:common.reactions.pudding%"><mk-reaction-icon reaction='pudding'/></button>
2018-02-07 07:16:01 +01:00
</div>
</div>
</div>
</template>
2018-02-13 00:11:10 +01:00
<script lang="ts">
import Vue from 'vue';
2018-02-13 01:27:57 +01:00
import * as anime from 'animejs';
2018-02-13 00:11:10 +01:00
2018-05-20 13:26:38 +02:00
const placeholder = '%i18n:@choose-reaction%';
2018-02-13 00:11:10 +01:00
export default Vue.extend({
2018-06-26 11:25:27 +02:00
props: {
note: {
type: Object,
required: true
},
source: {
required: true
},
compact: {
type: Boolean,
required: false,
default: false
},
cb: {
required: false
},
big: {
type: Boolean,
required: false,
default: false
}
},
2018-02-13 00:11:10 +01:00
data() {
return {
title: placeholder
};
},
mounted() {
2018-02-13 04:50:42 +01:00
this.$nextTick(() => {
const popover = this.$refs.popover as any;
2018-02-13 00:11:10 +01:00
2018-02-13 04:50:42 +01:00
const rect = this.source.getBoundingClientRect();
const width = popover.offsetWidth;
const height = popover.offsetHeight;
2018-02-13 00:11:10 +01:00
2018-02-13 04:50:42 +01:00
if (this.compact) {
const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
const y = rect.top + window.pageYOffset + (this.source.offsetHeight / 2);
popover.style.left = (x - (width / 2)) + 'px';
popover.style.top = (y - (height / 2)) + 'px';
} else {
const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
const y = rect.top + window.pageYOffset + this.source.offsetHeight;
popover.style.left = (x - (width / 2)) + 'px';
popover.style.top = y + 'px';
}
2018-02-07 07:34:08 +01:00
2018-02-13 04:50:42 +01:00
anime({
targets: this.$refs.backdrop,
opacity: 1,
duration: 100,
easing: 'linear'
});
2018-02-13 00:11:10 +01:00
2018-02-13 04:50:42 +01:00
anime({
targets: this.$refs.popover,
opacity: 1,
scale: [0.5, 1],
duration: 500
});
2018-02-13 00:11:10 +01:00
});
},
methods: {
react(reaction) {
2018-04-07 19:30:37 +02:00
(this as any).api('notes/reactions/create', {
noteId: this.note.id,
2018-02-13 00:11:10 +01:00
reaction: reaction
}).then(() => {
if (this.cb) this.cb();
this.$destroy();
});
2018-02-08 06:25:49 +01:00
},
2018-02-13 00:11:10 +01:00
onMouseover(e) {
this.title = e.target.title;
2018-02-07 07:34:08 +01:00
},
2018-02-13 00:11:10 +01:00
onMouseout(e) {
this.title = placeholder;
},
close() {
(this.$refs.backdrop as any).style.pointerEvents = 'none';
2018-02-07 10:17:59 +01:00
anime({
targets: this.$refs.backdrop,
2018-02-13 00:11:10 +01:00
opacity: 0,
duration: 200,
2018-02-07 10:17:59 +01:00
easing: 'linear'
});
2018-02-13 00:11:10 +01:00
(this.$refs.popover as any).style.pointerEvents = 'none';
2018-02-07 10:17:59 +01:00
anime({
targets: this.$refs.popover,
2018-02-13 00:11:10 +01:00
opacity: 0,
scale: 0.5,
duration: 200,
easing: 'easeInBack',
complete: () => this.$destroy()
2018-02-07 10:17:59 +01:00
});
2018-02-07 07:16:01 +01:00
}
2018-02-13 00:11:10 +01:00
}
});
2018-02-07 07:16:01 +01:00
</script>
2018-02-07 10:30:17 +01:00
<style lang="stylus" scoped>
2018-03-03 05:47:55 +01:00
@import '~const.styl'
2018-02-13 04:50:42 +01:00
$border-color = rgba(27, 31, 35, 0.15)
2018-02-07 10:30:17 +01:00
2018-04-20 00:45:37 +02:00
root(isDark)
2018-02-13 00:11:10 +01:00
position initial
> .backdrop
position fixed
top 0
left 0
z-index 10000
width 100%
height 100%
background isDark ? rgba(#000, 0.4) : rgba(#000, 0.1)
2018-02-13 00:11:10 +01:00
opacity 0
> .popover
2018-04-20 00:45:37 +02:00
$bgcolor = isDark ? #2c303c : #fff
2018-02-13 00:11:10 +01:00
position absolute
z-index 10001
2018-04-20 00:45:37 +02:00
background $bgcolor
2018-02-13 00:11:10 +01: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
&:not(.compact)
margin-top $balloon-size
transform-origin center -($balloon-size)
&:before
content ""
display block
position absolute
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
content ""
2018-02-07 10:30:17 +01:00
display block
2018-02-13 00:11:10 +01:00
position absolute
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-04-20 00:45:37 +02:00
border-bottom solid $balloon-size $bgcolor
2018-02-13 00:11:10 +01:00
2018-07-04 13:58:03 +02:00
&.big
2018-06-26 11:25:27 +02:00
> div
width 280px
> button
width 50px
height 50px
font-size 28px
border-radius 4px
2018-02-13 00:11:10 +01:00
> p
display block
margin 0
padding 8px 10px
font-size 14px
2018-04-20 00:45:37 +02:00
color isDark ? #d6dce2 : #586069
border-bottom solid 1px isDark ? #1c2023 : #e1e4e8
2018-02-13 00:11:10 +01:00
> div
padding 4px
width 240px
text-align center
> button
2018-03-03 08:59:00 +01:00
padding 0
2018-02-13 00:11:10 +01:00
width 40px
height 40px
font-size 24px
border-radius 2px
&:hover
2018-04-20 00:45:37 +02:00
background isDark ? #252731 : #eee
2018-02-13 00:11:10 +01:00
&:active
background $theme-color
box-shadow inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15)
2018-02-07 10:30:17 +01:00
2018-04-20 00:45:37 +02:00
.mk-reaction-picker[data-darkmode]
root(true)
.mk-reaction-picker:not([data-darkmode])
root(false)
2018-02-07 10:30:17 +01:00
</style>