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): update active selection to not use the action's active property #7911

Merged
merged 5 commits into from
Sep 29, 2023
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
Expand Up @@ -2,7 +2,7 @@ import { newE2EPage } from "@stencil/core/testing";
import { html } from "../../../support/formatting";
import { accessible, defaults, focusable, hidden, reflects, renders, slots } from "../../tests/commonTests";
import { TOOLTIP_OPEN_DELAY_MS } from "../tooltip/resources";
import { CSS, SLOTS } from "./resources";
import { CSS, SLOTS, activeAttr } from "./resources";

describe("calcite-action-menu", () => {
describe("renders", () => {
Expand Down Expand Up @@ -226,6 +226,7 @@ describe("calcite-action-menu", () => {

const actionMenu = await page.find("calcite-action-menu");
const actions = await page.findAll("calcite-action");
const trigger = await page.find(`calcite-action-menu >>> .${CSS.defaultTrigger}`);

expect(await actionMenu.getProperty("open")).toBe(false);

Expand All @@ -236,18 +237,19 @@ describe("calcite-action-menu", () => {
await page.waitForTimeout(0);
await page.waitForChanges();

expect(await trigger.getProperty("active")).toBe(true);
expect(await actionMenu.getProperty("open")).toBe(true);
expect(await actions[0].getProperty("active")).toBe(true);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe("");
Copy link
Member

Choose a reason for hiding this comment

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

For later, but this might be better off as a screenshot test since this is now an internal concern.

Copy link
Member Author

Choose a reason for hiding this comment

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

Screenshot tests will already capture the styles for this but this is a nice to test the keyboard navigation.

expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("ArrowDown");
await page.waitForTimeout(0);
await page.waitForChanges();

expect(await actions[0].getProperty("active")).toBe(false);
expect(await actions[1].getProperty("active")).toBe(true);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe(null);
expect(actions[1].getAttribute(activeAttr)).toBe("");
expect(actions[2].getAttribute(activeAttr)).toBe(null);
});

it("should handle ArrowUp navigation", async () => {
Expand All @@ -263,8 +265,10 @@ describe("calcite-action-menu", () => {

const actionMenu = await page.find("calcite-action-menu");
const actions = await page.findAll("calcite-action");
const trigger = await page.find(`calcite-action-menu >>> .${CSS.defaultTrigger}`);

expect(await actionMenu.getProperty("open")).toBe(false);
expect(await trigger.getProperty("active")).toBe(false);

await actionMenu.callMethod("setFocus");
await page.waitForChanges();
Expand All @@ -273,18 +277,19 @@ describe("calcite-action-menu", () => {
await page.waitForTimeout(0);
await page.waitForChanges();

expect(await trigger.getProperty("active")).toBe(true);
expect(await actionMenu.getProperty("open")).toBe(true);
expect(await actions[0].getProperty("active")).toBe(false);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(true);
expect(actions[0].getAttribute(activeAttr)).toBe(null);
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe("");

await page.keyboard.press("ArrowUp");
await page.waitForTimeout(0);
await page.waitForChanges();

expect(await actions[0].getProperty("active")).toBe(false);
expect(await actions[1].getProperty("active")).toBe(true);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe(null);
expect(actions[1].getAttribute(activeAttr)).toBe("");
expect(actions[2].getAttribute(activeAttr)).toBe(null);
});

it("should handle Enter, Home, End and ESC navigation", async () => {
Expand All @@ -300,8 +305,10 @@ describe("calcite-action-menu", () => {

const actionMenu = await page.find("calcite-action-menu");
const actions = await page.findAll("calcite-action");
const trigger = await page.find(`calcite-action-menu >>> .${CSS.defaultTrigger}`);

expect(await actionMenu.getProperty("open")).toBe(false);
expect(await trigger.getProperty("active")).toBe(false);

await actionMenu.callMethod("setFocus");
await page.waitForChanges();
Expand All @@ -310,39 +317,41 @@ describe("calcite-action-menu", () => {
await page.waitForChanges();

expect(await actionMenu.getProperty("open")).toBe(true);
expect(await actions[0].getProperty("active")).toBe(true);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(false);
expect(await trigger.getProperty("active")).toBe(true);
expect(actions[0].getAttribute(activeAttr)).toBe("");
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("ArrowDown");

await page.waitForChanges();

expect(await actions[0].getProperty("active")).toBe(false);
expect(await actions[1].getProperty("active")).toBe(true);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe(null);
expect(actions[1].getAttribute(activeAttr)).toBe("");
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("Home");

await page.waitForChanges();

expect(await actions[0].getProperty("active")).toBe(true);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe("");
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("End");

await page.waitForChanges();

expect(await actions[0].getProperty("active")).toBe(false);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(true);
expect(actions[0].getAttribute(activeAttr)).toBe(null);
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe("");

await page.keyboard.press("Escape");

await page.waitForChanges();

expect(await actionMenu.getProperty("open")).toBe(false);
expect(await trigger.getProperty("active")).toBe(false);
});

it("should handle TAB navigation", async () => {
Expand All @@ -368,9 +377,9 @@ describe("calcite-action-menu", () => {
await page.waitForChanges();

expect(await actionMenu.getProperty("open")).toBe(true);
expect(await actions[0].getProperty("active")).toBe(true);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe("");
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("Tab");

Expand Down Expand Up @@ -404,9 +413,9 @@ describe("calcite-action-menu", () => {
const clickSpy = await actions[0].spyOnEvent("click");

expect(await actionMenu.getProperty("open")).toBe(true);
expect(await actions[0].getProperty("active")).toBe(true);
expect(await actions[1].getProperty("active")).toBe(false);
expect(await actions[2].getProperty("active")).toBe(false);
expect(actions[0].getAttribute(activeAttr)).toBe("");
expect(actions[1].getAttribute(activeAttr)).toBe(null);
expect(actions[2].getAttribute(activeAttr)).toBe(null);

await page.keyboard.press("Enter");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
flex;
}

.menu ::slotted(calcite-action[active]) {
.menu ::slotted(calcite-action[data-active]) {
@apply focus-outset;
outline-offset: 0px;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,32 @@ export const open = (): string =>
<calcite-action text="Table" icon="table" text-enabled></calcite-action>
</calcite-action-menu>
`;

export const keyDownOpen_TestOnly = (): string =>
html`
<calcite-action-menu>
<calcite-action slot="trigger" text="Add" icon="banana"></calcite-action>
<calcite-action text="Plus" icon="plus" text-enabled></calcite-action>
<calcite-action text="Minus" icon="minus" text-enabled></calcite-action>
<calcite-action text="Table" icon="table" text-enabled></calcite-action>
</calcite-action-menu>
<script>
document
.querySelector("calcite-action-menu")
.setFocus()
.then(() => {
document.querySelector("calcite-action[slot=trigger]").dispatchEvent(
new KeyboardEvent("keydown", {
code: "Enter",
key: "Enter",
charCode: 13,
keyCode: 13,
view: window,
bubbles: true,
})
);
});
</script>
`;

keyDownOpen_TestOnly.parameters = { chromatic: { delay: 1000 } };
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
setUpLoadableComponent,
} from "../../utils/loadable";
import { Appearance, Scale } from "../interfaces";
import { CSS, ICONS, SLOTS } from "./resources";
import { activeAttr, CSS, ICONS, SLOTS } from "./resources";

const SUPPORTED_MENU_NAV_KEYS = ["ArrowUp", "ArrowDown", "End", "Home"];

Expand Down Expand Up @@ -388,7 +388,8 @@ export class ActionMenu implements LoadableComponent {
action.id = id;
}

action.active = index === activeMenuItemIndex;
// data attribute is used to style the "activeMenuItemIndex" action using token focus styling.
action.toggleAttribute(activeAttr, index === activeMenuItemIndex);
};

updateActions = (actions: HTMLCalciteActionElement[]): void => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export const SLOTS = {
export const ICONS = {
menu: "ellipsis",
};

export const activeAttr = "data-active";
Loading