diff --git a/packages/main/cypress/specs/base/AccessibilityTextsHelper.cy.tsx b/packages/main/cypress/specs/base/AccessibilityTextsHelper.cy.tsx index 04dd22632446..bc7c98f40c8b 100644 --- a/packages/main/cypress/specs/base/AccessibilityTextsHelper.cy.tsx +++ b/packages/main/cypress/specs/base/AccessibilityTextsHelper.cy.tsx @@ -1,6 +1,7 @@ import Label from "../../../src/Label.js"; import Input from "../../../src/Input.js"; import List from "../../../src/List.js"; +import Button from "../../../src/Button.js"; describe("AccessibilityTextsHelper", () => { it("Label-for tests", () => { @@ -465,4 +466,42 @@ describe("AccessibilityTextsHelper", () => { cy.get("@list") .should("have.attr", "aria-description", "Desc3"); }); + + it("Button accessibleNameRef Tests", () => { + cy.mount( + <> + + + + + ); + + // assert - both buttons should have the same aria-label + cy.get("#btn1") + .shadow() + .find("button") + .should("have.attr", "aria-label", "Counter value is 0"); + + cy.get("#btn2") + .shadow() + .find("button") + .should("have.attr", "aria-label", "Counter value is 0"); + + // act - update text of referenced label (simulating counter increment) + cy.get("#lblCounter") + .then($el => { + $el.get(0).innerHTML = "Counter value is 3"; + }); + + // assert - both buttons should update their aria-label + cy.get("#btn1") + .shadow() + .find("button") + .should("have.attr", "aria-label", "Counter value is 3"); + + cy.get("#btn2") + .shadow() + .find("button") + .should("have.attr", "aria-label", "Counter value is 3"); + }); }); diff --git a/packages/main/src/Button.ts b/packages/main/src/Button.ts index 472add2425d4..277544a53b63 100644 --- a/packages/main/src/Button.ts +++ b/packages/main/src/Button.ts @@ -13,7 +13,11 @@ import { isShift, isSpaceShift, } from "@ui5/webcomponents-base/dist/Keys.js"; -import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; +import { + getAllAccessibleNameRefTexts, + registerUI5Element, + deregisterUI5Element, +} from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import type { AccessibilityAttributes, AriaRole } from "@ui5/webcomponents-base"; import type { ITabbable } from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; @@ -375,6 +379,13 @@ class Button extends UI5Element implements IButton { @property({ type: Boolean, noAttribute: true }) _isSpacePressed = false; + /** + * Constantly updated value of texts collected from the accessibleNameRef elements + * @private + */ + @property({ noAttribute: true }) + _accessibleNameRefTexts?: string; + /** * Defines the text of the component. * @@ -443,6 +454,12 @@ class Button extends UI5Element implements IButton { this.addEventListener("click", this._onclickBound); this._clickHandlerAttached = true; } + + registerUI5Element(this, this._updateAccessibleNameRefTexts.bind(this)); + } + + _updateAccessibleNameRefTexts() { + this._accessibleNameRefTexts = getAllAccessibleNameRefTexts(this); } onExitDOM() { @@ -454,6 +471,8 @@ class Button extends UI5Element implements IButton { if (activeButton === this) { activeButton = null; } + + deregisterUI5Element(this); } async onBeforeRendering() { @@ -655,7 +674,8 @@ class Button extends UI5Element implements IButton { } get ariaLabelText() { - const effectiveAriaLabelText = getEffectiveAriaLabelText(this) || ""; + // Use accessibleNameRef texts (cached), then accessibleName (direct), then textContent as fallback + const effectiveAriaLabelText = this._accessibleNameRefTexts || this.accessibleName || ""; const textContent = this.textContent || ""; const internalLabelText = this.effectiveBadgeDescriptionText || "";