From ac1bcb85b1cc35e1bcbe9f6ff10886fdcf0f153b Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 16 Jul 2025 16:33:07 +0300 Subject: [PATCH 01/22] feat: improve AI button acc --- packages/ai/src/Button.ts | 30 ++++++++++++++++++- packages/ai/src/ButtonTemplate.tsx | 2 ++ packages/ai/src/i18n/messagebundle.properties | 6 +++- .../ai/src/i18n/messagebundle_en.properties | 2 ++ packages/base/src/types.ts | 3 +- packages/main/src/SplitButton.ts | 15 ++++++++++ packages/main/src/SplitButtonTemplate.tsx | 3 ++ 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index a9fa9a3cb6ab..8d94bdcc942b 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -9,12 +9,17 @@ import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import type SplitButton from "@ui5/webcomponents/dist/SplitButton.js"; import type ButtonDesign from "@ui5/webcomponents/dist/types/ButtonDesign.js"; import type ButtonState from "./ButtonState.js"; +import { BUTTON_TOOLTIP_TEXT } from "./generated/i18n/i18n-defaults.js"; import "./ButtonState.js"; - import ButtonTemplate from "./ButtonTemplate.js"; // Styles import ButtonCss from "./generated/themes/Button.css.js"; +import { i18n } from "@ui5/webcomponents-base/dist/decorators.js"; +import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import type { AccessibilityAttributes, AriaHasPopup } from "@ui5/webcomponents-base/dist/types.js"; + +type SplitButtonAccessibilityAttributes = Pick; /** * @class @@ -150,6 +155,9 @@ class Button extends UI5Element { @query(".ui5-ai-button-hidden[ui5-split-button]") _hiddenSplitButton?: SplitButton; + @i18n("@ui5/webcomponents") + static i18nBundle: I18nBundle; + get _hideArrowButton() { return !this._effectiveStateObject?.showArrowButton; } @@ -183,6 +191,10 @@ class Button extends UI5Element { return !!this._stateText; } + get _getButtonTooltipText() { + return this._hasText ? Button.i18nBundle.getText(BUTTON_TOOLTIP_TEXT, this._stateText as string) : undefined; + } + onBeforeRendering(): void { const splitButton = this._splitButton; @@ -305,6 +317,22 @@ class Button extends UI5Element { e.stopImmediatePropagation(); this.fireDecoratorEvent("arrow-button-click"); } + + get accessibilityAttributes(): SplitButtonAccessibilityAttributes { + let roleDescription; + if(this._hideArrowButton && !this._stateEndIcon) { + roleDescription = "Button"; + } else if (this._stateEndIcon) { + roleDescription = "Menu Button" + } else { + roleDescription = "Split Button" + } + + return { + hasPopup: !this._hideArrowButton || this._stateEndIcon ? "menu" : "false", + ariaRoleDescription: roleDescription + } + } } Button.define(); diff --git a/packages/ai/src/ButtonTemplate.tsx b/packages/ai/src/ButtonTemplate.tsx index a6cc1f794188..8e296b9e0a73 100644 --- a/packages/ai/src/ButtonTemplate.tsx +++ b/packages/ai/src/ButtonTemplate.tsx @@ -12,6 +12,8 @@ export default function ButtonTemplate(this: Button) { _hideArrowButton={this._hideArrowButton} onClick={this._onClick} onArrowClick={this._onArrowClick} + _leftButtonTooltipText={this._getButtonTooltipText} + accessibilityAttributes={this.accessibilityAttributes} > {this._hasText && (
{this._stateText}
diff --git a/packages/ai/src/i18n/messagebundle.properties b/packages/ai/src/i18n/messagebundle.properties index f350704b669e..5798eae6a052 100644 --- a/packages/ai/src/i18n/messagebundle.properties +++ b/packages/ai/src/i18n/messagebundle.properties @@ -5,4 +5,8 @@ PROMPT_INPUT_CHARACTERS_LEFT={0} characters remaining #XTXT: Text for characters over -PROMPT_INPUT_CHARACTERS_EXCEEDED={0} characters over limit \ No newline at end of file +PROMPT_INPUT_CHARACTERS_EXCEEDED={0} characters over limit + +#XTXT: Text for +BUTTON_TOOLTIP_TEXT={0} with AI + diff --git a/packages/ai/src/i18n/messagebundle_en.properties b/packages/ai/src/i18n/messagebundle_en.properties index 078ec94970bc..61bcca7e7f8e 100644 --- a/packages/ai/src/i18n/messagebundle_en.properties +++ b/packages/ai/src/i18n/messagebundle_en.properties @@ -2,3 +2,5 @@ PROMPT_INPUT_CHARACTERS_LEFT={0} characters remaining PROMPT_INPUT_CHARACTERS_EXCEEDED={0} characters over limit + +BUTTON_TOOLTIP_TEXT={0} with AI diff --git a/packages/base/src/types.ts b/packages/base/src/types.ts index 3f0c947a4d85..3ac11ae37b36 100644 --- a/packages/base/src/types.ts +++ b/packages/base/src/types.ts @@ -19,7 +19,7 @@ export type PassiveEventListenerObject = EventListenerObject & { passive: boolea // Accessibility export type AriaRole = JSX.AriaRole; -export type AriaHasPopup = "dialog" | "grid" | "listbox" | "menu" | "tree"; +export type AriaHasPopup = "dialog" | "grid" | "listbox" | "menu" | "tree" | "false"; export type AriaCurrent = "page" | "step" | "location" | "date" | "time" | "true" | "false" | boolean | undefined; export type AriaAutoComplete = "list" | "none" | "inline" | "both" | undefined; export type AriaLandmarkRole = "none" | "banner" | "main" | "region" | "navigation" | "search" | "complementary" | "form" | "contentinfo" @@ -61,4 +61,5 @@ export type AccessibilityAttributes = { ariaKeyShortcuts?: string, ariaCurrent?: AriaCurrent, current?: AriaCurrent, + ariaRoleDescription?: string } diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index 7b2e79469101..91b840d46d88 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -16,6 +16,7 @@ import { isTabNext, isTabPrevious, } from "@ui5/webcomponents-base/dist/Keys.js"; +import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js"; import type { AriaHasPopup, UI5CustomEvent } from "@ui5/webcomponents-base"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; @@ -35,6 +36,8 @@ import SplitButtonTemplate from "./SplitButtonTemplate.js"; // Styles import SplitButtonCss from "./generated/themes/SplitButton.css.js"; +type SplitButtonAccessibilityAttributes = Pick; + /** * @class * @@ -156,6 +159,14 @@ class SplitButton extends UI5Element { @property() accessibleName?: string; + /** + * Defines the tooltip text for the right button of the component. + * @default undefined + * @public + */ + @property() + _leftButtonTooltipText?: string; + /** * Defines the tabIndex of the component. * @default "0" @@ -210,6 +221,10 @@ class SplitButton extends UI5Element { @property({ type: Boolean }) _hideArrowButton = false; + + @property({ type: Object }) + accessibilityAttributes: SplitButtonAccessibilityAttributes = {}; + /** * Defines the text of the component. * diff --git a/packages/main/src/SplitButtonTemplate.tsx b/packages/main/src/SplitButtonTemplate.tsx index 9d07a1bcccf6..c5e1f5379627 100644 --- a/packages/main/src/SplitButtonTemplate.tsx +++ b/packages/main/src/SplitButtonTemplate.tsx @@ -9,6 +9,8 @@ export default function SplitButtonTemplate(this: SplitButton) { class="ui5-split-button-root" tabindex={this._tabIndex} aria-labelledby={`${this._id}-invisibleTextDefault ${this._id}-invisibleText`} + aria-haspopup={this.accessibilityAttributes.hasPopup} + aria-roledescription={this.accessibilityAttributes.ariaRoleDescription} onFocusOut={this._onFocusOut} onKeyDown={this._onKeyDown} onKeyUp={this._onKeyUp} @@ -28,6 +30,7 @@ export default function SplitButtonTemplate(this: SplitButton) { onMouseUp={this._textButtonRelease} onFocusIn={this._onInnerButtonFocusIn} onFocusOut={this._onFocusOut} + {...(this._leftButtonTooltipText ? { tooltip: this._leftButtonTooltipText } : {})} > {this.isTextButton && } From 21f464646b2464f58920e95b1a64bcd6f436a526 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Fri, 18 Jul 2025 16:00:08 +0300 Subject: [PATCH 02/22] feat: improve acc for ai button --- packages/ai/src/Button.ts | 39 +++++++++------ packages/ai/src/ButtonTemplate.tsx | 3 +- packages/ai/src/i18n/messagebundle.properties | 2 +- .../ai/src/i18n/messagebundle_en.properties | 2 +- packages/ai/test/pages/Button.html | 12 ++++- packages/main/src/SplitButton.ts | 17 +++---- packages/main/src/SplitButtonTemplate.tsx | 48 ++++++++++--------- 7 files changed, 70 insertions(+), 53 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index 8d94bdcc942b..37115ef761c7 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -12,14 +12,19 @@ import type ButtonState from "./ButtonState.js"; import { BUTTON_TOOLTIP_TEXT } from "./generated/i18n/i18n-defaults.js"; import "./ButtonState.js"; import ButtonTemplate from "./ButtonTemplate.js"; +import { + getEffectiveAriaLabelText, + getAssociatedLabelForTexts, + getAllAccessibleNameRefTexts, +} from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; // Styles import ButtonCss from "./generated/themes/Button.css.js"; import { i18n } from "@ui5/webcomponents-base/dist/decorators.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; -import type { AccessibilityAttributes, AriaHasPopup } from "@ui5/webcomponents-base/dist/types.js"; +import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js"; -type SplitButtonAccessibilityAttributes = Pick; +type AIButtonAccesibilityAttributes = Pick; /** * @class @@ -124,6 +129,15 @@ class Button extends UI5Element { @property({ type: Boolean, noAttribute: true }) arrowButtonPressed = false; + /** + * Defines the accesibility attributes of the component. + * + * @default {} + * @public + */ + @property({ type: Object }) + accessibilityAttributes: AIButtonAccesibilityAttributes = {}; + /** * Keeps the current state object of the component. * @private @@ -191,8 +205,8 @@ class Button extends UI5Element { return !!this._stateText; } - get _getButtonTooltipText() { - return this._hasText ? Button.i18nBundle.getText(BUTTON_TOOLTIP_TEXT, this._stateText as string) : undefined; + get _leftButtonTooltipText() { + return this._hasText ? Button.i18nBundle.getText(BUTTON_TOOLTIP_TEXT, this._stateText as string) : ""; } onBeforeRendering(): void { @@ -318,19 +332,14 @@ class Button extends UI5Element { this.fireDecoratorEvent("arrow-button-click"); } - get accessibilityAttributes(): SplitButtonAccessibilityAttributes { - let roleDescription; - if(this._hideArrowButton && !this._stateEndIcon) { - roleDescription = "Button"; - } else if (this._stateEndIcon) { - roleDescription = "Menu Button" - } else { - roleDescription = "Split Button" - } + get _computedAccessibilityAttributes(): AIButtonAccesibilityAttributes { + const labelRefTexts = getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; + const ariaLabel = this.accessibilityAttributes.ariaLabel?.concat(labelRefTexts) || ""; return { - hasPopup: !this._hideArrowButton || this._stateEndIcon ? "menu" : "false", - ariaRoleDescription: roleDescription + hasPopup: this.accessibilityAttributes.hasPopup ? this.accessibilityAttributes.hasPopup : (this._hideArrowButton ? "false" : "menu"), + ariaRoleDescription: this.accessibilityAttributes.ariaRoleDescription ? this.accessibilityAttributes.ariaRoleDescription : (this._hideArrowButton ? "Button" : "Split Button"), + ariaLabel: `${this._leftButtonTooltipText} ${ariaLabel}`.trim() } } } diff --git a/packages/ai/src/ButtonTemplate.tsx b/packages/ai/src/ButtonTemplate.tsx index 8e296b9e0a73..095f49965ad0 100644 --- a/packages/ai/src/ButtonTemplate.tsx +++ b/packages/ai/src/ButtonTemplate.tsx @@ -12,8 +12,7 @@ export default function ButtonTemplate(this: Button) { _hideArrowButton={this._hideArrowButton} onClick={this._onClick} onArrowClick={this._onArrowClick} - _leftButtonTooltipText={this._getButtonTooltipText} - accessibilityAttributes={this.accessibilityAttributes} + accessibilityAttributes={this._computedAccessibilityAttributes} > {this._hasText && (
{this._stateText}
diff --git a/packages/ai/src/i18n/messagebundle.properties b/packages/ai/src/i18n/messagebundle.properties index 5798eae6a052..38cf9268d21f 100644 --- a/packages/ai/src/i18n/messagebundle.properties +++ b/packages/ai/src/i18n/messagebundle.properties @@ -8,5 +8,5 @@ PROMPT_INPUT_CHARACTERS_LEFT={0} characters remaining PROMPT_INPUT_CHARACTERS_EXCEEDED={0} characters over limit #XTXT: Text for -BUTTON_TOOLTIP_TEXT={0} with AI +BUTTON_TOOLTIP_TEXT={0} with Artificial Intelligence diff --git a/packages/ai/src/i18n/messagebundle_en.properties b/packages/ai/src/i18n/messagebundle_en.properties index 61bcca7e7f8e..05a4e8173dda 100644 --- a/packages/ai/src/i18n/messagebundle_en.properties +++ b/packages/ai/src/i18n/messagebundle_en.properties @@ -3,4 +3,4 @@ PROMPT_INPUT_CHARACTERS_LEFT={0} characters remaining PROMPT_INPUT_CHARACTERS_EXCEEDED={0} characters over limit -BUTTON_TOOLTIP_TEXT={0} with AI +BUTTON_TOOLTIP_TEXT={0} with Artificial Intelligence diff --git a/packages/ai/test/pages/Button.html b/packages/ai/test/pages/Button.html index 37237010b85c..d14317d41bbd 100644 --- a/packages/ai/test/pages/Button.html +++ b/packages/ai/test/pages/Button.html @@ -20,7 +20,11 @@
- + @@ -235,7 +239,11 @@ button.arrowButtonPressed = false; }); - + myAiButton.accessibilityAttributes = { + "hasPopup": "Menu Button", + "ariaRoleDescription": "Custom Role Description", + "ariaLabel": "Custom Aria Label" + }; myAiButton.addEventListener("click", aiButtonClickHandler); myAiButtonSplit.addEventListener("click", aiButtonSplitClickHandler); myAiButtonSplit.addEventListener("arrow-button-click", aiButtonSplitArrowClickHandler); diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index 91b840d46d88..74e4137cb05a 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -36,7 +36,7 @@ import SplitButtonTemplate from "./SplitButtonTemplate.js"; // Styles import SplitButtonCss from "./generated/themes/SplitButton.css.js"; -type SplitButtonAccessibilityAttributes = Pick; +type SplitButtonAccessibilityAttributes = Pick; /** * @class @@ -159,14 +159,6 @@ class SplitButton extends UI5Element { @property() accessibleName?: string; - /** - * Defines the tooltip text for the right button of the component. - * @default undefined - * @public - */ - @property() - _leftButtonTooltipText?: string; - /** * Defines the tabIndex of the component. * @default "0" @@ -221,7 +213,12 @@ class SplitButton extends UI5Element { @property({ type: Boolean }) _hideArrowButton = false; - + /** + * Defines the accesibility attributes of the component. + * + * @default false + * @private + */ @property({ type: Object }) accessibilityAttributes: SplitButtonAccessibilityAttributes = {}; diff --git a/packages/main/src/SplitButtonTemplate.tsx b/packages/main/src/SplitButtonTemplate.tsx index c5e1f5379627..0b2d3e7a7a3c 100644 --- a/packages/main/src/SplitButtonTemplate.tsx +++ b/packages/main/src/SplitButtonTemplate.tsx @@ -10,6 +10,7 @@ export default function SplitButtonTemplate(this: SplitButton) { tabindex={this._tabIndex} aria-labelledby={`${this._id}-invisibleTextDefault ${this._id}-invisibleText`} aria-haspopup={this.accessibilityAttributes.hasPopup} + aria-label={this.accessibilityAttributes.ariaLabel} aria-roledescription={this.accessibilityAttributes.ariaRoleDescription} onFocusOut={this._onFocusOut} onKeyDown={this._onKeyDown} @@ -30,32 +31,35 @@ export default function SplitButtonTemplate(this: SplitButton) { onMouseUp={this._textButtonRelease} onFocusIn={this._onInnerButtonFocusIn} onFocusOut={this._onFocusOut} - {...(this._leftButtonTooltipText ? { tooltip: this._leftButtonTooltipText } : {})} + title={this.accessibilityAttributes.ariaLabel} + tooltip={this.accessibilityAttributes.ariaLabel} > {this.isTextButton && } - {!this._hideArrowButton && - - } - {this.accInfo.root.description} {this.accInfo.root.keyboardHint} {this.accessibleName} - {this.textButtonAccText} + {!this._hideArrowButton && ( + <> + + {this.accInfo.root.description} {this.accInfo.root.keyboardHint} {this.accessibleName} + {this.textButtonAccText} + + )} ); } From d80e887d7776859bef2f02f7ac974887b64e3d2c Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Fri, 18 Jul 2025 16:24:17 +0300 Subject: [PATCH 03/22] refactor: refactor getter --- packages/ai/src/Button.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index 37115ef761c7..c2349cfdaee4 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -333,14 +333,25 @@ class Button extends UI5Element { } get _computedAccessibilityAttributes(): AIButtonAccesibilityAttributes { - const labelRefTexts = getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; - const ariaLabel = this.accessibilityAttributes.ariaLabel?.concat(labelRefTexts) || ""; + const { + ariaLabel: attrLabel, + hasPopup, + ariaRoleDescription + } = this.accessibilityAttributes; + + const labelRefTexts = + getAllAccessibleNameRefTexts(this) || + getEffectiveAriaLabelText(this) || + getAssociatedLabelForTexts(this) || + ""; + + const ariaLabel = `${this._leftButtonTooltipText} ${(attrLabel?.concat(labelRefTexts) || "").trim()}`.trim(); return { - hasPopup: this.accessibilityAttributes.hasPopup ? this.accessibilityAttributes.hasPopup : (this._hideArrowButton ? "false" : "menu"), - ariaRoleDescription: this.accessibilityAttributes.ariaRoleDescription ? this.accessibilityAttributes.ariaRoleDescription : (this._hideArrowButton ? "Button" : "Split Button"), - ariaLabel: `${this._leftButtonTooltipText} ${ariaLabel}`.trim() - } + hasPopup: hasPopup ?? (this._hideArrowButton ? "false" : "menu"), + ariaRoleDescription: ariaRoleDescription ?? (this._hideArrowButton ? "Button" : "Split Button"), + ariaLabel + }; } } From 0bc576f99bb5cb9674da44d8e8ddae3fdbf2cbe6 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Fri, 18 Jul 2025 16:25:24 +0300 Subject: [PATCH 04/22] refactor: remove redundant trim --- packages/ai/src/Button.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index c2349cfdaee4..aa6b69b97c18 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -345,7 +345,7 @@ class Button extends UI5Element { getAssociatedLabelForTexts(this) || ""; - const ariaLabel = `${this._leftButtonTooltipText} ${(attrLabel?.concat(labelRefTexts) || "").trim()}`.trim(); + const ariaLabel = `${this._leftButtonTooltipText} ${(attrLabel?.concat(labelRefTexts) || "")}`.trim(); return { hasPopup: hasPopup ?? (this._hideArrowButton ? "false" : "menu"), From ea193e5fada432313b11f5185ac7ecc427aca751 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Fri, 18 Jul 2025 16:27:07 +0300 Subject: [PATCH 05/22] refactor: remove redundant attribute --- packages/ai/test/pages/Button.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/ai/test/pages/Button.html b/packages/ai/test/pages/Button.html index d14317d41bbd..aa2c6c58a257 100644 --- a/packages/ai/test/pages/Button.html +++ b/packages/ai/test/pages/Button.html @@ -20,11 +20,7 @@
- + From 8bad9c9dbcdfddd37c1149ecfc4d2961dc8e9876 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 21 Jul 2025 11:45:42 +0300 Subject: [PATCH 06/22] fix: address review comments --- packages/ai/src/Button.ts | 34 +++++++++++------------ packages/ai/test/pages/Button.html | 8 ++++-- packages/base/src/types.ts | 3 +- packages/main/src/SplitButton.ts | 17 ++++++++---- packages/main/src/SplitButtonTemplate.tsx | 8 ++---- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index aa6b69b97c18..7b41a62b16be 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -24,7 +24,10 @@ import { i18n } from "@ui5/webcomponents-base/dist/decorators.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js"; -type AIButtonAccesibilityAttributes = Pick; +type AIButtonRootAccAttributes = Pick; +type AIButtonArrowButtonAccAtributes = Pick; +type AIButtonAccessibilityAttributes = { root?: AIButtonRootAccAttributes, arrowButton?: AIButtonArrowButtonAccAtributes} + /** * @class @@ -136,7 +139,7 @@ class Button extends UI5Element { * @public */ @property({ type: Object }) - accessibilityAttributes: AIButtonAccesibilityAttributes = {}; + accessibilityAttributes: AIButtonAccessibilityAttributes = {}; /** * Keeps the current state object of the component. @@ -205,10 +208,6 @@ class Button extends UI5Element { return !!this._stateText; } - get _leftButtonTooltipText() { - return this._hasText ? Button.i18nBundle.getText(BUTTON_TOOLTIP_TEXT, this._stateText as string) : ""; - } - onBeforeRendering(): void { const splitButton = this._splitButton; @@ -332,25 +331,26 @@ class Button extends UI5Element { this.fireDecoratorEvent("arrow-button-click"); } - get _computedAccessibilityAttributes(): AIButtonAccesibilityAttributes { - const { - ariaLabel: attrLabel, - hasPopup, - ariaRoleDescription - } = this.accessibilityAttributes; - + get _computedAccessibilityAttributes() { const labelRefTexts = getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; - const ariaLabel = `${this._leftButtonTooltipText} ${(attrLabel?.concat(labelRefTexts) || "")}`.trim(); + const mainTitle = this._hasText ? Button.i18nBundle.getText(BUTTON_TOOLTIP_TEXT, this._stateText as string) : ""; + const title = `${mainTitle} ${labelRefTexts}`.trim(); return { - hasPopup: hasPopup ?? (this._hideArrowButton ? "false" : "menu"), - ariaRoleDescription: ariaRoleDescription ?? (this._hideArrowButton ? "Button" : "Split Button"), - ariaLabel + root: { + hasPopup: this.accessibilityAttributes?.root?.hasPopup || "false", + ariaRoleDescription: this.accessibilityAttributes?.root?.ariaRoleDescription || (this._hideArrowButton ? "Button" : "Split Button"), + title + }, + arrowButton: { + hasPopup: this.accessibilityAttributes?.arrowButton?.hasPopup, + expanded: this.accessibilityAttributes?.arrowButton?.expanded + } }; } } diff --git a/packages/ai/test/pages/Button.html b/packages/ai/test/pages/Button.html index aa2c6c58a257..955b7118620d 100644 --- a/packages/ai/test/pages/Button.html +++ b/packages/ai/test/pages/Button.html @@ -236,9 +236,11 @@ button.arrowButtonPressed = false; }); myAiButton.accessibilityAttributes = { - "hasPopup": "Menu Button", - "ariaRoleDescription": "Custom Role Description", - "ariaLabel": "Custom Aria Label" + "root": { + "hasPopup": "Menu Button", + "ariaRoleDescription": "Custom Role Description" + } + }; myAiButton.addEventListener("click", aiButtonClickHandler); myAiButtonSplit.addEventListener("click", aiButtonSplitClickHandler); diff --git a/packages/base/src/types.ts b/packages/base/src/types.ts index 22d1f05fd7a0..34fddbdb2ca9 100644 --- a/packages/base/src/types.ts +++ b/packages/base/src/types.ts @@ -64,5 +64,6 @@ export type AccessibilityAttributes = { ariaKeyShortcuts?: string, ariaCurrent?: AriaCurrent, current?: AriaCurrent, - ariaRoleDescription?: string + ariaRoleDescription?: string, + title?:string, } diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index 74e4137cb05a..6bbf88218ca2 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -36,7 +36,9 @@ import SplitButtonTemplate from "./SplitButtonTemplate.js"; // Styles import SplitButtonCss from "./generated/themes/SplitButton.css.js"; -type SplitButtonAccessibilityAttributes = Pick; +type SplitButtonRootAccAttributes = Pick; +type SplitButtonArrowButtonAccAtributes = Pick; +type SplitButtonAccessibilityAttributes = {root?: SplitButtonRootAccAttributes, arrowButton?: SplitButtonArrowButtonAccAtributes} /** * @class @@ -216,8 +218,8 @@ class SplitButton extends UI5Element { /** * Defines the accesibility attributes of the component. * - * @default false - * @private + * @default {} + * @public */ @property({ type: Object }) accessibilityAttributes: SplitButtonAccessibilityAttributes = {}; @@ -446,12 +448,17 @@ class SplitButton extends UI5Element { root: { "description": SplitButton.i18nBundle.getText(SPLIT_BUTTON_DESCRIPTION), "keyboardHint": SplitButton.i18nBundle.getText(SPLIT_BUTTON_KEYBOARD_HINT), + "accessibilityAttributes": { + "hasPopup": this.accessibilityAttributes?.root?.hasPopup, + "ariaRoleDescription": this.accessibilityAttributes?.root?.ariaRoleDescription, + "title": this.accessibilityAttributes?.root?.title + } }, arrowButton: { "title": this.arrowButtonTooltip, "accessibilityAttributes": { - "hasPopup": "menu" as AriaHasPopup, - "expanded": this.effectiveActiveArrowButton, + "hasPopup": this.accessibilityAttributes?.arrowButton?.hasPopup || "menu" as AriaHasPopup, + "expanded": this.accessibilityAttributes?.arrowButton?.expanded || this.effectiveActiveArrowButton, }, }, }; diff --git a/packages/main/src/SplitButtonTemplate.tsx b/packages/main/src/SplitButtonTemplate.tsx index 0b2d3e7a7a3c..7fdda042b044 100644 --- a/packages/main/src/SplitButtonTemplate.tsx +++ b/packages/main/src/SplitButtonTemplate.tsx @@ -9,9 +9,8 @@ export default function SplitButtonTemplate(this: SplitButton) { class="ui5-split-button-root" tabindex={this._tabIndex} aria-labelledby={`${this._id}-invisibleTextDefault ${this._id}-invisibleText`} - aria-haspopup={this.accessibilityAttributes.hasPopup} - aria-label={this.accessibilityAttributes.ariaLabel} - aria-roledescription={this.accessibilityAttributes.ariaRoleDescription} + aria-haspopup={this.accInfo?.root?.accessibilityAttributes?.hasPopup} + aria-roledescription={this.accInfo?.root?.accessibilityAttributes?.ariaRoleDescription} onFocusOut={this._onFocusOut} onKeyDown={this._onKeyDown} onKeyUp={this._onKeyUp} @@ -31,8 +30,7 @@ export default function SplitButtonTemplate(this: SplitButton) { onMouseUp={this._textButtonRelease} onFocusIn={this._onInnerButtonFocusIn} onFocusOut={this._onFocusOut} - title={this.accessibilityAttributes.ariaLabel} - tooltip={this.accessibilityAttributes.ariaLabel} + tooltip={this.accInfo?.root?.accessibilityAttributes?.title} > {this.isTextButton && } From ee027a04bcc42867da144ca2aa4b6fc5f8b572b7 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 21 Jul 2025 14:48:11 +0300 Subject: [PATCH 07/22] test: add test suite --- packages/ai/cypress/specs/Button.cy.tsx | 70 +++++++++++++++++++ packages/ai/cypress/support/commands.ts | 13 +++- .../support/commands/Button.commands.ts | 36 ++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 packages/ai/cypress/support/commands/Button.commands.ts diff --git a/packages/ai/cypress/specs/Button.cy.tsx b/packages/ai/cypress/specs/Button.cy.tsx index b7106c704e2c..2dd9811bc04e 100644 --- a/packages/ai/cypress/specs/Button.cy.tsx +++ b/packages/ai/cypress/specs/Button.cy.tsx @@ -12,3 +12,73 @@ describe("Initial rendering", () => { ); }); }); + +describe("Accessibility", () => { + it("should set correct tooltip to right text button", () => { + cy.mount( + + ); + + cy.get("[ui5-ai-button]") + .ui5AIButtonCheckAttributeInTextButton("tooltip", "Generate with Artificial Intelligence"); + }); + + it("should set correct aria-haspopup to SplitButton root element", () => { + cy.mount( + + ); + + cy.get("[ui5-ai-button]") + .ui5AIButtonCheckAttributeSplitButtonRoot("aria-haspopup", "menu"); + }); + + it("should set correct aria-roledescription to SplitButton root element", () => { + cy.mount( + + ); + + cy.get("[ui5-ai-button]") + .ui5AIButtonCheckAttributeSplitButtonRoot("aria-roledescription", "Open Menu"); + }); + + it("should set correct aria-haspopup to arrow button if shown", () => { + cy.mount( + + ); + + cy.get("[ui5-ai-button]") + .ui5AIButtonCheckAttributeInArrowButton("aria-haspopup", "menu"); + }); + + it("should set correct aria attributes with default values when not provided", () => { + cy.mount( + + ); + + cy.get("[ui5-ai-button]") + .as("button"); + + cy.get("@button") + .ui5AIButtonCheckAttributeSplitButtonRoot("aria-haspopup", "false"); + + cy.get("@button") + .ui5AIButtonCheckAttributeSplitButtonRoot("aria-roledescription", "Split Button"); + + cy.get("@button") + .ui5AIButtonCheckAttributeInArrowButton("aria-haspopup", "menu"); + + cy.get("@button") + .ui5AIButtonCheckAttributeInArrowButton("aria-expanded", "false"); + }); +}); diff --git a/packages/ai/cypress/support/commands.ts b/packages/ai/cypress/support/commands.ts index 3d44a956b147..9570783f6a8d 100644 --- a/packages/ai/cypress/support/commands.ts +++ b/packages/ai/cypress/support/commands.ts @@ -37,4 +37,15 @@ // } import "@ui5/cypress-internal/commands.js"; -import "../../../main/cypress/support/commands.js"; \ No newline at end of file +import "../../../main/cypress/support/commands.js"; +import "./commands/Button.commands.js"; + +declare global { + namespace Cypress { + interface Chainable { + ui5AIButtonCheckAttributeInTextButton(attrName: string, attrValue: string): Chainable + ui5AIButtonCheckAttributeInArrowButton(attrName: string, attrValue: string): Chainable + ui5AIButtonCheckAttributeSplitButtonRoot(attrName: string, attrValue: string): Chainable + } + } +} \ No newline at end of file diff --git a/packages/ai/cypress/support/commands/Button.commands.ts b/packages/ai/cypress/support/commands/Button.commands.ts new file mode 100644 index 000000000000..4f63c98b0425 --- /dev/null +++ b/packages/ai/cypress/support/commands/Button.commands.ts @@ -0,0 +1,36 @@ +import Button from "../../../src/Button.js"; + +Cypress.Commands.add("ui5AIButtonCheckAttributeInTextButton", { prevSubject: true }, (subject: JQuery @@ -42,8 +43,8 @@ export default function SplitButtonTemplate(this: SplitButton) { design={this.design} icon={slimArrowDown} tabindex={-1} - tooltip={this.accInfo.arrowButton.title} - accessibilityAttributes={this.accInfo.arrowButton.accessibilityAttributes} + tooltip={this._computedAccessibilityAttributes?.arrowButton?.title} + accessibilityAttributes={{ hasPopup: this._computedAccessibilityAttributes?.arrowButton?.hasPopup, expanded: this._computedAccessibilityAttributes?.arrowButton?.expanded }} disabled={this.disabled} active={this.effectiveActiveArrowButton} part="arrowButton" @@ -54,8 +55,8 @@ export default function SplitButtonTemplate(this: SplitButton) { onActiveStateChange={this._onArrowButtonActiveStateChange} > - {this.accInfo.root.description} {this.accInfo.root.keyboardHint} {this.accessibleName} - {this.textButtonAccText} + {this.accInfo.keyboardHint} {this.accessibleName} + {this._computedAccessibilityAttributes?.root?.title || this.textButtonAccText} )} diff --git a/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js b/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js index edc251818f8c..c5f39106ac34 100644 --- a/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js +++ b/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js @@ -8,15 +8,15 @@ var generationId; function startGeneration(button) { console.warn("startGeneration"); - generationId = setTimeout(function() { + generationId = setTimeout(function () { console.warn("Generation completed"); button.state = "revise"; button.accessibilityAttributes = { - root: { - hasPopup: "menu", - ariaRoleDescription: "Menu Button" - } + root: { + hasPopup: "menu", + ariaRoleDescription: "Menu Button" } + }; }, 3000); } @@ -24,16 +24,15 @@ function stopGeneration(button) { console.warn("stopGeneration"); clearTimeout(generationId); button.accessibilityAttributes = { - root: { - hasPopup: "false", - ariaRoleDescription: "Button" - } - }; + root: { + hasPopup: "false" + } + }; } function aiButtonClickHandler(evt) { var button = evt.target; - switch(button.state) { + switch (button.state) { case "generate": button.state = "generating"; startGeneration(button); @@ -51,7 +50,7 @@ function aiButtonClickHandler(evt) { myAiButton.addEventListener("click", aiButtonClickHandler); -menu.addEventListener("item-click", function(evt) { +menu.addEventListener("item-click", function (evt) { var button = menu.opener; if (evt.detail.text === "Regenerate") { button.state = "generating"; diff --git a/packages/website/docs/_samples/ai/Button/ButtonSplitMenu/main.js b/packages/website/docs/_samples/ai/Button/ButtonSplitMenu/main.js index 45033b36faf7..987bf497fc78 100644 --- a/packages/website/docs/_samples/ai/Button/ButtonSplitMenu/main.js +++ b/packages/website/docs/_samples/ai/Button/ButtonSplitMenu/main.js @@ -9,21 +9,31 @@ var prevTriggerState = "generate"; function startGeneration(button) { console.warn("startGeneration"); - generationId = setTimeout(function() { + generationId = setTimeout(function () { console.warn("Generation completed"); button.state = "regenerate"; + button.accessibilityAttributes = { + root: { + hasPopup: "menu" + } + }; }, 3000); } -function stopGeneration() { +function stopGeneration(button) { console.warn("stopGeneration"); clearTimeout(generationId); + button.accessibilityAttributes = { + root: { + hasPopup: "false" + } + }; } function aiButtonClickHandler(evt) { var button = evt.target; - switch(button.state) { + switch (button.state) { case "": case "generate": prevTriggerState = "generate"; @@ -32,7 +42,7 @@ function aiButtonClickHandler(evt) { break; case "generating": button.state = prevTriggerState; - stopGeneration(); + stopGeneration(button); break; case "regenerate": menu.open = false; diff --git a/packages/website/docs/_samples/patterns/AIRegenerate/Basic/main.js b/packages/website/docs/_samples/patterns/AIRegenerate/Basic/main.js index 7bbde73d3e5a..b14d4ccd4c12 100644 --- a/packages/website/docs/_samples/patterns/AIRegenerate/Basic/main.js +++ b/packages/website/docs/_samples/patterns/AIRegenerate/Basic/main.js @@ -29,6 +29,11 @@ const toggleDialog = (dialog, isOpen) => { }; dialogCloser.addEventListener("click", () => toggleDialog(dialog, false)); +myAiButton.accessibilityAttributes = { + root: { + hasPopup: "dialog" + } +}; myAiButton.addEventListener("click", () => { if (myAiButton.state === "generating") { @@ -88,6 +93,11 @@ const setBusyIndicator = (isActive) => { const resetAfterGeneration = (button) => { setBusyIndicator(false); button.state = "regenerate"; + button.accessibilityAttributes = { + root: { + hasPopup: "false" + } + }; }; const stopTextGeneration = () => { From a9f3630290d463c40404f5358a87eea30cd8390c Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 01:22:00 +0300 Subject: [PATCH 15/22] fix: rename proeprty name --- packages/ai/src/Button.ts | 4 ++-- packages/base/src/types.ts | 2 +- packages/main/src/SplitButtonTemplate.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index 4ee3e326cab9..db6a36f85453 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -24,7 +24,7 @@ import { i18n } from "@ui5/webcomponents-base/dist/decorators.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js"; -type AIButtonRootAccessibilityAttributes = Pick; +type AIButtonRootAccessibilityAttributes = Pick; type AIButtonArrowButtonAccessibilityAttributes = Pick; type AIButtonAccessibilityAttributes = { root?: AIButtonRootAccessibilityAttributes, arrowButton?: AIButtonArrowButtonAccessibilityAttributes} @@ -355,7 +355,7 @@ class Button extends UI5Element { return { root: { hasPopup: this.accessibilityAttributes?.root?.hasPopup || "false", - ariaRoleDescription: this.accessibilityAttributes?.root?.ariaRoleDescription, + roleDescription: this.accessibilityAttributes?.root?.roleDescription, title: this.accessibilityAttributes?.root?.title || title, }, arrowButton: { diff --git a/packages/base/src/types.ts b/packages/base/src/types.ts index 306e979f22d0..ad2d7bd4f377 100644 --- a/packages/base/src/types.ts +++ b/packages/base/src/types.ts @@ -64,6 +64,6 @@ export type AccessibilityAttributes = { ariaKeyShortcuts?: string, ariaCurrent?: AriaCurrent, current?: AriaCurrent, - ariaRoleDescription?: string, + roleDescription?: string, title?: string, } diff --git a/packages/main/src/SplitButtonTemplate.tsx b/packages/main/src/SplitButtonTemplate.tsx index c44c302b1d49..c15946cf2a3a 100644 --- a/packages/main/src/SplitButtonTemplate.tsx +++ b/packages/main/src/SplitButtonTemplate.tsx @@ -10,7 +10,7 @@ export default function SplitButtonTemplate(this: SplitButton) { tabindex={this._tabIndex} aria-labelledby={this._hideArrowButton ? undefined : `${this._id}-invisibleTextDefault ${this._id}-invisibleText`} aria-haspopup={this._computedAccessibilityAttributes?.root?.hasPopup} - aria-roledescription={this._computedAccessibilityAttributes?.root?.ariaRoleDescription} + aria-roledescription={this._computedAccessibilityAttributes?.root?.roleDescription} aria-label={this._hideArrowButton ? this._computedAccessibilityAttributes?.root?.title : undefined} onFocusOut={this._onFocusOut} onKeyDown={this._onKeyDown} From e7db9ae8786c8c8a49db98ee12dca2d873f0473f Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 01:26:20 +0300 Subject: [PATCH 16/22] fix: lint error --- packages/ai/src/Button.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index db6a36f85453..9bda35bc2033 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -361,7 +361,7 @@ class Button extends UI5Element { arrowButton: { hasPopup: this.accessibilityAttributes?.arrowButton?.hasPopup, expanded: this.accessibilityAttributes?.arrowButton?.expanded, - title: this.accessibilityAttributes?.arrowButton?.title + title: this.accessibilityAttributes?.arrowButton?.title, }, }; } From 2273e593382a11f52e9f2ee639138e8f992eed11 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 09:47:22 +0300 Subject: [PATCH 17/22] fix: rename property --- packages/main/src/SplitButton.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index 98cffc9afa15..3eadca8a44a0 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -36,7 +36,7 @@ import SplitButtonTemplate from "./SplitButtonTemplate.js"; // Styles import SplitButtonCss from "./generated/themes/SplitButton.css.js"; -type SplitButtonRootAccAttributes = Pick; +type SplitButtonRootAccAttributes = Pick; type SplitButtonArrowButtonAccAtributes = Pick; type SplitButtonAccessibilityAttributes = {root?: SplitButtonRootAccAttributes, arrowButton?: SplitButtonArrowButtonAccAtributes} @@ -463,7 +463,7 @@ class SplitButton extends UI5Element { return { root: { hasPopup: this.accessibilityAttributes?.root?.hasPopup, - ariaRoleDescription: this.accessibilityAttributes?.root?.ariaRoleDescription || (this._hideArrowButton ? undefined : SplitButton.i18nBundle.getText(SPLIT_BUTTON_DESCRIPTION)), + roleDescription: this.accessibilityAttributes?.root?.roleDescription || (this._hideArrowButton ? undefined : SplitButton.i18nBundle.getText(SPLIT_BUTTON_DESCRIPTION)), title: this.accessibilityAttributes?.root?.title, }, arrowButton: { From bb8f4f89799572641552a9aa1f5721297367301e Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 09:51:24 +0300 Subject: [PATCH 18/22] fix: update property in tests and samples --- packages/ai/cypress/specs/Button.cy.tsx | 2 +- packages/website/docs/_samples/ai/Button/ButtonMenu/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ai/cypress/specs/Button.cy.tsx b/packages/ai/cypress/specs/Button.cy.tsx index 2dd9811bc04e..4c35e774fa66 100644 --- a/packages/ai/cypress/specs/Button.cy.tsx +++ b/packages/ai/cypress/specs/Button.cy.tsx @@ -39,7 +39,7 @@ describe("Accessibility", () => { it("should set correct aria-roledescription to SplitButton root element", () => { cy.mount( - ); diff --git a/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js b/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js index c5f39106ac34..5517380b1143 100644 --- a/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js +++ b/packages/website/docs/_samples/ai/Button/ButtonMenu/main.js @@ -14,7 +14,7 @@ function startGeneration(button) { button.accessibilityAttributes = { root: { hasPopup: "menu", - ariaRoleDescription: "Menu Button" + roleDescription: "Menu Button" } }; }, 3000); From bb853fce95b4fa0e084fb449536dfe5883612da8 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 09:59:05 +0300 Subject: [PATCH 19/22] fix: update jsdocs versions --- packages/ai/src/Button.ts | 2 +- packages/main/src/SplitButton.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index 9bda35bc2033..f1a53b522380 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -126,7 +126,7 @@ class Button extends UI5Element { * is opened by the arrow button. Set back to false when the menu is closed. * @default false * @public - * @since 2.6.0 + * @since 2.13.0 */ @property({ type: Boolean, noAttribute: true }) arrowButtonPressed = false; diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index 3eadca8a44a0..e15fcb6557d3 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -235,7 +235,7 @@ class SplitButton extends UI5Element { * * @default {} * @public - * @since 2.6.0 + * @since 2.13.0 */ @property({ type: Object }) accessibilityAttributes: SplitButtonAccessibilityAttributes = {}; From 19c2039e4771ab6845db2b4398c6116699b426ca Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 10:02:09 +0300 Subject: [PATCH 20/22] fix: update jdsocs --- packages/ai/src/Button.ts | 2 +- packages/main/src/SplitButton.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index f1a53b522380..8f9f6a59c9da 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -140,7 +140,7 @@ class Button extends UI5Element { * - **root**: Accessibility attributes that will be applied to the root element. * - **hasPopup**: Indicates the availability and type of interactive popup element (such as a menu or dialog). * Accepts string values: `"dialog"`, `"grid"`, `"listbox"`, `"menu"`, or `"tree"`. - * - **ariaRoleDescription**: Defines a human-readable description for the button's role. + * - **roleDescription**: Defines a human-readable description for the button's role. * Accepts any string value. * * - **arrowButton**: Accessibility attributes that will be applied to the arrow (split) button element. diff --git a/packages/main/src/SplitButton.ts b/packages/main/src/SplitButton.ts index e15fcb6557d3..b1254099519f 100644 --- a/packages/main/src/SplitButton.ts +++ b/packages/main/src/SplitButton.ts @@ -222,7 +222,7 @@ class SplitButton extends UI5Element { * - **root**: Attributes that will be applied to the main (text) button. * - **hasPopup**: Indicates the presence and type of popup triggered by the button. * Accepts string values: `"dialog"`, `"grid"`, `"listbox"`, `"menu"`, or `"tree"`. - * - **ariaRoleDescription**: Provides a human-readable description for the role of the button. + * - **roleDescription**: Provides a human-readable description for the role of the button. * Accepts any string value. * - **title**: Specifies a tooltip or description for screen readers. * Accepts any string value. From ee396b2c5f2e0f8e15500bea0ad16f6181ac5e76 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Wed, 23 Jul 2025 10:07:37 +0300 Subject: [PATCH 21/22] fix: update property --- packages/ai/src/Button.ts | 2 +- packages/ai/test/pages/Button.html | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ai/src/Button.ts b/packages/ai/src/Button.ts index 8f9f6a59c9da..b317042dd246 100644 --- a/packages/ai/src/Button.ts +++ b/packages/ai/src/Button.ts @@ -126,7 +126,7 @@ class Button extends UI5Element { * is opened by the arrow button. Set back to false when the menu is closed. * @default false * @public - * @since 2.13.0 + * @since 2.6.0 */ @property({ type: Boolean, noAttribute: true }) arrowButtonPressed = false; diff --git a/packages/ai/test/pages/Button.html b/packages/ai/test/pages/Button.html index 795d4ac4690d..f26dcf26b517 100644 --- a/packages/ai/test/pages/Button.html +++ b/packages/ai/test/pages/Button.html @@ -153,7 +153,7 @@ button.accessibilityAttributes = { root: { hasPopup: "menu", - ariaRoleDescription: isSplitButton ? undefined : "Menu Button" + roleDescription: isSplitButton ? undefined : "Menu Button" } }; }, 3000); @@ -289,7 +289,7 @@ button.accessibilityAttributes = { root: { hasPopup: "menu", - ariaRoleDescription: "Menu Button" + roleDescription: "Menu Button" } }; }, 2000); @@ -444,7 +444,7 @@ button.accessibilityAttributes = { root: { hasPopup: "menu", - ariaRoleDescription: "Menu Button" + roleDescription: "Menu Button" } }; From b1abf0405d173feba69716336595fe1028a7fa17 Mon Sep 17 00:00:00 2001 From: Georgi Damyanov Date: Mon, 28 Jul 2025 09:52:26 +0300 Subject: [PATCH 22/22] fix: address review comments --- packages/ai/cypress/support/commands/Button.commands.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/ai/cypress/support/commands/Button.commands.ts b/packages/ai/cypress/support/commands/Button.commands.ts index 4f63c98b0425..0ad6e783c346 100644 --- a/packages/ai/cypress/support/commands/Button.commands.ts +++ b/packages/ai/cypress/support/commands/Button.commands.ts @@ -7,8 +7,7 @@ Cypress.Commands.add("ui5AIButtonCheckAttributeInTextButton", { prevSubject: tru .shadow() .find(".ui5-split-text-button") .should("be.visible") - .invoke("attr", attrName) - .should("eq", attrValue); + .should("have.attr", attrName, attrValue); }); Cypress.Commands.add("ui5AIButtonCheckAttributeInArrowButton", { prevSubject: true }, (subject: JQuery