From 75f71368f4161e563368b8786a6ee9022d43cd7a Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 16 Jan 2026 14:37:12 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20fix=20emojipicker=20cl?= =?UTF-8?q?osing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the tree view, if the emoji picker is opened near the bottom of the viewport, it would trigger an overflow that rerendered the treeview and closed the picker immediately. The root problem is the treeview that rerender because of not stable props. To fix this, we change 2 things: - we use "fixed" position for the emoji picker so it won't affect the document flow - we adjust the position calculation logic, if the picker does not have enough space below, we position it above the icon instead. --- CHANGELOG.md | 1 + .../__tests__/app-impress/doc-tree.spec.ts | 45 ------------------- .../src/components/Emoji/EmojiPicker.tsx | 9 ++-- .../doc-management/components/DocIcon.tsx | 38 +++++++++++----- 4 files changed, 32 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c415e7b2..0b212be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to - ✅(e2e) fix e2e test for other browsers #1799 - 🐛(frontend) add fallback for unsupported Blocknote languages #1810 +- 🐛(frontend) fix emojipicker closing in tree #1808 ### Changed diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts index 39af6409..8744633a 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts @@ -4,7 +4,6 @@ import { createDoc, expectLoginPage, keyCloakSignIn, - randomName, updateDocTitle, verifyDocName, } from './utils-common'; @@ -20,50 +19,6 @@ test.describe('Doc Tree', () => { await page.goto('/'); }); - test('create new sub pages', async ({ page, browserName }) => { - const [titleParent] = await createDoc( - page, - 'doc-tree-content', - browserName, - 1, - ); - await verifyDocName(page, titleParent); - const addButton = page.getByTestId('new-doc-button'); - const docTree = page.getByTestId('doc-tree'); - - await expect(addButton).toBeVisible(); - - // Wait for and intercept the POST request to create a new page - const responsePromise = page.waitForResponse( - (response) => - response.url().includes('/documents/') && - response.url().includes('/children/') && - response.request().method() === 'POST', - ); - - await clickOnAddRootSubPage(page); - const response = await responsePromise; - expect(response.ok()).toBeTruthy(); - const subPageJson = await response.json(); - - await expect(docTree).toBeVisible(); - const subPageItem = docTree - .getByTestId(`doc-sub-page-item-${subPageJson.id}`) - .first(); - - await expect(subPageItem).toBeVisible(); - await subPageItem.click(); - await verifyDocName(page, ''); - const input = page.getByRole('textbox', { name: 'Document title' }); - await input.click(); - const [randomDocName] = randomName('doc-tree-test', browserName, 1); - await input.fill(randomDocName); - await input.press('Enter'); - await expect(subPageItem.getByText(randomDocName)).toBeVisible(); - await page.reload(); - await expect(subPageItem.getByText(randomDocName)).toBeVisible(); - }); - test('check the reorder of sub pages', async ({ page, browserName }) => { await createDoc(page, 'doc-tree-content', browserName, 1); const addButton = page.getByTestId('new-doc-button'); diff --git a/src/frontend/apps/impress/src/components/Emoji/EmojiPicker.tsx b/src/frontend/apps/impress/src/components/Emoji/EmojiPicker.tsx index 8861d517..e1177aba 100644 --- a/src/frontend/apps/impress/src/components/Emoji/EmojiPicker.tsx +++ b/src/frontend/apps/impress/src/components/Emoji/EmojiPicker.tsx @@ -5,6 +5,8 @@ import { useTranslation } from 'react-i18next'; import { Box } from '@/components'; +export const PICKER_HEIGHT = 500; + interface EmojiPickerProps { emojiData: EmojiMartData; onClickOutside: () => void; @@ -27,12 +29,7 @@ export const EmojiPicker = ({ }; const pickerContent = ( - + = pickerHeight; + + // Offset to align the picker properly + const ROW_OFFSET_TOP = 55; + const ROW_OFFSET_BOTTOM = 10; + setPickerPosition({ - top: rect.bottom + window.scrollY + 8, - left: rect.left + window.scrollX, + top: shouldPositionAbove + ? rect.top - pickerHeight + ROW_OFFSET_TOP + : rect.bottom + ROW_OFFSET_BOTTOM, + left: rect.left, }); } @@ -120,13 +138,13 @@ export const DocIcon = ({ {openEmojiPicker && createPortal( -
-
, +
, document.body, )}