aboutsummaryrefslogtreecommitdiff
path: root/src/components/emoji_picker
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/emoji_picker')
-rw-r--r--src/components/emoji_picker/emoji_picker.js52
-rw-r--r--src/components/emoji_picker/emoji_picker.scss103
-rw-r--r--src/components/emoji_picker/emoji_picker.vue35
3 files changed, 124 insertions, 66 deletions
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 0d7ca812..9ea5c877 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -98,8 +98,14 @@ const EmojiPicker = {
required: false,
type: Boolean,
default: false
+ },
+ hideCustomEmoji: {
+ required: false,
+ type: Boolean,
+ default: false
}
},
+ inject: ['popoversZLayer'],
data () {
return {
keyword: '',
@@ -108,11 +114,13 @@ const EmojiPicker = {
groupsScrolledClass: 'scrolled-top',
keepOpen: false,
customEmojiTimeout: null,
+ hideCustomEmojiInPicker: false,
// Lazy-load only after the first time `showing` becomes true.
contentLoaded: false,
groupRefs: {},
emojiRefs: {},
filteredEmojiGroups: [],
+ emojiSize: 0,
width: 0
}
},
@@ -123,9 +131,28 @@ const EmojiPicker = {
Popover
},
methods: {
+ updateEmojiSize () {
+ const css = window.getComputedStyle(this.$refs.popover.$el)
+ const emojiSize = css.getPropertyValue('--emojiSize')
+ const emojiSizeUnit = emojiSize.replace(/[0-9,.]+/, '')
+ const emojiSizeValue = Number(emojiSize.replace(/[^0-9,.]+/, ''))
+ const fontSize = css.getPropertyValue('font-size').replace(/[^0-9,.]+/, '')
+
+ let emojiSizeReal
+ if (emojiSizeUnit.endsWith('em')) {
+ emojiSizeReal = emojiSizeValue * fontSize
+ } else {
+ emojiSizeReal = emojiSizeValue
+ }
+
+ const fullEmojiSize = emojiSizeReal + (2 * 0.2 * fontSize)
+ this.emojiSize = fullEmojiSize
+ },
showPicker () {
this.$refs.popover.showPopover()
- this.onShowing()
+ this.$nextTick(() => {
+ this.onShowing()
+ })
},
hidePicker () {
this.$refs.popover.hidePopover()
@@ -217,6 +244,7 @@ const EmojiPicker = {
},
onShowing () {
const oldContentLoaded = this.contentLoaded
+ this.updateEmojiSize()
this.recalculateItemPerRow()
this.$nextTick(() => {
this.$refs.search.focus()
@@ -259,16 +287,20 @@ const EmojiPicker = {
},
computed: {
minItemSize () {
- return this.emojiHeight
+ return this.emojiSize
},
- emojiHeight () {
- return 32 + 4
+ // used to watch it
+ fontSize () {
+ this.$nextTick(() => {
+ this.updateEmojiSize()
+ })
+ return this.$store.getters.mergedConfig.fontSize
},
- emojiWidth () {
- return 32 + 4
+ emojiHeight () {
+ return this.emojiSize
},
itemPerRow () {
- return this.width ? Math.floor(this.width / this.emojiWidth - 1) : 6
+ return this.width ? Math.floor(this.width / this.emojiSize) : 6
},
activeGroupView () {
return this.showingStickers ? '' : this.activeGroup
@@ -280,6 +312,9 @@ const EmojiPicker = {
return 0
},
allCustomGroups () {
+ if (this.hideCustomEmoji || this.hideCustomEmojiInPicker) {
+ return {}
+ }
const emojis = this.$store.getters.groupedCustomEmojis
if (emojis.unpacked) {
emojis.unpacked.text = this.$t('emoji.unpacked')
@@ -342,6 +377,9 @@ const EmojiPicker = {
return emoji.displayText
}
+ },
+ isInModal () {
+ return this.popoversZLayer === 'modals'
}
}
}
diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss
index 5bcff33b..12c09388 100644
--- a/src/components/emoji_picker/emoji_picker.scss
+++ b/src/components/emoji_picker/emoji_picker.scss
@@ -1,62 +1,55 @@
-@import "../../variables";
-
-$emoji-picker-header-height: 36px;
-$emoji-picker-header-picture-width: 32px;
-$emoji-picker-header-picture-height: 32px;
-$emoji-picker-emoji-size: 32px;
-
.emoji-picker {
+ --__emoji-picker-header: 2.2em;
+
width: 25em;
max-width: calc(100vw - 20px); // popover gives 10px margin from window edge
display: flex;
flex-direction: column;
- background-color: $fallback--bg;
- background-color: var(--popover, $fallback--bg);
- color: $fallback--link;
- color: var(--popoverText, $fallback--link);
-
- --faint: var(--popoverFaintText, $fallback--faint);
- --faintLink: var(--popoverFaintLink, $fallback--faint);
- --lightText: var(--popoverLightText, $fallback--lightText);
- --icon: var(--popoverIcon, $fallback--icon);
&-header-image {
display: inline-flex;
justify-content: center;
align-items: center;
- width: $emoji-picker-header-picture-width;
- max-width: $emoji-picker-header-picture-width;
- height: $emoji-picker-header-picture-height;
- max-height: $emoji-picker-header-picture-height;
+ width: var(--__emoji-picker-header);
+ max-width: var(--__emoji-picker-header);
+ height: var(--__emoji-picker-header);
+ max-height: var(--__emoji-picker-header);
.still-image {
- max-width: 100%;
- max-height: 100%;
- height: 100%;
- width: 100%;
+ width: var(--__emoji-picker-header);
+ max-width: var(--__emoji-picker-header);
+ height: var(--__emoji-picker-header);
+ max-height: var(--__emoji-picker-header);
object-fit: contain;
+
+ --_still_image-label-scale: 0.5;
}
}
.keep-open,
- .too-many-emoji {
- padding: 7px;
+ .too-many-emoji,
+ .hide-custom-emoji {
+ padding: 0.5em;
line-height: normal;
}
+ .hide-custom-emoji {
+ padding-top: 0;
+ }
+
.too-many-emoji {
display: flex;
flex-direction: column;
}
.keep-open-label {
- padding: 0 7px;
+ padding: 0 0.5em;
display: flex;
}
.heading {
display: flex;
- padding: 10px 7px 5px;
+ padding: 0.7em 0.5em 0;
}
.content {
@@ -71,14 +64,14 @@ $emoji-picker-emoji-size: 32px;
display: flex;
flex-flow: row nowrap;
overflow-x: auto;
+ overflow-y: hidden;
}
.additional-tabs {
display: flex;
border-left: 1px solid;
- border-left-color: $fallback--icon;
- border-left-color: var(--icon, $fallback--icon);
- padding-left: 7px;
+ border-left-color: var(--border);
+ padding-left: 0.5em;
flex: 0 0 auto;
}
@@ -87,30 +80,29 @@ $emoji-picker-emoji-size: 32px;
flex-basis: auto;
display: flex;
align-content: center;
+ scrollbar-width: thin;
&-item {
- padding: 0 7px;
+ padding: 0 0.5em;
cursor: pointer;
- font-size: 1.85em;
- width: $emoji-picker-header-picture-width;
- max-width: $emoji-picker-header-picture-width;
- height: $emoji-picker-header-picture-height;
- max-height: $emoji-picker-header-picture-height;
+ width: var(--__emoji-picker-header);
+ max-width: var(--__emoji-picker-header);
+ height: var(--__emoji-picker-header);
+ max-height: var(--__emoji-picker-header);
display: flex;
align-items: center;
+ .svg-inline--fa {
+ font-size: 1.85em;
+ }
+
&.disabled {
opacity: 0.5;
pointer-events: none;
}
- &.active {
- border-bottom: 4px solid;
-
- svg {
- color: $fallback--lightText;
- color: var(--lightText, $fallback--lightText);
- }
+ &.toggled {
+ border-bottom: 0.2em solid;
}
}
}
@@ -137,7 +129,7 @@ $emoji-picker-emoji-size: 32px;
.emoji {
&-search {
- padding: 5px;
+ padding: 0.3em;
flex: 0 0 auto;
input {
@@ -151,6 +143,7 @@ $emoji-picker-emoji-size: 32px;
flex: 1 1 1px;
position: relative;
overflow: auto;
+ scrollbar-gutter: stable both-edges;
user-select: none;
mask:
linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
@@ -177,13 +170,13 @@ $emoji-picker-emoji-size: 32px;
display: flex;
align-items: center;
flex-wrap: wrap;
- padding-left: 5px;
justify-content: left;
&-title {
font-size: 0.85em;
width: 100%;
margin: 0;
+ padding-left: 0.3em;
&.disabled {
display: none;
@@ -192,24 +185,28 @@ $emoji-picker-emoji-size: 32px;
}
&-item {
- width: $emoji-picker-emoji-size;
- height: $emoji-picker-emoji-size;
+ width: var(--emoji-size);
+ height: var(--emoji-size);
box-sizing: border-box;
display: flex;
- line-height: $emoji-picker-emoji-size;
+ line-height: var(--emoji-size);
align-items: center;
justify-content: center;
- margin: 4px;
+ margin: 0.2em;
cursor: pointer;
.emoji-picker-emoji.-custom {
object-fit: contain;
- max-width: 100%;
- max-height: 100%;
+ width: var(--emoji-size);
+ max-width: var(--emoji-size);
+ height: var(--emoji-size);
+ max-height: var(--emoji-size);
+
+ --_still_image-label-scale: 0.5;
}
.emoji-picker-emoji.-unicode {
- font-size: 24px;
+ font-size: 1.6em;
overflow: hidden;
}
}
diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue
index 6972164b..a3dc8f9e 100644
--- a/src/components/emoji_picker/emoji_picker.vue
+++ b/src/components/emoji_picker/emoji_picker.vue
@@ -3,25 +3,32 @@
ref="popover"
trigger="click"
popover-class="emoji-picker popover-default"
- :trigger-attrs="{ 'aria-hidden': true }"
+ :trigger-attrs="{ 'aria-hidden': true, tabindex: -1 }"
@show="onPopoverShown"
@close="onPopoverClosed"
>
<template #content>
<div class="heading">
+ <!--
+ Body scroll lock needs to be on every scrollable element on safari iOS.
+ Here we tell it to enable scrolling for this element.
+ See https://github.com/willmcpo/body-scroll-lock#vanilla-js
+ -->
<span
ref="header"
+ v-body-scroll-lock="isInModal"
class="emoji-tabs"
>
<span
v-for="group in filteredEmojiGroups"
:ref="setGroupRef('group-header-' + group.id)"
:key="group.id"
- class="emoji-tabs-item"
+ class="button-unstyled emoji-tabs-item"
:class="{
- active: activeGroupView === group.id
+ toggled: activeGroupView === group.id
}"
:title="group.text"
+ role="button"
@click.prevent="highlight(group.id)"
>
<span
@@ -45,8 +52,8 @@
class="additional-tabs"
>
<span
- class="stickers-tab-icon additional-tabs-item"
- :class="{active: showingStickers}"
+ class="button-unstyled stickers-tab-icon additional-tabs-item"
+ :class="{toggled: showingStickers}"
:title="$t('emoji.stickers')"
@click.prevent="toggleStickers"
>
@@ -70,16 +77,19 @@
ref="search"
v-model="keyword"
type="text"
- class="form-control"
+ class="input form-control"
:placeholder="$t('emoji.search_emoji')"
@input="$event.target.composing = false"
>
</div>
+ <!-- Enables scrolling for this element on safari iOS. See comments for header. -->
<DynamicScroller
ref="emoji-groups"
+ v-body-scroll-lock="isInModal"
class="emoji-groups"
:class="groupsScrolledClass"
:min-item-size="minItemSize"
+ :buffer="minItemSize"
:items="emojiItems"
:emit-update="true"
@update="onScroll"
@@ -108,6 +118,7 @@
:key="group.id + emoji.displayText"
:title="maybeLocalizedEmojiName(emoji)"
class="emoji-item"
+ role="button"
@click.stop.prevent="onEmoji(emoji)"
>
<span
@@ -118,6 +129,7 @@
v-else
class="emoji-picker-emoji -custom"
loading="lazy"
+ :alt="maybeLocalizedEmojiName(emoji)"
:src="emoji.imageUrl"
:data-emoji-name="group.id + emoji.displayText"
/>
@@ -131,6 +143,17 @@
{{ $t('emoji.keep_open') }}
</Checkbox>
</div>
+ <div
+ v-if="!hideCustomEmoji"
+ class="hide-custom-emoji"
+ >
+ <Checkbox
+ v-model="hideCustomEmojiInPicker"
+ @change="onShowing"
+ >
+ {{ $t('emoji.hide_custom_emoji') }}
+ </Checkbox>
+ </div>
</div>
<div
v-if="showingStickers"