From 17eb2997c53f2b429b43b305f1361f2ebde4d392 Mon Sep 17 00:00:00 2001 From: Iliana Bobeva Date: Tue, 4 Nov 2025 17:25:05 +0200 Subject: [PATCH 1/4] feat(ui5-select): implement accessibilityInfo getter --- packages/main/cypress/specs/Select.cy.tsx | 76 ++++++++++++++++++++++- packages/main/src/Select.ts | 16 ++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/packages/main/cypress/specs/Select.cy.tsx b/packages/main/cypress/specs/Select.cy.tsx index f8876d4bd9d7..028c47b07bbf 100644 --- a/packages/main/cypress/specs/Select.cy.tsx +++ b/packages/main/cypress/specs/Select.cy.tsx @@ -513,6 +513,80 @@ describe("Select - Accessibility", () => { .find(".ui5-select-label-root") .should("contain.text", "SelectedOption – ExtraInfo"); }); + + it("tests accessibilityInfo getter returns correct values", () => { + cy.mount( + <> + Reference Label + {/* Basic select with selected option */} + + + {/* Select with accessibleName */} + + + {/* Select with accessibleNameRef */} + + + {/* Select with readonly and required attributes */} + + + ); + + // Test basic select + cy.get("#basicSelect").then(($select) => { + const select = $select[0] as Select; + const accessInfo = select.accessibilityInfo; + + expect(accessInfo.role).to.equal("combobox"); + expect(accessInfo.type).to.equal("listbox"); + expect(accessInfo.readonly).to.be.false; + expect(accessInfo.required).to.be.false; + expect(accessInfo.description).to.equal("Option 1"); // Just text since no aria-label + }); + + // Test select with accessibleName + cy.get("#namedSelect").then(($select) => { + const select = $select[0] as Select; + const accessInfo = select.accessibilityInfo; + + expect(accessInfo.description).to.equal("Select Name Option 1"); + }); + + // Test select with accessibleNameRef + cy.get("#refSelect").then(($select) => { + const select = $select[0] as Select; + const accessInfo = select.accessibilityInfo; + + expect(accessInfo.description).to.equal("Reference Label Option 1"); + }); + + // Test select with readonly and required properties + cy.get("#propsSelect").then(($select) => { + const select = $select[0] as Select; + const accessInfo = select.accessibilityInfo; + + expect(accessInfo.readonly).to.be.true; + expect(accessInfo.required).to.be.true; + }); + + // Update the referenced label and check if the description updates + cy.get("#labelRef").invoke("text", "Updated Reference"); + cy.get("#refSelect").then(($select) => { + const select = $select[0] as Select; + const accessInfo = select.accessibilityInfo; + + expect(accessInfo.description).to.equal("Updated Reference Option 1"); + }); + }); }); describe("Select - Popover", () => { @@ -1740,4 +1814,4 @@ describe("Select general interaction", () => { .should("have.attr", "selected"); cy.get("[ui5-select]").should("have.prop", "value", "C"); }); -}); \ No newline at end of file +}); diff --git a/packages/main/src/Select.ts b/packages/main/src/Select.ts index 0101bdc362bb..64b892df1f41 100644 --- a/packages/main/src/Select.ts +++ b/packages/main/src/Select.ts @@ -34,7 +34,7 @@ import "@ui5/webcomponents-icons/dist/information.js"; import { isPhone } from "@ui5/webcomponents-base/dist/Device.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; -import type { Timeout } from "@ui5/webcomponents-base/dist/types.js"; +import type { Timeout, AriaRole } from "@ui5/webcomponents-base/dist/types.js"; import InvisibleMessageMode from "@ui5/webcomponents-base/dist/types/InvisibleMessageMode.js"; import { getScopedVarName } from "@ui5/webcomponents-base/dist/CustomElementsScope.js"; import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; @@ -1174,6 +1174,20 @@ class Select extends UI5Element implements IFormInputElement { return ids.length ? ids.join(" ") : undefined; } + get accessibilityInfo() { + const description = this.ariaLabelText + ? `${this.ariaLabelText}${this.text ? ` ${this.text}` : ""}` + : this.text || ""; + + return { + role: "combobox" as AriaRole, + type: "listbox", + readonly: this.readonly, + required: this.required, + description, + }; + } + _updateAssociatedLabelsTexts() { this._associatedDescriptionRefTexts = getAllAccessibleDescriptionRefTexts(this); } From 685ff22a66e096880e59c44bcaae91b3e9081f9d Mon Sep 17 00:00:00 2001 From: Iliana Bobeva Date: Wed, 5 Nov 2025 16:06:09 +0200 Subject: [PATCH 2/4] chore: fix lint errors --- packages/main/src/Select.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/main/src/Select.ts b/packages/main/src/Select.ts index ad2f7770cc0b..6255c293f2f8 100644 --- a/packages/main/src/Select.ts +++ b/packages/main/src/Select.ts @@ -1174,10 +1174,10 @@ class Select extends UI5Element implements IFormInputElement { return ids.length ? ids.join(" ") : undefined; } - get accessibilityInfo() { - const description = this.ariaLabelText - ? `${this.ariaLabelText}${this.text ? ` ${this.text}` : ""}` - : this.text || ""; + get accessibilityInfo() { + const description = this.ariaLabelText + ? `${this.ariaLabelText}${this.text ? ` ${this.text}` : ""}` + : this.text || ""; return { role: "combobox" as AriaRole, From 182fdf079f1c41df5d235caeff7c8305b57d6dab Mon Sep 17 00:00:00 2001 From: Iliana Bobeva Date: Mon, 17 Nov 2025 17:07:43 +0200 Subject: [PATCH 3/4] chore: make type translatable and add missing disabled property --- packages/main/cypress/specs/Select.cy.tsx | 5 +++-- packages/main/src/Select.ts | 7 +++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/main/cypress/specs/Select.cy.tsx b/packages/main/cypress/specs/Select.cy.tsx index 723a0fa91920..1408a3d23f5c 100644 --- a/packages/main/cypress/specs/Select.cy.tsx +++ b/packages/main/cypress/specs/Select.cy.tsx @@ -535,7 +535,7 @@ describe("Select - Accessibility", () => { {/* Select with readonly and required attributes */} - @@ -547,7 +547,7 @@ describe("Select - Accessibility", () => { const accessInfo = select.accessibilityInfo; expect(accessInfo.role).to.equal("combobox"); - expect(accessInfo.type).to.equal("listbox"); + expect(accessInfo.type).to.equal("Listbox"); expect(accessInfo.readonly).to.be.false; expect(accessInfo.required).to.be.false; expect(accessInfo.description).to.equal("Option 1"); // Just text since no aria-label @@ -576,6 +576,7 @@ describe("Select - Accessibility", () => { expect(accessInfo.readonly).to.be.true; expect(accessInfo.required).to.be.true; + expect(accessInfo.disabled).to.be.true; }); // Update the referenced label and check if the description updates diff --git a/packages/main/src/Select.ts b/packages/main/src/Select.ts index 6255c293f2f8..d3eec24a0514 100644 --- a/packages/main/src/Select.ts +++ b/packages/main/src/Select.ts @@ -1175,15 +1175,14 @@ class Select extends UI5Element implements IFormInputElement { } get accessibilityInfo() { - const description = this.ariaLabelText - ? `${this.ariaLabelText}${this.text ? ` ${this.text}` : ""}` - : this.text || ""; + const description = [this.ariaLabelText, this.text].filter(Boolean).join(" "); return { role: "combobox" as AriaRole, - type: "listbox", + type: this._ariaRoleDescription, readonly: this.readonly, required: this.required, + disabled: this.disabled, description, }; } From 35fcc670bd6293aae4ba07170e30d4510f7b37fc Mon Sep 17 00:00:00 2001 From: Iliana Bobeva Date: Mon, 1 Dec 2025 17:00:03 +0200 Subject: [PATCH 4/4] chore: remove aria label from description and return it as label property --- packages/main/cypress/specs/Select.cy.tsx | 14 +++++++++----- packages/main/src/Select.ts | 5 ++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/main/cypress/specs/Select.cy.tsx b/packages/main/cypress/specs/Select.cy.tsx index 1408a3d23f5c..76d26b7aed5c 100644 --- a/packages/main/cypress/specs/Select.cy.tsx +++ b/packages/main/cypress/specs/Select.cy.tsx @@ -550,7 +550,8 @@ describe("Select - Accessibility", () => { expect(accessInfo.type).to.equal("Listbox"); expect(accessInfo.readonly).to.be.false; expect(accessInfo.required).to.be.false; - expect(accessInfo.description).to.equal("Option 1"); // Just text since no aria-label + expect(accessInfo.description).to.equal("Option 1"); // Just text + expect(accessInfo.label).to.be.undefined; // No aria-label }); // Test select with accessibleName @@ -558,7 +559,8 @@ describe("Select - Accessibility", () => { const select = $select[0] as Select; const accessInfo = select.accessibilityInfo; - expect(accessInfo.description).to.equal("Select Name Option 1"); + expect(accessInfo.description).to.equal("Option 1"); // Just text + expect(accessInfo.label).to.equal("Select Name"); // Aria label }); // Test select with accessibleNameRef @@ -566,7 +568,8 @@ describe("Select - Accessibility", () => { const select = $select[0] as Select; const accessInfo = select.accessibilityInfo; - expect(accessInfo.description).to.equal("Reference Label Option 1"); + expect(accessInfo.description).to.equal("Option 1"); // Just text + expect(accessInfo.label).to.equal("Reference Label"); // Aria label from ref }); // Test select with readonly and required properties @@ -579,13 +582,14 @@ describe("Select - Accessibility", () => { expect(accessInfo.disabled).to.be.true; }); - // Update the referenced label and check if the description updates + // Update the referenced label and check if the label updates cy.get("#labelRef").invoke("text", "Updated Reference"); cy.get("#refSelect").then(($select) => { const select = $select[0] as Select; const accessInfo = select.accessibilityInfo; - expect(accessInfo.description).to.equal("Updated Reference Option 1"); + expect(accessInfo.description).to.equal("Option 1"); // Text remains the same + expect(accessInfo.label).to.equal("Updated Reference"); // Updated aria label from ref }); }); }); diff --git a/packages/main/src/Select.ts b/packages/main/src/Select.ts index d3eec24a0514..301a52b4254c 100644 --- a/packages/main/src/Select.ts +++ b/packages/main/src/Select.ts @@ -1175,15 +1175,14 @@ class Select extends UI5Element implements IFormInputElement { } get accessibilityInfo() { - const description = [this.ariaLabelText, this.text].filter(Boolean).join(" "); - return { role: "combobox" as AriaRole, type: this._ariaRoleDescription, + description: this.text, + label: this.ariaLabelText, readonly: this.readonly, required: this.required, disabled: this.disabled, - description, }; }