From e97f30a8712ae052420efde959cb1050715588e0 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Wed, 2 Jul 2025 13:41:41 +0300 Subject: [PATCH 1/9] fix: adjust popover accessible name and label --- packages/main/src/DatePicker.ts | 14 +- .../main/src/DatePickerPopoverTemplate.tsx | 4 +- packages/main/test/pages/DatePicker.html | 142 ++++++++++-------- 3 files changed, 90 insertions(+), 70 deletions(-) diff --git a/packages/main/src/DatePicker.ts b/packages/main/src/DatePicker.ts index 006500e2ef8d..f6bc3e0fadc2 100644 --- a/packages/main/src/DatePicker.ts +++ b/packages/main/src/DatePicker.ts @@ -12,7 +12,7 @@ import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateB import getRoundedTimestamp from "@ui5/webcomponents-localization/dist/dates/getRoundedTimestamp.js"; import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; -import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; +import { getEffectiveAriaLabelText, getAssociatedLabelForTexts, getAllAccessibleNameRefTexts } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import { submitForm } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; import willShowContent from "@ui5/webcomponents-base/dist/util/willShowContent.js"; import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; @@ -663,7 +663,7 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get _headerTitleText() { - return DatePicker.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE); + return DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME); } get showHeader() { @@ -679,10 +679,14 @@ class DatePicker extends DateComponentBase implements IFormInputElement { "ariaRoledescription": this.dateAriaDescription, "ariaHasPopup": "grid", "ariaRequired": this.required, - "ariaLabel": getEffectiveAriaLabelText(this), + "ariaLabel": this._inputLabelTexts || undefined, }; } + get _inputLabelTexts() { + return getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; + } + get valueStateDefaultText(): string | undefined { if (this.valueState === ValueState.None) { return; @@ -725,7 +729,9 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get pickerAccessibleName() { - return DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME); + return isPhone() + ? `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim() + : DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME); } /** diff --git a/packages/main/src/DatePickerPopoverTemplate.tsx b/packages/main/src/DatePickerPopoverTemplate.tsx index 8158e9ef9624..c00aede866aa 100644 --- a/packages/main/src/DatePickerPopoverTemplate.tsx +++ b/packages/main/src/DatePickerPopoverTemplate.tsx @@ -52,13 +52,13 @@ function defaultHeader(this: DatePicker) {
{this._headerTitleText} - + */}
); diff --git a/packages/main/test/pages/DatePicker.html b/packages/main/test/pages/DatePicker.html index 66ad50023d99..e0d20a8b316b 100644 --- a/packages/main/test/pages/DatePicker.html +++ b/packages/main/test/pages/DatePicker.html @@ -30,10 +30,24 @@
-

DatePicker with value-state-change event prevented

- - -
+ + Application context announcement + + + Application context announcement + +
+ Application context ONE announcement +
+ Application context TWO announcement +
+ +
+ Application context announcement +
+ + +
From a12d4d9943f0f9b0eb1f029a5e069ea7822fd5d0 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Wed, 2 Jul 2025 13:48:22 +0300 Subject: [PATCH 2/9] fix: adjust popover title text on mobile --- packages/main/src/DatePicker.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/main/src/DatePicker.ts b/packages/main/src/DatePicker.ts index f6bc3e0fadc2..613ec14ef191 100644 --- a/packages/main/src/DatePicker.ts +++ b/packages/main/src/DatePicker.ts @@ -663,7 +663,7 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get _headerTitleText() { - return DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME); + return this._inputLabelTexts || DatePicker.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE); } get showHeader() { @@ -729,9 +729,7 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get pickerAccessibleName() { - return isPhone() - ? `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim() - : DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME); + return `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim(); } /** From ea81019b24ad2d4eb10bff1c46fe127424a5dc75 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Wed, 2 Jul 2025 16:41:53 +0300 Subject: [PATCH 3/9] fix: remove redundant announcements --- packages/main/src/DatePicker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/main/src/DatePicker.ts b/packages/main/src/DatePicker.ts index 613ec14ef191..de86336072d6 100644 --- a/packages/main/src/DatePicker.ts +++ b/packages/main/src/DatePicker.ts @@ -729,7 +729,9 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get pickerAccessibleName() { - return `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim(); + return isPhone() + ? DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME) + : `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim(); } /** From 792e0b30e831a964b1ab22e734dc382c65ab36d7 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Wed, 2 Jul 2025 16:44:24 +0300 Subject: [PATCH 4/9] fix: retrieve the clear button in the dialog header --- packages/main/src/DatePickerPopoverTemplate.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/DatePickerPopoverTemplate.tsx b/packages/main/src/DatePickerPopoverTemplate.tsx index c00aede866aa..d926c472a928 100644 --- a/packages/main/src/DatePickerPopoverTemplate.tsx +++ b/packages/main/src/DatePickerPopoverTemplate.tsx @@ -52,13 +52,13 @@ function defaultHeader(this: DatePicker) {
{this._headerTitleText} - {/* */} + }
); From 9386ba81711b34ba8d22c4d6115f25b2f91e7820 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Wed, 2 Jul 2025 16:46:16 +0300 Subject: [PATCH 5/9] fix: remove redundant braces from the template --- packages/main/src/DatePickerPopoverTemplate.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/DatePickerPopoverTemplate.tsx b/packages/main/src/DatePickerPopoverTemplate.tsx index d926c472a928..8158e9ef9624 100644 --- a/packages/main/src/DatePickerPopoverTemplate.tsx +++ b/packages/main/src/DatePickerPopoverTemplate.tsx @@ -52,13 +52,13 @@ function defaultHeader(this: DatePicker) {
{this._headerTitleText} - { } +
); From 31396b5dbb7d0d2272bc476f76ee74c79a296863 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Thu, 14 Aug 2025 10:25:37 +0300 Subject: [PATCH 6/9] fix: add description APIs --- docs/2-advanced/09-accessibility.md | 12 ++++++ packages/main/src/DatePicker.ts | 39 ++++++++++++++---- packages/main/src/DateRangePicker.ts | 4 +- packages/main/src/DateTimePicker.ts | 4 +- packages/main/src/FileUploader.ts | 21 ++++++++++ packages/main/src/FileUploaderTemplate.tsx | 1 + packages/main/src/TimePicker.ts | 41 ++++++++++++++++--- .../main/src/i18n/messagebundle.properties | 6 +-- packages/main/test/pages/DatePicker.html | 20 ++++++++- 9 files changed, 127 insertions(+), 21 deletions(-) diff --git a/docs/2-advanced/09-accessibility.md b/docs/2-advanced/09-accessibility.md index f0b00cffd51d..4e5860a94e7f 100644 --- a/docs/2-advanced/09-accessibility.md +++ b/docs/2-advanced/09-accessibility.md @@ -213,6 +213,11 @@ The `accessibleDescription` property is currently supported in: * [Popover](https://sap.github.io/ui5-webcomponents/nightly/components/Popover/) * [ResponsivePopover](https://sap.github.io/ui5-webcomponents/nightly/components/ResponsivePopover/) * [Dialog](https://sap.github.io/ui5-webcomponents/nightly/components/Dialog/) +* [DatePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DatePicker/) +* [DateRangePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DateRangePicker/) +* [DateTimePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DateTimePicker/) +* [TimePicker](https://sap.github.io/ui5-webcomponents/nightly/components/TimePicker/) +* [FileUploader](https://sap.github.io/ui5-webcomponents/nightly/components/FileUploader/) --- @@ -241,6 +246,11 @@ The `accessibleDescriptionRef` property is currently supported in: * [Popover](https://sap.github.io/ui5-webcomponents/nightly/components/Popover/) * [ResponsivePopover](https://sap.github.io/ui5-webcomponents/nightly/components/ResponsivePopover/) * [Dialog](https://sap.github.io/ui5-webcomponents/nightly/components/Dialog/) +* [DatePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DatePicker/) +* [DateRangePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DateRangePicker/) +* [DateTimePicker](https://sap.github.io/ui5-webcomponents/nightly/components/DateTimePicker/) +* [TimePicker](https://sap.github.io/ui5-webcomponents/nightly/components/TimePicker/) +* [FileUploader](https://sap.github.io/ui5-webcomponents/nightly/components/FileUploader/) --- @@ -302,6 +312,7 @@ The `accessibilityAttributes` property is currently supported in: * [Avatar](https://sap.github.io/ui5-webcomponents/nightly/components/Avatar/) * [AvatarGroup](https://sap.github.io/ui5-webcomponents/nightly/components/AvatarGroup/) * [Button](https://sap.github.io/ui5-webcomponents/nightly/components/Button/) +* [Button](https://sap.github.io/ui5-webcomponents/nightly/components/ai/Button/) * [Link](https://sap.github.io/ui5-webcomponents/nightly/components/Link/) * [ToggleButton](https://sap.github.io/ui5-webcomponents/nightly/components/ToggleButton/) * [Link](https://sap.github.io/ui5-webcomponents/nightly/components/Link/) @@ -311,6 +322,7 @@ The `accessibilityAttributes` property is currently supported in: * [FlexibleColumnLayout](https://sap.github.io/ui5-webcomponents/nightly/components/fiori/FlexibleColumnLayout/) * [ShellBar](https://sap.github.io/ui5-webcomponents/nightly/components/fiori/ShellBar/) * [ShellBarItem](https://sap.github.io/ui5-webcomponents/nightly/components/fiori/ShellBarItem/) +* [SplitButton](https://sap.github.io/ui5-webcomponents/nightly/components/SplitButton/) * [MenuItem](https://sap.github.io/ui5-webcomponents/nightly/components/MenuItem/) * [List](https://sap.github.io/ui5-webcomponents/nightly/components/List/) diff --git a/packages/main/src/DatePicker.ts b/packages/main/src/DatePicker.ts index 614d7f228fc6..07e6a7fcb8e2 100644 --- a/packages/main/src/DatePicker.ts +++ b/packages/main/src/DatePicker.ts @@ -13,7 +13,13 @@ import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateB import getRoundedTimestamp from "@ui5/webcomponents-localization/dist/dates/getRoundedTimestamp.js"; import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; -import { getEffectiveAriaLabelText, getAssociatedLabelForTexts, getAllAccessibleNameRefTexts } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; +import { + getEffectiveAriaLabelText, + getAssociatedLabelForTexts, + getAllAccessibleNameRefTexts, + getEffectiveAriaDescriptionText, + getAllAccessibleDescriptionRefTexts, +} from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import { submitForm } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; import willShowContent from "@ui5/webcomponents-base/dist/util/willShowContent.js"; import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; @@ -337,6 +343,24 @@ class DatePicker extends DateComponentBase implements IFormInputElement { @property() accessibleNameRef?: string; + /** + * Defines the accessible description of the component. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescription?: string; + + /** + * Receives id(or many ids) of the elements that describe the input. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescriptionRef?: string; + @property({ type: Object }) _respPopoverConfig?: object; @@ -768,7 +792,7 @@ class DatePicker extends DateComponentBase implements IFormInputElement { } get _headerTitleText() { - return this._inputLabelTexts || DatePicker.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE); + return this.ariaLabelText || DatePicker.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE); } get showHeader() { @@ -793,14 +817,15 @@ class DatePicker extends DateComponentBase implements IFormInputElement { get accInfo(): InputAccInfo { return { - "ariaRoledescription": this.dateAriaDescription, + "ariaRoledescription": this.roleDescription, "ariaHasPopup": "grid", "ariaRequired": this.required, - "ariaLabel": this._inputLabelTexts || undefined, + "ariaLabel": this.ariaLabelText || undefined, + "ariaDescription": getAllAccessibleDescriptionRefTexts(this) || getEffectiveAriaDescriptionText(this) || undefined, }; } - get _inputLabelTexts() { + get ariaLabelText() { return getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; } @@ -841,12 +866,12 @@ class DatePicker extends DateComponentBase implements IFormInputElement { return "appointment-2"; } - get dateAriaDescription() { + get roleDescription() { return DatePicker.i18nBundle.getText(DATEPICKER_DATE_DESCRIPTION); } get pickerAccessibleName() { - return `${this._inputLabelTexts} ${DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME)}`.trim(); + return DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME, this.ariaLabelText); } /** diff --git a/packages/main/src/DateRangePicker.ts b/packages/main/src/DateRangePicker.ts index bbb9357bb429..0a90fdfc41c5 100644 --- a/packages/main/src/DateRangePicker.ts +++ b/packages/main/src/DateRangePicker.ts @@ -212,7 +212,7 @@ class DateRangePicker extends DatePicker implements IFormInputElement { /** * @override */ - get dateAriaDescription() { + get roleDescription() { return DateRangePicker.i18nBundle.getText(DATERANGE_DESCRIPTION); } @@ -220,7 +220,7 @@ class DateRangePicker extends DatePicker implements IFormInputElement { * @override */ get pickerAccessibleName() { - return DateRangePicker.i18nBundle.getText(DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME); + return DateRangePicker.i18nBundle.getText(DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME, this.ariaLabelText); } /** diff --git a/packages/main/src/DateTimePicker.ts b/packages/main/src/DateTimePicker.ts index 9c0f7c5048a5..513abb1e0387 100644 --- a/packages/main/src/DateTimePicker.ts +++ b/packages/main/src/DateTimePicker.ts @@ -255,7 +255,7 @@ class DateTimePicker extends DatePicker implements IFormInputElement { /** * @override */ - get dateAriaDescription() { + get roleDescription() { return DateTimePicker.i18nBundle.getText(DATETIME_DESCRIPTION); } @@ -263,7 +263,7 @@ class DateTimePicker extends DatePicker implements IFormInputElement { * @override */ get pickerAccessibleName() { - return DateTimePicker.i18nBundle.getText(DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME); + return DateTimePicker.i18nBundle.getText(DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME, this.ariaLabelText); } /** diff --git a/packages/main/src/FileUploader.ts b/packages/main/src/FileUploader.ts index 4327be6034b7..2bc36b55b9e7 100644 --- a/packages/main/src/FileUploader.ts +++ b/packages/main/src/FileUploader.ts @@ -9,6 +9,8 @@ import { getEffectiveAriaLabelText, getAssociatedLabelForTexts, getAllAccessibleNameRefTexts, + getEffectiveAriaDescriptionText, + getAllAccessibleDescriptionRefTexts, } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js"; import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; @@ -234,6 +236,24 @@ class FileUploader extends UI5Element implements IFormInputElement { @property() accessibleNameRef?: string; + /** + * Defines the accessible description of the component. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescription?: string; + + /** + * Receives id(or many ids) of the elements that describe the input. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescriptionRef?: string; + /** * @private */ @@ -603,6 +623,7 @@ class FileUploader extends UI5Element implements IFormInputElement { "ariaInvalid": this.valueState === ValueState.Negative || undefined, "ariaHasPopup": "dialog", "ariaLabel": getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || undefined, + "ariaDescription": getAllAccessibleDescriptionRefTexts(this) || getEffectiveAriaDescriptionText(this) || undefined, }; } diff --git a/packages/main/src/FileUploaderTemplate.tsx b/packages/main/src/FileUploaderTemplate.tsx index 3458b150a707..1150d29f0395 100644 --- a/packages/main/src/FileUploaderTemplate.tsx +++ b/packages/main/src/FileUploaderTemplate.tsx @@ -32,6 +32,7 @@ export default function FileUploaderTemplate(this: FileUploader) { aria-roledescription={this.accInfo.ariaRoledescription} aria-haspopup={this.accInfo.ariaHasPopup} aria-label={this.accInfo.ariaLabel} + aria-description={this.accInfo.ariaDescription} aria-required={this.accInfo.ariaRequired} aria-invalid={this.accInfo.ariaInvalid} onClick={this._onNativeInputClick} diff --git a/packages/main/src/TimePicker.ts b/packages/main/src/TimePicker.ts index 40380511f505..6438f1a97ad4 100644 --- a/packages/main/src/TimePicker.ts +++ b/packages/main/src/TimePicker.ts @@ -13,7 +13,13 @@ import { submitForm } from "@ui5/webcomponents-base/dist/features/InputElementsF import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import getLocale from "@ui5/webcomponents-base/dist/locale/getLocale.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; -import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; +import { + getEffectiveAriaLabelText, + getAssociatedLabelForTexts, + getAllAccessibleNameRefTexts, + getEffectiveAriaDescriptionText, + getAllAccessibleDescriptionRefTexts, +} from "@ui5/webcomponents-base/dist/util/AccessibilityTextsHelper.js"; import "@ui5/webcomponents-localization/dist/features/calendar/Gregorian.js"; // default calendar for bundling import DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js"; import getCachedLocaleDataInstance from "@ui5/webcomponents-localization/dist/getCachedLocaleDataInstance.js"; @@ -295,6 +301,24 @@ class TimePicker extends UI5Element implements IFormInputElement { @property() accessibleNameRef?: string; + /** + * Defines the accessible description of the component. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescription?: string; + + /** + * Receives id(or many ids) of the elements that describe the input. + * @default undefined + * @public + * @since 2.14.0 + */ + @property() + accessibleDescriptionRef?: string; + @property({ type: Boolean, noAttribute: true }) _isInputsPopoverOpen = false; @@ -349,23 +373,28 @@ class TimePicker extends UI5Element implements IFormInputElement { this.tempValue = this.value && this.isValid(this.value) ? this.value : this.getFormat().format(UI5Date.getInstance()); } - get dateAriaDescription() { + get roleDescription() { return TimePicker.i18nBundle.getText(TIMEPICKER_INPUT_DESCRIPTION); } get pickerAccessibleName() { - return TimePicker.i18nBundle.getText(TIMEPICKER_POPOVER_ACCESSIBLE_NAME); + return TimePicker.i18nBundle.getText(TIMEPICKER_POPOVER_ACCESSIBLE_NAME, this.ariaLabelText); } get accInfo(): InputAccInfo { return { - "ariaRoledescription": this.dateAriaDescription, - "ariaHasPopup": "dialog", + "ariaRoledescription": this.roleDescription, + "ariaHasPopup": "grid", "ariaRequired": this.required, - "ariaLabel": getEffectiveAriaLabelText(this), + "ariaLabel": this.ariaLabelText || undefined, + "ariaDescription": getAllAccessibleDescriptionRefTexts(this) || getEffectiveAriaDescriptionText(this) || undefined, }; } + get ariaLabelText() { + return getAllAccessibleNameRefTexts(this) || getEffectiveAriaLabelText(this) || getAssociatedLabelForTexts(this) || ""; + } + /** * Currently selected time represented as JavaScript Date instance * @public diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 8c586cc6f69a..d541cb716cb8 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -185,16 +185,16 @@ DATETIME_DESCRIPTION=Date Time Input DATERANGE_DESCRIPTION=Date Range Input #XACT: Aria information for the Date Picker popover -DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date +DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date for {0} #XTXT: Date Picker placeholder prefix DATETIME_COMPONENTS_PLACEHOLDER_PREFIX=e.g. #XACT: Aria information for the Date Time Picker popover -DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time +DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time for {0} #XACT: Aria information for the Date Range Picker popover -DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date Range +DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date Range for {0} DELETE=Delete diff --git a/packages/main/test/pages/DatePicker.html b/packages/main/test/pages/DatePicker.html index da5348001ee5..b830c789f307 100644 --- a/packages/main/test/pages/DatePicker.html +++ b/packages/main/test/pages/DatePicker.html @@ -31,7 +31,7 @@
- Application context announcement + Deadline Application context announcement @@ -46,6 +46,24 @@ Application context announcement
+
+ Application context announcement
+ +
+ Application context announcement
+ +
+ + Application context announcement
+
+ +
+ Application context TWO announcement +
+ + +
+ - Deadline - - - Application context announcement - -
- Application context ONE announcement -
- Application context TWO announcement -
- -
- Application context announcement -
- -
- Application context announcement
- -
- Application context announcement
- -
- - Application context announcement
-
- -
- Application context TWO announcement -
- - -
- - - +
From 5987ba4999d64f43924d539c3c2d6c16a6970436 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Tue, 19 Aug 2025 14:20:14 +0100 Subject: [PATCH 8/9] fix: adjust tests --- packages/main/src/i18n/messagebundle_en.properties | 8 ++++---- packages/main/test/pages/DatePicker.html | 3 +++ packages/main/test/pages/DateRangePicker.html | 3 +++ packages/main/test/pages/DateTimePicker.html | 4 ++++ packages/main/test/pages/TimePicker.html | 5 ++++- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/main/src/i18n/messagebundle_en.properties b/packages/main/src/i18n/messagebundle_en.properties index 4cf6819d98b8..74b27a9ebd45 100644 --- a/packages/main/src/i18n/messagebundle_en.properties +++ b/packages/main/src/i18n/messagebundle_en.properties @@ -121,13 +121,13 @@ DATETIME_DESCRIPTION=Date Time Input DATERANGE_DESCRIPTION=Date Range Input -DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date +DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date for {0} DATETIME_COMPONENTS_PLACEHOLDER_PREFIX=e.g. -DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time +DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time for {0} -DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date Range +DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date Range for {0} DELETE=Delete @@ -324,7 +324,7 @@ TIMEPICKER_CANCEL_BUTTON=Cancel TIMEPICKER_INPUT_DESCRIPTION=Time Input -TIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Time +TIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Time for {0} TIMEPICKER_CLOCK_DIAL_LABEL=Clock Dial diff --git a/packages/main/test/pages/DatePicker.html b/packages/main/test/pages/DatePicker.html index ec3ebdbb0795..ea805a57901d 100644 --- a/packages/main/test/pages/DatePicker.html +++ b/packages/main/test/pages/DatePicker.html @@ -30,6 +30,9 @@
+ Deadline + +

DatePicker with value-state-change event prevented

diff --git a/packages/main/test/pages/DateRangePicker.html b/packages/main/test/pages/DateRangePicker.html index 0466b0298f62..c44746ca6f97 100644 --- a/packages/main/test/pages/DateRangePicker.html +++ b/packages/main/test/pages/DateRangePicker.html @@ -26,6 +26,9 @@
+ Deadline + +
diff --git a/packages/main/test/pages/DateTimePicker.html b/packages/main/test/pages/DateTimePicker.html index 89ee47ee7b2a..205dd3dd75f6 100644 --- a/packages/main/test/pages/DateTimePicker.html +++ b/packages/main/test/pages/DateTimePicker.html @@ -18,6 +18,10 @@ + + Deadline + +
DateTimePicker
diff --git a/packages/main/test/pages/TimePicker.html b/packages/main/test/pages/TimePicker.html index cb0edfd64cc1..c7c8930ee39e 100644 --- a/packages/main/test/pages/TimePicker.html +++ b/packages/main/test/pages/TimePicker.html @@ -12,7 +12,10 @@ - + + + Deadline +
From 197caf243294bc694a149989c3931a96de44ef5f Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Tue, 19 Aug 2025 18:50:35 +0100 Subject: [PATCH 9/9] fix: adjust tests --- packages/main/cypress/specs/DatePicker.cy.tsx | 160 +++++------ .../main/cypress/specs/DateRangePicker.cy.tsx | 258 +++++++++--------- .../main/cypress/specs/DateTimePicker.cy.tsx | 120 ++++---- packages/main/cypress/specs/TimePicker.cy.tsx | 44 +-- 4 files changed, 295 insertions(+), 287 deletions(-) diff --git a/packages/main/cypress/specs/DatePicker.cy.tsx b/packages/main/cypress/specs/DatePicker.cy.tsx index 0e8790d70730..07865db24ebb 100644 --- a/packages/main/cypress/specs/DatePicker.cy.tsx +++ b/packages/main/cypress/specs/DatePicker.cy.tsx @@ -6,49 +6,6 @@ import Label from "../../src/Label.js"; describe("Date Picker Tests", () => { - it("accessibleDescription property", () => { - const DESCRIPTION = "This is a date picker"; - cy.mount(); - - cy.get("[ui5-date-picker]") - .as("datePicker"); - - cy.get("@datePicker") - .ui5DatePickerGetInnerInput() - .should("have.attr", "aria-describedby", "descr"); - - cy.get("@datePicker") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("span#descr") - .should("have.text", DESCRIPTION); - }); - - it("accessibleDescriptionRef property", () => { - const DESCRIPTION = "This is a date picker"; - cy.mount( - <> -

{DESCRIPTION}

- - - ); - - cy.get("[ui5-date-picker]") - .as("datePicker"); - - cy.get("@datePicker") - .ui5DatePickerGetInnerInput() - .should("have.attr", "aria-describedby", "descr"); - - cy.get("@datePicker") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("span#descr") - .should("have.text", DESCRIPTION); - }); - it("input renders", () => { cy.mount(); @@ -1592,42 +1549,6 @@ describe("Date Picker Tests", () => { .find("ui5-yearpicker") .should("be.visible"); }); - - it("picker popover accessible name with external label", () => { - const LABEL = "Deadline"; - - cy.mount( - <> - - - - ); - - cy.get("[ui5-date-picker]") - .as("datePicker") - .ui5DatePickerValueHelpIconPress(); - - cy.get("@datePicker") - .shadow() - .find("ui5-responsive-popover") - .should("have.attr", "accessible-name", `Choose Date for ${LABEL}`); - }); - - it("picker popover accessible name", () => { - const LABEL = "Deadline"; - cy.mount( - - ); - - cy.get("[ui5-date-picker]") - .as("datePicker") - .ui5DatePickerValueHelpIconPress(); - - cy.get("@datePicker") - .shadow() - .find("ui5-responsive-popover") - .should("have.attr", "accessible-name", `Choose Date for ${LABEL}`); - }); }); describe("Legacy date customization and Islamic calendar type", () => { @@ -1756,3 +1677,84 @@ describe("Legacy date customization and Islamic calendar type", () => { .should("have.attr", "value-state", "None"); }); }); + +describe("Accessibility", () => { + it("picker popover accessible name with external label", () => { + const LABEL = "Deadline"; + + cy.mount( + <> + + + + ); + + cy.get("[ui5-date-picker]") + .as("datePicker") + .ui5DatePickerValueHelpIconPress(); + + cy.get("@datePicker") + .shadow() + .find("ui5-responsive-popover") + .should("have.attr", "accessible-name", `Choose Date for ${LABEL}`); + }); + + it("picker popover accessible name", () => { + const LABEL = "Deadline"; + cy.mount( + + ); + + cy.get("[ui5-date-picker]") + .as("datePicker") + .ui5DatePickerValueHelpIconPress(); + + cy.get("@datePicker") + .shadow() + .find("ui5-responsive-popover") + .should("have.attr", "accessible-name", `Choose Date for ${LABEL}`); + }); + + it("accessibleDescription property", () => { + const DESCRIPTION = "This is a date picker"; + cy.mount(); + + cy.get("[ui5-date-picker]") + .as("datePicker"); + + cy.get("@datePicker") + .ui5DatePickerGetInnerInput() + .should("have.attr", "aria-describedby", "descr"); + + cy.get("@datePicker") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("span#descr") + .should("have.text", DESCRIPTION); + }); + + it("accessibleDescriptionRef property", () => { + const DESCRIPTION = "This is a date picker"; + cy.mount( + <> +

{DESCRIPTION}

+ + + ); + + cy.get("[ui5-date-picker]") + .as("datePicker"); + + cy.get("@datePicker") + .ui5DatePickerGetInnerInput() + .should("have.attr", "aria-describedby", "descr"); + + cy.get("@datePicker") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("span#descr") + .should("have.text", DESCRIPTION); + }); +}); \ No newline at end of file diff --git a/packages/main/cypress/specs/DateRangePicker.cy.tsx b/packages/main/cypress/specs/DateRangePicker.cy.tsx index a7680f910b46..1957c15496c4 100644 --- a/packages/main/cypress/specs/DateRangePicker.cy.tsx +++ b/packages/main/cypress/specs/DateRangePicker.cy.tsx @@ -488,134 +488,6 @@ describe("DateRangePicker general interaction", () => { }); }); - it("Picker popover accessible name", () => { - const LABEL = "Deadline"; - cy.mount(); - - cy.get("[ui5-daterange-picker]") - .as("dateRangePicker") - .shadow() - .find("[ui5-datetime-input]") - .realClick() - .should("be.focused"); - - cy.realPress("F4"); - - cy.get("@dateRangePicker") - .ui5DateRangePickerExpectToBeOpen() - - cy.get("@dateRangePicker") - .shadow() - .find("[ui5-responsive-popover]") - .should("have.attr", "accessible-name", `Choose Date Range for ${LABEL}`); - }); - - it("Picker popover accessible name with external label", () => { - const LABEL = "Deadline"; - cy.mount(<> - - - ); - - cy.get("[ui5-daterange-picker]") - .as("dateRangePicker") - .shadow() - .find("[ui5-datetime-input]") - .realClick() - .should("be.focused"); - - cy.realPress("F4"); - - cy.get("@dateRangePicker") - .ui5DateRangePickerExpectToBeOpen() - - cy.get("@dateRangePicker") - .shadow() - .find("[ui5-responsive-popover]") - .should("have.attr", "accessible-name", `Choose Date Range for ${LABEL}`); - }); - - it("accessibleDescription property", () => { - const DESCRIPTION = "Some description"; - cy.mount(); - - cy.get("[ui5-daterange-picker]") - .ui5DatePickerGetInnerInput() - .should("have.attr", "aria-describedby", "descr"); - - cy.get("[ui5-daterange-picker]") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("span#descr") - .should("have.text", DESCRIPTION); - }); - - it("accessibleDescriptionRef property", () => { - const DESCRIPTION = "External description"; - cy.mount( - <> -

{DESCRIPTION}

- - - ); - - cy.get("[ui5-daterange-picker]") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("input") - .should("have.attr", "aria-describedby") - .and("contain", "descr"); - - cy.get("#descr").should("have.text", DESCRIPTION); - }); - - it("Selected days: accessibility semantics", () => { - cy.wrap({ setLanguage }) - .then(api => { - return api.setLanguage("en"); - }) - - cy.mount(); - - cy.get("[ui5-daterange-picker]") - .as("dateRangePicker") - .shadow() - .find("[ui5-datetime-input]") - .realClick() - .should("be.focused"); - - cy.realType("09/06/2024 - 15/06/2024"); - - cy.realPress("Enter") - - cy.get("@dateRangePicker") - .should("have.value", "09/06/2024 - 15/06/2024"); - - cy.realPress("F4"); - - cy.get("@dateRangePicker") - .ui5DateRangePickerExpectToBeOpen() - - cy.get("@dateRangePicker") - .shadow() - .find("[ui5-calendar]") - .shadow() - .find("[ui5-daypicker]") - .shadow() - .find(".ui5-dp-root .ui5-dp-content div > .ui5-dp-item") - .should(days => { - const startSelectionDay = days[14]; - const dayInBetween = days[15]; - const endSelectionDay = days[20]; - - expect(startSelectionDay).to.have.attr("aria-selected", "true"); - expect(dayInBetween).to.have.attr("aria-selected", "true"); - expect(endSelectionDay).to.have.attr("aria-selected", "true"); - }); - }); - it("Min and max dates are set without format-pattern by using ISO (yyyy-MM-dd) format", () => { cy.wrap({ setLanguage }) .then(api => { @@ -784,3 +656,133 @@ describe("DateRangePicker general interaction", () => { }); }); }); + +describe("Accessibility", () => { + it("Picker popover accessible name", () => { + const LABEL = "Deadline"; + cy.mount(); + + cy.get("[ui5-daterange-picker]") + .as("dateRangePicker") + .shadow() + .find("[ui5-datetime-input]") + .realClick() + .should("be.focused"); + + cy.realPress("F4"); + + cy.get("@dateRangePicker") + .ui5DateRangePickerExpectToBeOpen() + + cy.get("@dateRangePicker") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "accessible-name", `Choose Date Range for ${LABEL}`); + }); + + it("Picker popover accessible name with external label", () => { + const LABEL = "Deadline"; + cy.mount(<> + + + ); + + cy.get("[ui5-daterange-picker]") + .as("dateRangePicker") + .shadow() + .find("[ui5-datetime-input]") + .realClick() + .should("be.focused"); + + cy.realPress("F4"); + + cy.get("@dateRangePicker") + .ui5DateRangePickerExpectToBeOpen() + + cy.get("@dateRangePicker") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "accessible-name", `Choose Date Range for ${LABEL}`); + }); + + it("accessibleDescription property", () => { + const DESCRIPTION = "Some description"; + cy.mount(); + + cy.get("[ui5-daterange-picker]") + .ui5DatePickerGetInnerInput() + .should("have.attr", "aria-describedby", "descr"); + + cy.get("[ui5-daterange-picker]") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("span#descr") + .should("have.text", DESCRIPTION); + }); + + it("accessibleDescriptionRef property", () => { + const DESCRIPTION = "External description"; + cy.mount( + <> +

{DESCRIPTION}

+ + + ); + + cy.get("[ui5-daterange-picker]") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("input") + .should("have.attr", "aria-describedby") + .and("contain", "descr"); + + cy.get("#descr").should("have.text", DESCRIPTION); + }); + + it("Selected days: accessibility semantics", () => { + cy.wrap({ setLanguage }) + .then(api => { + return api.setLanguage("en"); + }) + + cy.mount(); + + cy.get("[ui5-daterange-picker]") + .as("dateRangePicker") + .shadow() + .find("[ui5-datetime-input]") + .realClick() + .should("be.focused"); + + cy.realType("09/06/2024 - 15/06/2024"); + + cy.realPress("Enter") + + cy.get("@dateRangePicker") + .should("have.value", "09/06/2024 - 15/06/2024"); + + cy.realPress("F4"); + + cy.get("@dateRangePicker") + .ui5DateRangePickerExpectToBeOpen() + + cy.get("@dateRangePicker") + .shadow() + .find("[ui5-calendar]") + .shadow() + .find("[ui5-daypicker]") + .shadow() + .find(".ui5-dp-root .ui5-dp-content div > .ui5-dp-item") + .should(days => { + const startSelectionDay = days[14]; + const dayInBetween = days[15]; + const endSelectionDay = days[20]; + + expect(startSelectionDay).to.have.attr("aria-selected", "true"); + expect(dayInBetween).to.have.attr("aria-selected", "true"); + expect(endSelectionDay).to.have.attr("aria-selected", "true"); + }); + }); +}); \ No newline at end of file diff --git a/packages/main/cypress/specs/DateTimePicker.cy.tsx b/packages/main/cypress/specs/DateTimePicker.cy.tsx index d428a93bc08b..74fa5ee68072 100644 --- a/packages/main/cypress/specs/DateTimePicker.cy.tsx +++ b/packages/main/cypress/specs/DateTimePicker.cy.tsx @@ -468,65 +468,6 @@ describe("DateTimePicker general interaction", () => { }); }); - it("picker popover accessible name", () => { - const LABEL = "Deadline"; - cy.mount(); - - cy.get("[ui5-datetime-picker]") - .ui5DateTimePickerGetPopover() - .should("have.attr", "accessible-name", `Choose Date and Time for ${LABEL}`); - }); - - it("picker popover accessible name with external label", () => { - const LABEL = "Deadline"; - cy.mount( - <> - - - - ); - - cy.get("[ui5-datetime-picker]") - .ui5DateTimePickerGetPopover() - .should("have.attr", "accessible-name", `Choose Date and Time for ${LABEL}`); - }); - - it("accessibleDescription property", () => { - const DESCRIPTION = "Some description"; - cy.mount(); - - cy.get("[ui5-datetime-picker]") - .ui5DatePickerGetInnerInput() - .should("have.attr", "aria-describedby", "descr"); - - cy.get("[ui5-datetime-picker]") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("span#descr") - .should("have.text", DESCRIPTION); - }); - - it("accessibleDescriptionRef property", () => { - const DESCRIPTION = "External description"; - cy.mount( - <> -

{DESCRIPTION}

- - - ); - - cy.get("[ui5-datetime-picker]") - .shadow() - .find("[ui5-datetime-input]") - .shadow() - .find("input") - .should("have.attr", "aria-describedby") - .and("contain", "descr"); - - cy.get("#descr").should("have.text", DESCRIPTION); - }); - it("value state", () => { cy.mount(); @@ -608,3 +549,64 @@ describe("DateTimePicker general interaction", () => { cy.get("@changeStub").should("have.been.calledOnce"); }); }); + +describe("Accessibility", () => { + it("picker popover accessible name", () => { + const LABEL = "Deadline"; + cy.mount(); + + cy.get("[ui5-datetime-picker]") + .ui5DateTimePickerGetPopover() + .should("have.attr", "accessible-name", `Choose Date and Time for ${LABEL}`); + }); + + it("picker popover accessible name with external label", () => { + const LABEL = "Deadline"; + cy.mount( + <> + + + + ); + + cy.get("[ui5-datetime-picker]") + .ui5DateTimePickerGetPopover() + .should("have.attr", "accessible-name", `Choose Date and Time for ${LABEL}`); + }); + + it("accessibleDescription property", () => { + const DESCRIPTION = "Some description"; + cy.mount(); + + cy.get("[ui5-datetime-picker]") + .ui5DatePickerGetInnerInput() + .should("have.attr", "aria-describedby", "descr"); + + cy.get("[ui5-datetime-picker]") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("span#descr") + .should("have.text", DESCRIPTION); + }); + + it("accessibleDescriptionRef property", () => { + const DESCRIPTION = "External description"; + cy.mount( + <> +

{DESCRIPTION}

+ + + ); + + cy.get("[ui5-datetime-picker]") + .shadow() + .find("[ui5-datetime-input]") + .shadow() + .find("input") + .should("have.attr", "aria-describedby") + .and("contain", "descr"); + + cy.get("#descr").should("have.text", DESCRIPTION); + }); +}); diff --git a/packages/main/cypress/specs/TimePicker.cy.tsx b/packages/main/cypress/specs/TimePicker.cy.tsx index 697c2ba82a52..632e91f0fafd 100644 --- a/packages/main/cypress/specs/TimePicker.cy.tsx +++ b/packages/main/cypress/specs/TimePicker.cy.tsx @@ -328,6 +328,28 @@ describe("TimePicker Tests", () => { .ui5ResponsivePopoverOpened() }); + it("displays value state message header in popover when value state is set", () => { + cy.mount(); + + cy.get("[ui5-time-picker]") + .as("timePicker") + .ui5TimePickerValueHelpIconPress(); + + cy.get("@timePicker") + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); + + cy.get("@timePicker") + .shadow() + .find("[ui5-responsive-popover]") + .find(".ui5-valuestatemessage-header") + .should("exist") + .and("have.class", "ui5-valuestatemessage--error"); + }); +}); + +describe("Accessibility", () => { it("picker popover accessible name", () => { const LABEL = "Deadline"; cy.mount(); @@ -428,24 +450,4 @@ describe("TimePicker Tests", () => { .ui5TimePickerGetInnerInput() .should("have.attr", "aria-label", "Pick a time"); }); - - it("displays value state message header in popover when value state is set", () => { - cy.mount(); - - cy.get("[ui5-time-picker]") - .as("timePicker") - .ui5TimePickerValueHelpIconPress(); - - cy.get("@timePicker") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); - - cy.get("@timePicker") - .shadow() - .find("[ui5-responsive-popover]") - .find(".ui5-valuestatemessage-header") - .should("exist") - .and("have.class", "ui5-valuestatemessage--error"); - }); -}); \ No newline at end of file +}); \ No newline at end of file