diff options
Diffstat (limited to 'src/components/emoji_picker')
| -rw-r--r-- | src/components/emoji_picker/emoji_picker.js | 52 | ||||
| -rw-r--r-- | src/components/emoji_picker/emoji_picker.scss | 103 | ||||
| -rw-r--r-- | src/components/emoji_picker/emoji_picker.vue | 35 |
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" |
