diff --git a/packages/core/src/components/dropdown/dropdown-controller.ts b/packages/core/src/components/dropdown/dropdown-controller.ts index 072fcbd741d..7b6cf6c79e8 100644 --- a/packages/core/src/components/dropdown/dropdown-controller.ts +++ b/packages/core/src/components/dropdown/dropdown-controller.ts @@ -96,10 +96,10 @@ class DropdownController { } } - dismissAll(includeUids?: string[]) { + dismissAll(ignoreBehaviorForIds: string[] = []) { this.dropdowns.forEach((dropdown) => { if ( - !includeUids?.includes(dropdown.getId()) && + !ignoreBehaviorForIds.includes(dropdown.getId()) && (dropdown.closeBehavior === 'inside' || dropdown.closeBehavior === false) ) { @@ -115,7 +115,6 @@ class DropdownController { this.dropdowns.forEach((dropdown) => { if ( - dropdown.isPresent() && dropdown.closeBehavior !== 'inside' && dropdown.closeBehavior !== false && !path.has(dropdown.getId()) @@ -126,10 +125,15 @@ class DropdownController { } pathIncludesTrigger(eventTargets: EventTarget[]) { - return !!eventTargets.find( - (element: HTMLElement) => - !!element.hasAttribute?.('data-ix-dropdown-trigger') - ); + for (let eventTarget of eventTargets) { + if (eventTarget instanceof HTMLElement) { + if (eventTarget.hasAttribute('data-ix-dropdown-trigger')) { + return true; + } + } + } + + return false; } private pathIncludesDropdown(eventTargets: EventTarget[]) { diff --git a/packages/core/src/components/dropdown/dropdown.tsx b/packages/core/src/components/dropdown/dropdown.tsx index 4f8e0d45dd7..9f235b127b1 100644 --- a/packages/core/src/components/dropdown/dropdown.tsx +++ b/packages/core/src/components/dropdown/dropdown.tsx @@ -213,10 +213,16 @@ export class Dropdown implements ComponentInterface, DropdownInterface { this.triggerElement, 'click', (event: PointerEvent) => { - if (!event.defaultPrevented) toggleController(); + if (!event.defaultPrevented) { + toggleController(); + } } ); - this.triggerElement.setAttribute('data-ix-dropdown-trigger', this.localUId); + + this.triggerElement?.setAttribute( + 'data-ix-dropdown-trigger', + this.localUId + ); } /** @internal */ @@ -255,8 +261,6 @@ export class Dropdown implements ComponentInterface, DropdownInterface { const dropdownItem = await element.getDropdownItemElement(); dropdownItem.isSubMenu = true; this.hostElement.style.zIndex = `var(--theme-z-index-dropdown)`; - - return dropdownItem; } if (element.tagName === 'IX-DROPDOWN-ITEM') { @@ -419,7 +423,9 @@ export class Dropdown implements ComponentInterface, DropdownInterface { if (dropdownController.pathIncludesTrigger(event.composedPath())) { event.preventDefault(); - if (this.isTriggerElement(event.target as HTMLElement)) return; + if (this.isTriggerElement(event.target as HTMLElement)) { + return; + } } if (this.closeBehavior === 'inside' || this.closeBehavior === 'both') { diff --git a/packages/core/src/components/menu-avatar-item/test/menu-avatar-item.ct.ts b/packages/core/src/components/menu-avatar-item/test/menu-avatar-item.ct.ts new file mode 100644 index 00000000000..cedc35bab4c --- /dev/null +++ b/packages/core/src/components/menu-avatar-item/test/menu-avatar-item.ct.ts @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2023 Siemens AG + * + * SPDX-License-Identifier: MIT + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import { expect } from '@playwright/test'; +import { test } from '@utils/test'; + +const html = String.raw; + +test('Nested dropdowns', async ({ mount, page }) => { + await mount(html` + + + + + + + SubMenuItem 1 + SubMenuItem 2 + SubMenuItem 3 + SubMenuItem 4 + + + SubMenuItem 1 + SubMenuItem 2 + SubMenuItem 3 + SubMenuItem 4 + + `); + + const menuAvatar = page.locator('ix-menu-avatar'); + await expect(menuAvatar).toBeVisible(); + await menuAvatar.click(); + + await expect(menuAvatar.locator('ix-dropdown')).toBeVisible(); + + const menuAvatarItem = menuAvatar.locator('ix-menu-avatar-item').nth(0); + await menuAvatarItem.click(); + + const dropdown1 = page.locator('#d1'); + const dropdown2 = page.locator('#d2'); + + await expect(dropdown1).toBeVisible(); + + const dropdown2Trigger = dropdown1 + .locator('ix-dropdown-item') + .filter({ hasText: 'SubMenuItem 4' }); + await dropdown2Trigger.click(); + + await expect(dropdown2).toBeVisible(); +});