diff --git a/packages/calcite-components/src/components/button/button.e2e.ts b/packages/calcite-components/src/components/button/button.e2e.ts index 604cc470148..3fc1e942a6b 100644 --- a/packages/calcite-components/src/components/button/button.e2e.ts +++ b/packages/calcite-components/src/components/button/button.e2e.ts @@ -644,4 +644,27 @@ describe("calcite-button", () => { expect(button1.textContent.length).toBeLessThan(longText.length); expect(button1.getAttribute("title")).toEqual(longText); }); + + it("should set aria-expanded attribute on shadowDOM element when used as trigger", async () => { + const page = await newE2EPage(); + await page.setContent(html`Info + +

Information

+
`); + + const calciteButton = await page.find("calcite-button"); + const button = await page.find("calcite-button >>> button"); + expect(button.getAttribute("aria-expanded")).toBe("false"); + expect(calciteButton.getAttribute("aria-expanded")).toBe("false"); + + await calciteButton.click(); + await page.waitForChanges(); + expect(button.getAttribute("aria-expanded")).toBe("true"); + expect(calciteButton.getAttribute("aria-expanded")).toBe("true"); + }); }); diff --git a/packages/calcite-components/src/components/button/button.tsx b/packages/calcite-components/src/components/button/button.tsx index 5aa7441aa18..6930f4a1277 100644 --- a/packages/calcite-components/src/components/button/button.tsx +++ b/packages/calcite-components/src/components/button/button.tsx @@ -26,6 +26,11 @@ import { Appearance, FlipContext, Kind, Scale, Width } from "../interfaces"; import { ButtonMessages } from "./assets/button/t9n"; import { ButtonAlignment } from "./interfaces"; import { CSS } from "./resources"; +import { + GlobalAttrComponent, + unwatchGlobalAttributes, + watchGlobalAttributes, +} from "../../utils/globalAttributes"; /** Passing a 'href' will render an anchor link, instead of a button. Role will be set to link, or button, depending on this. */ /** It is the consumers responsibility to add aria information, rel, target, for links, and any button attributes for form submission */ @@ -39,6 +44,7 @@ import { CSS } from "./resources"; }) export class Button implements + GlobalAttrComponent, LabelableComponent, InteractiveComponent, FormOwner, @@ -175,6 +181,7 @@ export class Button connectInteractive(this); connectLocalized(this); connectMessages(this); + watchGlobalAttributes(this, ["aria-expanded"]); this.hasLoader = this.loading; this.setupTextContentObserver(); connectLabel(this); @@ -189,6 +196,7 @@ export class Button disconnectMessages(this); this.resizeObserver?.disconnect(); this.formEl = null; + unwatchGlobalAttributes(this); } async componentWillLoad(): Promise { @@ -268,6 +276,7 @@ export class Button target={childElType === "a" && this.target} title={this.tooltipText} type={childElType === "button" && this.type} + {...this.globalAttributes} > {loaderNode} {this.iconStart ? iconStartEl : null} @@ -344,6 +353,10 @@ export class Button resizeObserver = createObserver("resize", () => this.setTooltipText()); + @State() globalAttributes = { + ariaExpanded: undefined, + }; + //-------------------------------------------------------------------------- // // Private Methods diff --git a/packages/calcite-components/src/utils/globalAttributes.ts b/packages/calcite-components/src/utils/globalAttributes.ts index 0fcde59a844..05f7880eec4 100644 --- a/packages/calcite-components/src/utils/globalAttributes.ts +++ b/packages/calcite-components/src/utils/globalAttributes.ts @@ -1,8 +1,8 @@ import { createObserver } from "./observers"; type AttributeObject = { [k: string]: any }; -type AllowedGlobalAttribute = "lang" | "role"; -const allowedGlobalAttributes = ["lang", "role"]; +type AllowedGlobalAttribute = "lang" | "role" | "aria-expanded"; +const allowedGlobalAttributes = ["lang", "role", "aria-expanded"]; const elementToComponentAndObserverOptionsMap = new Map< HTMLElement,