more work on emoji component (wip)

This commit is contained in:
Craig 2020-02-01 10:43:02 +00:00
parent 9aa6ddbe08
commit 1f1e67b829
3 changed files with 163 additions and 34 deletions

View File

@ -35,8 +35,16 @@
<div v-if="!muted" class="chat-send"> <div v-if="!muted" class="chat-send">
<div class="accent" /> <div class="accent" />
<div class="text-container"> <div class="text-container">
<textarea ref="chat" placeholder="Send a message" @keydown="onKeyDown" v-model="content" /> <textarea
<div class="emoji"><neko-emoji /></div> ref="input"
placeholder="Send a message"
@keydown="onKeyDown"
v-model="content"
@click.stop.prevent="emoji = false"
/>
<div class="emoji" @click.stop.prevent="emoji = !emoji">
<neko-emoji v-if="emoji" @picked="onEmojiPicked" />
</div>
</div> </div>
</div> </div>
</div> </div>
@ -336,9 +344,11 @@
}, },
}) })
export default class extends Vue { export default class extends Vue {
@Ref('input') readonly _input!: HTMLTextAreaElement
@Ref('history') readonly _history!: HTMLElement @Ref('history') readonly _history!: HTMLElement
@Ref('context') readonly _context!: any @Ref('context') readonly _context!: any
emoji = false
content = '' content = ''
get id() { get id() {
@ -360,6 +370,11 @@
}) })
} }
@Watch('emoji')
onEmojiChange() {
this._input.focus()
}
@Watch('muted') @Watch('muted')
onMutedChange(muted: boolean) { onMutedChange(muted: boolean) {
if (muted) { if (muted) {
@ -382,6 +397,22 @@
return `${str.charAt(0).toUpperCase()}${str.slice(1)}` return `${str.charAt(0).toUpperCase()}${str.slice(1)}`
} }
onEmojiPicked(emoji: string) {
const text = `:${emoji}:`
if (this._input.selectionStart || this._input.selectionStart === 0) {
var startPos = this._input.selectionStart
var endPos = this._input.selectionEnd
this.content = this.content.substring(0, startPos) + text + this.content.substring(endPos, this.content.length)
this.$nextTick(() => {
this._input.selectionStart = startPos + text.length
this._input.selectionEnd = startPos + text.length
})
} else {
this.content += text
}
this.emoji = false
}
onContext(event: MouseEvent, data: any) { onContext(event: MouseEvent, data: any) {
this._context.open(event, data) this._context.open(event, data)
} }

View File

@ -1,8 +1,10 @@
<template> <template>
<div class="neko-emoji"> <div class="neko-emoji">
<div class="search"> <div class="search">
<div class="search-contianer">
<input type="text" ref="search" v-model="search" /> <input type="text" ref="search" v-model="search" />
</div> </div>
</div>
<div class="list" ref="scroll" @scroll="onScroll"> <div class="list" ref="scroll" @scroll="onScroll">
<ul :class="[search === '' ? 'group-list' : 'emoji-list']"> <ul :class="[search === '' ? 'group-list' : 'emoji-list']">
<template v-if="search === ''"> <template v-if="search === ''">
@ -35,9 +37,9 @@
</ul> </ul>
</div> </div>
<div class="details"> <div class="details">
<template v-if="hovered !== ''"> <div class="icon-container" v-if="hovered !== ''">
<span :class="['icon', 'emoji-20', `e-${hovered}`]"></span><span class="emoji">:{{ hovered }}:</span> <span :class="['icon', 'emoji-20', `e-${hovered}`]"></span><span class="emoji">:{{ hovered }}:</span>
</template> </div>
</div> </div>
<div class="groups"> <div class="groups">
<ul> <ul>
@ -47,7 +49,7 @@
:class="[group.id, active === group.id && search === '' ? 'active' : '']" :class="[group.id, active === group.id && search === '' ? 'active' : '']"
@click.stop.prevent="scrollTo($event, index)" @click.stop.prevent="scrollTo($event, index)"
> >
<i class="fas fa-angry"></i> <span :class="[`group-${group.id}`]" />
</li> </li>
</ul> </ul>
</div> </div>
@ -55,12 +57,13 @@
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
$emoji-width: 350px; $emoji-width: 300px;
.neko-emoji { .neko-emoji {
position: absolute; position: absolute;
z-index: 10000;
width: $emoji-width; width: $emoji-width;
height: 200px; height: 350px;
background: $background-secondary; background: $background-secondary;
bottom: 30px; bottom: 30px;
right: 0; right: 0;
@ -68,13 +71,46 @@
flex-direction: column; flex-direction: column;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
box-shadow: $elevation-high;
.search { .search {
flex-shrink: 0; flex-shrink: 0;
height: 38px;
border-bottom: 1px solid $background-tertiary; border-bottom: 1px solid $background-tertiary;
padding: 10px;
.search-contianer {
border-radius: 5px;
color: $interactive-normal;
position: relative;
display: flex;
flex-direction: column;
align-content: center;
overflow: hidden;
&::before {
content: '\f002';
font-weight: 900;
font-family: 'Font Awesome 5 Free';
position: absolute;
width: 15px;
height: 15px;
top: 6px;
right: 6px;
opacity: 0.5;
}
input { input {
border: none;
background-color: $background-floating;
color: $interactive-normal;
padding: 5px;
font-weight: 500;
&::placeholder {
color: $text-muted;
font-weight: 500;
}
}
} }
} }
@ -118,11 +154,11 @@
font-weight: 500; font-weight: 500;
font-size: 12px; font-size: 12px;
position: sticky; position: sticky;
top: 0; top: -5px;
} background-color: rgba($color: $background-secondary, $alpha: 0.9);
width: 100%;
.emoji-list { display: block;
margin: 10px 0; padding: 8px 0;
} }
} }
} }
@ -136,9 +172,10 @@
&.emoji { &.emoji {
padding: 2px; padding: 2px;
border-radius: 3px; border-radius: 3px;
cursor: pointer;
&.active { &.active {
background-color: #fff; background-color: $background-floating;
} }
} }
} }
@ -147,22 +184,40 @@
.details { .details {
flex-shrink: 0; flex-shrink: 0;
display: flex;
align-content: center;
justify-content: center;
flex-direction: column;
height: 36px; height: 36px;
background: $background-tertiary; background: $background-tertiary;
.icon-container {
display: flex;
align-content: center;
flex-direction: row;
height: 20px;
span { span {
cursor: default;
&.icon { &.icon {
margin: 0 5px 0 10px;
} }
&.emoji { &.emoji {
line-height: 20px;
font-size: 16px;
font-weight: 500;
}
} }
} }
} }
.groups { .groups {
flex-shrink: 0; flex-shrink: 0;
height: 28px; height: 30px;
background: $background-floating; background: $background-floating;
padding: 0 5px;
ul { ul {
display: flex; display: flex;
@ -171,10 +226,53 @@
li { li {
flex-grow: 1; flex-grow: 1;
height: 23px; display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
flex-direction: column;
height: 27px;
cursor: pointer;
&.active { &.active {
border-bottom: 2px solid $style-primary; border-bottom: 3px solid $style-primary;
}
span {
margin: 0 auto;
height: 20px;
width: 20px;
&.group-recent {
background-color: #fff;
}
&.group-neko {
background-color: #fff;
}
&.group-people {
background-color: #fff;
}
&.group-nature {
background-color: #fff;
}
&.group-food {
background-color: #fff;
}
&.group-activity {
background-color: #fff;
}
&.group-travel {
background-color: #fff;
}
&.group-objects {
background-color: #fff;
}
&.group-symbols {
background-color: #fff;
}
&.group-flags {
background-color: #fff;
}
} }
} }
} }
@ -265,7 +363,7 @@
} }
onClick(event: MouseEvent, emoji: string) { onClick(event: MouseEvent, emoji: string) {
this.$emit('done', emoji) this.$emit('picked', emoji)
} }
} }
</script> </script>

View File

@ -1,16 +1,16 @@
export const groups: Array<{ name: string; id: string; list: string[] }> = [ export const groups: Array<{ name: string; id: string; list: string[] }> = [
{ {
id: 'Recent', id: 'recent',
name: 'Recent', name: 'Recent',
list: [], list: [],
}, },
{ {
id: 'Neko', id: 'neko',
name: 'Neko', name: 'Neko',
list: [], list: [],
}, },
{ {
id: 'People', id: 'people',
name: 'People', name: 'People',
list: [ list: [
'grinning', 'grinning',
@ -362,7 +362,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Nature', id: 'nature',
name: 'Nature', name: 'Nature',
list: [ list: [
'dog', 'dog',
@ -545,7 +545,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Food', id: 'food',
name: 'Food', name: 'Food',
list: [ list: [
'green_apple', 'green_apple',
@ -656,7 +656,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Activity', id: 'activity',
name: 'Activity', name: 'Activity',
list: [ list: [
'soccer', 'soccer',
@ -757,7 +757,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Travel', id: 'travel',
name: 'Travel', name: 'Travel',
list: [ list: [
'red_car', 'red_car',
@ -882,7 +882,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Objects', id: 'objects',
name: 'Objects', name: 'Objects',
list: [ list: [
'watch', 'watch',
@ -1090,7 +1090,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Symbols', id: 'symbols',
name: 'Symbols', name: 'Symbols',
list: [ list: [
'100', '100',
@ -1370,7 +1370,7 @@ export const groups: Array<{ name: string; id: string; list: string[] }> = [
], ],
}, },
{ {
id: 'Flags', id: 'flags',
name: 'Flags', name: 'Flags',
list: [ list: [
'afghanistan', 'afghanistan',