diff --git a/packages/lexical-playground/__tests__/e2e/Mentions.spec.mjs b/packages/lexical-playground/__tests__/e2e/Mentions.spec.mjs index 86084759c66..e96137d6b4b 100644 --- a/packages/lexical-playground/__tests__/e2e/Mentions.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/Mentions.spec.mjs @@ -16,6 +16,7 @@ import { import { assertHTML, assertSelection, + expect, focusEditor, html, initialize, @@ -1019,4 +1020,17 @@ test.describe('Mentions', () => { focusPath: [0, 1, 0], }); }); + + test(`Sets correct attributes on typeahead menu container`, async ({ + page, + isCollab, + }) => { + test.skip(isCollab); + await focusEditor(page); + await page.keyboard.type('@a'); + + const menuElement = await page.locator('#typeahead-menu'); + expect(await menuElement.getAttribute('aria-label')).toBe('Typeahead menu'); + expect(await menuElement.getAttribute('role')).toBe('listbox'); + }); }); diff --git a/packages/lexical-react/src/shared/LexicalMenu.ts b/packages/lexical-react/src/shared/LexicalMenu.ts index 05fc084eb00..f3da1c9f52d 100644 --- a/packages/lexical-react/src/shared/LexicalMenu.ts +++ b/packages/lexical-react/src/shared/LexicalMenu.ts @@ -480,6 +480,19 @@ export function LexicalMenu({ ); } +function setContainerDivAttributes( + containerDiv: HTMLElement, + className?: string, +) { + if (className != null) { + containerDiv.className = className; + } + containerDiv.setAttribute('aria-label', 'Typeahead menu'); + containerDiv.setAttribute('role', 'listbox'); + containerDiv.style.display = 'block'; + containerDiv.style.position = 'absolute'; +} + export function useMenuAnchorRef( resolution: MenuResolution | null, setResolution: (r: MenuResolution | null) => void, @@ -540,16 +553,10 @@ export function useMenuAnchorRef( } if (!containerDiv.isConnected) { - if (className != null) { - containerDiv.className = className; - } - containerDiv.setAttribute('aria-label', 'Typeahead menu'); - containerDiv.setAttribute('id', 'typeahead-menu'); - containerDiv.setAttribute('role', 'listbox'); - containerDiv.style.display = 'block'; - containerDiv.style.position = 'absolute'; + setContainerDivAttributes(containerDiv, className); parent.append(containerDiv); } + containerDiv.setAttribute('id', 'typeahead-menu'); anchorElementRef.current = containerDiv; rootElement.setAttribute('aria-controls', 'typeahead-menu'); } @@ -573,6 +580,7 @@ export function useMenuAnchorRef( const containerDiv = anchorElementRef.current; if (containerDiv !== null && containerDiv.isConnected) { containerDiv.remove(); + containerDiv.removeAttribute('id'); } }; } @@ -599,7 +607,7 @@ export function useMenuAnchorRef( // Append the context for the menu immediately const containerDiv = anchorElementRef.current; if (containerDiv != null) { - containerDiv.style.position = 'absolute'; + setContainerDivAttributes(containerDiv, className); if (parent != null) { parent.append(containerDiv); }