Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(action-menu): fix toggle logic when action-menu is reconnected #11139

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting";
import { describe, expect, it } from "vitest";
import { E2EPage, newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting";
import { beforeEach, describe, expect, it } from "vitest";
import { html } from "../../../support/formatting";
import {
accessible,
Expand Down Expand Up @@ -202,6 +202,53 @@ describe("calcite-action-menu", () => {
await isElementFocused(page, focusTargetSelector);
});

describe("adding/removing from DOM", () => {
let page: E2EPage;

beforeEach(async (): Promise<void> => {
page = await newE2EPage();
await skipAnimations(page);
});

async function testToggle(triggerSelector: string): Promise<void> {
await page.evaluate(() => {
const actionMenu = document.querySelector("calcite-action-menu");
actionMenu.remove();
document.body.append(actionMenu);
});
await page.waitForChanges();

const trigger = await page.find(triggerSelector);
await trigger.click();

const actionMenu = await page.find("calcite-action-menu");
expect(await actionMenu.getProperty("open")).toBe(true);
}

it("should toggle with default trigger", async () => {
await page.setContent(html`
<calcite-action-menu>
<calcite-action text="Add" icon="plus" text-enabled></calcite-action>
<calcite-action text="Remove" icon="minus" text-enabled></calcite-action>
<calcite-action text="Banana" icon="banana" text-enabled></calcite-action>
</calcite-action-menu>
`);
await testToggle(`calcite-action-menu >>> .${CSS.defaultTrigger}`);
});

it("should toggle with slotted trigger", async () => {
await page.setContent(html`
<calcite-action-menu>
<calcite-action id="trigger" slot="${SLOTS.trigger}" text="Toggle" icon="toggle"></calcite-action>
<calcite-action text="Add" icon="plus" text-enabled></calcite-action>
<calcite-action text="Remove" icon="minus" text-enabled></calcite-action>
<calcite-action text="Banana" icon="banana" text-enabled></calcite-action>
</calcite-action-menu>
`);
await testToggle("#trigger");
});
});

it("should honor scale of expand icon", async () => {
const page = await newE2EPage({ html: `<calcite-action-menu scale="l"></calcite-action-menu>` });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ export class ActionMenu extends LitElement implements LoadableComponent {
"keydown",
this.menuButtonKeyDown,
) /* TODO: [MIGRATION] If possible, refactor to use on* JSX prop or this.listen()/this.listenOn() utils - they clean up event listeners automatically, thus prevent memory leaks */;

this.menuButtonEl = null;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clearing this reference would cause connectMenuButtonEl to bail since the references would remain the same.

}

private setMenuButtonEl(event: Event): void {
Expand All @@ -334,7 +336,10 @@ export class ActionMenu extends LitElement implements LoadableComponent {

private setDefaultMenuButtonEl(el: Action["el"]): void {
this.defaultMenuButtonEl = el;
this.connectMenuButtonEl();

if (el) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a lot of components might need this kind of if statement since this is similar to some other fixes 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I created #11093 to take a closer look, but it might be easier for the time being to return early when the reference element is null in all cases (preserves existing component logic based on Stencil lifecycle). WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think that might be the easiest and most consistent solution.

this.connectMenuButtonEl();
}
}

private setPopoverEl(el: Popover["el"]): void {
Expand Down
Loading