diff --git a/packages/fiori/cypress/specs/Wizard.cy.tsx b/packages/fiori/cypress/specs/Wizard.cy.tsx index d13ade802dfc..39678533dacc 100644 --- a/packages/fiori/cypress/specs/Wizard.cy.tsx +++ b/packages/fiori/cypress/specs/Wizard.cy.tsx @@ -105,6 +105,67 @@ describe("Wizard general interaction", () => { .should("have.attr", "role", "region"); }); + it("should use accessibleName property as aria-label", () => { + cy.mount( + + + + + ); + + cy.get("[ui5-wizard]") + .shadow() + .find(".ui5-wiz-root") + .should("have.attr", "aria-label", "Registration Process"); + }); + + it("should use accessibleNameRef to reference external element for aria-label", () => { + cy.mount( +
+

Order Completion Wizard

+ + + + +
+ ); + + cy.get("[ui5-wizard]") + .shadow() + .find(".ui5-wiz-root") + .should("have.attr", "aria-label", "Order Completion Wizard"); + }); + + it("should use accessibleNameRef over accessibleName when both are provided", () => { + cy.mount( +
+ External Wizard Label + + + + +
+ ); + + cy.get("[ui5-wizard]") + .shadow() + .find(".ui5-wiz-root") + .should("have.attr", "aria-label", "External Wizard Label"); + }); + + it("should fall back to default i18n label when no accessibleName or accessibleNameRef is provided", () => { + cy.mount( + + + + ); + + cy.get("[ui5-wizard]") + .shadow() + .find(".ui5-wiz-root") + .should("have.attr", "aria-label", "Wizard"); + }); + it("Disabled step should not be interactive", () => { cy.mount( diff --git a/packages/fiori/src/Wizard.ts b/packages/fiori/src/Wizard.ts index 79586d50b072..4e3fe25bdb42 100644 --- a/packages/fiori/src/Wizard.ts +++ b/packages/fiori/src/Wizard.ts @@ -15,6 +15,7 @@ import type { UI5CustomEvent } from "@ui5/webcomponents-base"; import type { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; import debounce from "@ui5/webcomponents-base/dist/util/debounce.js"; import { getFirstFocusableElement } from "@ui5/webcomponents-base/dist/util/FocusableElements.js"; +import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import type ResponsivePopover from "@ui5/webcomponents/dist/ResponsivePopover.js"; import type Button from "@ui5/webcomponents/dist/Button.js"; import type WizardContentLayout from "./types/WizardContentLayout.js"; @@ -210,6 +211,24 @@ class Wizard extends UI5Element { @property() contentLayout: `${WizardContentLayout}` = "MultipleSteps"; + /** + * Defines the accessible ARIA name of the component. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleName?: string; + + /** + * Receives id(or many ids) of the elements that label the component. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleNameRef?: string; + /** * Defines the width of the `ui5-wizard`. * @private @@ -811,7 +830,11 @@ class Wizard extends UI5Element { return Wizard.i18nBundle.getText(WIZARD_STEP_INACTIVE); } - get ariaLabelText() { + get ariaLabelText(): string { + if (this.accessibleName || this.accessibleNameRef) { + return getEffectiveAriaLabelText(this) || Wizard.i18nBundle.getText(WIZARD_NAV_ARIA_ROLE_DESCRIPTION); + } + return Wizard.i18nBundle.getText(WIZARD_NAV_ARIA_ROLE_DESCRIPTION); } diff --git a/packages/fiori/test/pages/WizardAccessibility.html b/packages/fiori/test/pages/WizardAccessibility.html new file mode 100644 index 000000000000..eadb21bba66a --- /dev/null +++ b/packages/fiori/test/pages/WizardAccessibility.html @@ -0,0 +1,289 @@ + + + + + + + Wizard Accessibility Test Page + + + + + + + + + +

Wizard Accessibility Test Page

+

Use this page to test the accessibleName and accessibleNameRef properties with screen readers (JAWS on Windows, VoiceOver on macOS).

+ + +
+

Test 1: Default Behavior (No accessibleName)

+

+ This wizard has no accessibleName set. It should announce the default i18n label: "Wizard" +

+
+ + +
+ Step 1: Personal Information +
+ Enter your personal details here. +

+ +

+ Continue to Step 2 +
+
+ +
+ Step 2: Contact Details +
+ Enter your contact information. +
+
+
+
+
+ + +
+

Test 2: Using accessibleName Property

+

+ This wizard has accessibleName="Employee Registration Process" set. It should announce: "Employee Registration Process" +

+
+ + +
+ Step 1: Personal Details +
+ Complete your employee profile. +

+ +

+ Continue to Step 2 +
+
+ +
+ Step 2: Department Assignment +
+ Select your department. +
+
+
+
+
+ + +
+

Test 3: Using accessibleNameRef Property

+

+ This wizard has accessibleNameRef="order-wizard-label" referencing an external element. It should announce: "Order Completion Workflow" +

+

Order Completion Workflow

+
+ + +
+ Step 1: Review Your Cart +
+ Please review the items in your cart before proceeding. +

+ Continue to Payment +
+
+ +
+ Step 2: Payment Details +
+ Enter your payment information. +
+
+ +
+ Step 3: Order Confirmation +
+ Your order has been placed. +
+
+
+
+
+ + +
+

Test 4: accessibleNameRef Takes Precedence Over accessibleName

+

+ This wizard has both accessibleName="Internal Label" and accessibleNameRef="external-label". + The accessibleNameRef should take precedence. It should announce: "Expense Report Submission" +

+ Expense Report Submission +
+ + +
+ Step 1: Expense Details +
+ Enter your expense information. +

+ +

+ Continue to Receipts +
+
+ +
+ Step 2: Upload Receipts +
+ Upload your expense receipts. +
+
+
+
+
+ + +
+

Test 5: Multiple Wizards with Different Accessible Names

+

+ Two wizards on the same page with different accessible names. Screen readers should distinguish between them. +

+ +

Wizard A: Account Setup Wizard

+
+ + +
+ +
+
+ +
+ +
+
+
+
+ +

Wizard B: Profile Customization Wizard

+
+ + +
+ Choose your profile picture. +
+
+ +
+ Select your preferred theme. +
+
+
+
+
+ + + + +