UBER-1146: fix scrolling in emojis popup (#3912)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2023-10-30 19:39:21 +04:00 committed by GitHub
parent e80af41f37
commit 705197a674
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,9 +1,8 @@
<script lang="ts"> <script lang="ts">
import { IntlString } from '@hcengineering/platform'
import emojiRegex from 'emoji-regex' import emojiRegex from 'emoji-regex'
import { createEventDispatcher, getContext } from 'svelte' import { createEventDispatcher, getContext } from 'svelte'
import { tooltip } from '../tooltips' import { IntlString } from '@hcengineering/platform'
import { AnySvelteComponent, emojiSP } from '../types'
import Label from './Label.svelte' import Label from './Label.svelte'
import Scroller from './Scroller.svelte' import Scroller from './Scroller.svelte'
import Emoji from './icons/Emoji.svelte' import Emoji from './icons/Emoji.svelte'
@ -13,23 +12,13 @@
import Places from './icons/Places.svelte' import Places from './icons/Places.svelte'
import Symbols from './icons/Symbols.svelte' import Symbols from './icons/Symbols.svelte'
import Work from './icons/Work.svelte' import Work from './icons/Work.svelte'
import { tooltip } from '../tooltips'
import { AnySvelteComponent, emojiSP } from '../types'
import plugin from '../plugin' import plugin from '../plugin'
export let embedded = false export let embedded = false
let div: HTMLDivElement
const regex = emojiRegex()
const { currentFontSize } = getContext('fontsize') as { currentFontSize: string }
function getEmojis (startCode: number, endCode: number, postfix?: number[]): (string | undefined)[] {
return [...Array(endCode - startCode + 1).keys()].map((v) => {
const str = postfix ? String.fromCodePoint(v + startCode, ...postfix) : String.fromCodePoint(v + startCode)
if ([...str.matchAll(regex)].length > 0) return str
return undefined
})
}
interface Category { interface Category {
id: string id: string
label: IntlString label: IntlString
@ -37,6 +26,13 @@
icon: AnySvelteComponent icon: AnySvelteComponent
} }
let scrollElement: HTMLDivElement
const regex = emojiRegex()
const dispatch = createEventDispatcher()
const { currentFontSize } = getContext('fontsize') as { currentFontSize: string }
const emojiRowHeightPx = (currentFontSize === 'small-font' ? 14 : 16) * 2
const categories: Category[] = [ const categories: Category[] = [
{ {
id: 'work', id: 'work',
@ -106,21 +102,41 @@
icon: Symbols icon: Symbols
} }
] ]
const dispatch = createEventDispatcher()
let currentCategory = categories[0]
function getEmojis (startCode: number, endCode: number, postfix?: number[]): (string | undefined)[] {
return [...Array(endCode - startCode + 1).keys()].map((v) => {
const str = postfix ? String.fromCodePoint(v + startCode, ...postfix) : String.fromCodePoint(v + startCode)
if ([...str.matchAll(regex)].length > 0) return str
return undefined
})
}
function handleScrollToCategory (categoryId: string) { function handleScrollToCategory (categoryId: string) {
const el = document.getElementById(categoryId) const labelElement = document.getElementById(categoryId)
if (el) {
const next = el.nextElementSibling as HTMLElement if (labelElement) {
div.scroll(0, next.offsetTop - (currentFontSize === 'small-font' ? 14 : 16) * 1.75) const emojisElement = labelElement.nextElementSibling as HTMLElement
scrollElement.scroll(0, emojisElement.offsetTop - (currentFontSize === 'small-font' ? 14 : 16) * 1.75)
} }
} }
let currentCategory = categories[0] function handleCategoryScrolled () {
function handleScrolled (catId?: CustomEvent) { const selectedCategory = categories.find((category) => {
if (catId) { const labelElement = document.getElementById(category.id)
const curCat = categories.find((it) => it.id === catId.detail[catId.detail.length - 1])
if (curCat) currentCategory = curCat if (!labelElement) {
return false
}
const emojisElement = labelElement.nextElementSibling as HTMLElement
return emojisElement.offsetTop + emojisElement.offsetHeight - emojiRowHeightPx > scrollElement.scrollTop
})
if (selectedCategory) {
currentCategory = selectedCategory
} }
} }
</script> </script>
@ -130,17 +146,27 @@
{#each categories as category} {#each categories as category}
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<div <div
use:tooltip={{ label: category.label }}
class="element" class="element"
class:selected={currentCategory === category} class:selected={currentCategory.id === category.id}
use:tooltip={{ label: category.label }}
on:click={() => handleScrollToCategory(category.id)} on:click={() => handleScrollToCategory(category.id)}
> >
<svelte:component this={category.icon} size={'medium'} opacity={currentCategory === category ? '1' : '0.3'} /> <svelte:component
this={category.icon}
size="medium"
opacity={currentCategory.id === category.id ? '1' : '0.3'}
/>
</div> </div>
{/each} {/each}
</div> </div>
<div class="scrolling"> <div class="scrolling">
<Scroller bind:divScroll={div} on:scrolledCategories={handleScrolled} fade={emojiSP} noStretch checkForHeaders> <Scroller
bind:divScroll={scrollElement}
fade={emojiSP}
noStretch
checkForHeaders
on:scrolledCategories={handleCategoryScrolled}
>
{#each categories as category} {#each categories as category}
<div id={category.id} class="scroll-header categoryHeader"> <div id={category.id} class="scroll-header categoryHeader">
<Label label={category.label} /> <Label label={category.label} />
@ -163,14 +189,17 @@
.popup { .popup {
height: 21.25rem; height: 21.25rem;
} }
.scrolling { .scrolling {
min-height: 0; min-height: 0;
height: 16.5rem; height: 16.5rem;
max-height: 16.5rem; max-height: 16.5rem;
} }
.popup-header { .popup-header {
margin: 0.75rem 0.75rem 0.5rem; margin: 0.75rem 0.75rem 0.5rem;
} }
.scroll-header { .scroll-header {
position: sticky; position: sticky;
flex-shrink: 0; flex-shrink: 0;
@ -184,16 +213,19 @@
color: var(--theme-caption-color); color: var(--theme-caption-color);
background-color: var(--theme-popup-header); background-color: var(--theme-popup-header);
border-radius: 0.25rem; border-radius: 0.25rem;
&:first-child { &:first-child {
margin-top: 0; margin-top: 0;
} }
} }
.palette { .palette {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
// width: 19.25rem; // width: 19.25rem;
font-size: 1.25rem; font-size: 1.25rem;
} }
.element { .element {
display: flex; display: flex;
justify-content: center; justify-content: center;