Skip to content
Open
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 @@ -31,12 +31,18 @@ import Chevron from "../../assets/chevron-icon.svg";
},
})
export class MenuItem {
private buttonEl?: HTMLIcButtonElement;

@Element() el: HTMLIcMenuItemElement;

/**
* If `true`, the menu item will be in a checked state. This is only applicable when variant is set to `toggle`.
*/
@Prop({ mutable: true, reflect: true }) checked?: boolean = false;
@Watch("checked")
watchCheckedHandler(): void {
this.updateButtonAccessibilityAttributes();
}

/**
* The description displayed in the menu item, below the label.
Expand Down Expand Up @@ -97,6 +103,10 @@ export class MenuItem {
*/
@Prop({ mutable: true, reflect: true }) variant?: IcMenuItemVariants =
"default";
@Watch("variant")
watchVariantHandler(): void {
this.updateButtonAccessibilityAttributes();
}

/**
* If `true`, the menu will close when this menu item is clicked.
Expand Down Expand Up @@ -138,8 +148,27 @@ export class MenuItem {
[{ prop: this.label, propName: "label" }],
"Menu Item"
);
this.updateButtonAccessibilityAttributes();
}

componentDidUpdate(): void {
this.updateButtonAccessibilityAttributes();
}

private updateButtonAccessibilityAttributes = (): void => {
const button =
this.buttonEl?.shadowRoot?.querySelector<HTMLElement>(".button");
if (!button) return;

if (this.variant === "toggle") {
button.setAttribute("role", "menuitemcheckbox");
button.setAttribute("aria-checked", `${!!this.checked}`);
} else {
button.removeAttribute("role");
button.removeAttribute("aria-checked");
}
};

@Listen("click", { capture: true })
handleHostClick(e: Event): void {
if (this.disabled) {
Expand Down Expand Up @@ -235,16 +264,10 @@ export class MenuItem {
target={isPropDefined(this.target)}
rel={isPropDefined(this.rel)}
referrerpolicy={this.referrerpolicy}
role={this.variant === "toggle" ? "menuitemcheckbox" : "menuitem"}
role={this.variant === "toggle" ? undefined : "menuitem"}
aria-disabled={`${this.disabled}`}
aria-checked={
this.variant === "toggle"
? this.checked
? "true"
: "false"
: undefined
}
aria-label={this.getMenuItemAriaLabel()}
ref={(el) => (this.buttonEl = el)}
aria-haspopup={
isPropDefined(this.submenuTriggerFor) ||
this.el.classList.contains("ic-popover-submenu-back-button")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ exports[`menu item variants should render the disabled variant: disabled-removed
exports[`menu item variants should render the toggle variant 1`] = `
<ic-menu-item class="ic-menu-item-variant-toggle" id="test-menu-item" label="Toggle variant" variant="toggle">
<template shadowrootmode="open">
<ic-button aria-checked="false" class="ic-button-full-width ic-button-size-medium ic-button-variant-tertiary" exportparts="button" role="menuitemcheckbox">
<ic-button class="ic-button-full-width ic-button-size-medium ic-button-variant-tertiary" exportparts="button">
<template shadowrootmode="open">
<button aria-disabled="false" aria-label="Toggle variant" class="button" part="button" tabindex="0" type="button">
<button aria-checked="false" aria-disabled="false" aria-label="Toggle variant" class="button" part="button" role="menuitemcheckbox" tabindex="0" type="button">
<slot></slot>
</button>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,23 @@ describe("menu item variants", () => {
expect(page.rootInstance.variant).toMatch("toggle");
expect(page.rootInstance.checked).toBeFalsy();

const button = page.root?.shadowRoot
?.querySelector("li > ic-button")
?.shadowRoot?.querySelector("button");
const buttonComponent = page.root?.shadowRoot?.querySelector("ic-button");
let button = buttonComponent?.shadowRoot?.querySelector("button");

button?.click();
await page.waitForChanges;
expect(button?.getAttribute("role")).toBe("menuitemcheckbox");
expect(button?.getAttribute("aria-checked")).toBe("false");
expect(
page.root?.shadowRoot?.querySelector("ic-button")?.getAttribute("role")
).toBeNull();

buttonComponent?.click();
await page.waitForChanges();

button = buttonComponent?.shadowRoot?.querySelector("button");

expect(button?.getAttribute("role")).toBe("menuitemcheckbox");
expect(button?.getAttribute("aria-checked")).toBe("true");
expect(page.rootInstance.checked).toBeTruthy();
});

it("should render the destructive variant", async () => {
Expand Down