diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index 56657d2b8627..a1f1dc8eddac 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -14,6 +14,7 @@ @ui5-change="{{_handleInputChange}}" @ui5-input="{{_handleInputLiveChange}}" data-sap-focus-ref + ._inputAccInfo ="{{accInfo}}" > {{#unless readonly}} {{/unless}} @@ -46,6 +49,5 @@ @ui5-selectedDatesChange="{{_calendar.onSelectedDatesChange}}" > - diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 8e14d0c70dd3..7a95672407b9 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -13,6 +13,8 @@ import CalendarDate from "@ui5/webcomponents-base/dist/dates/CalendarDate.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import { isShow } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js"; import "./icons/appointment-2.js"; +import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_ACC_TEXT } from "./generated/i18n/i18n-defaults.js"; import Icon from "./Icon.js"; import Popover from "./Popover.js"; import Calendar from "./Calendar.js"; @@ -285,6 +287,8 @@ class DatePicker extends UI5Element { onSelectedDatesChange: this._handleCalendarSelectedDatesChange.bind(this), selectedDates: [], }; + + this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } onBeforeRendering() { @@ -397,6 +401,26 @@ class DatePicker extends UI5Element { return this._oDateFormat; } + get accInfo() { + return { + "ariaDescribedBy": `${this._id}-date`, + "ariaHasPopup": "true", + "ariaAutoComplete": "none", + "role": "combobox", + "ariaOwns": `${this._id}-popover`, + "ariaExpanded": this.isOpen(), + "ariaDescription": this.dateAriaDescription, + }; + } + + get openIconTitle() { + return this.i18nBundle.getText(DATEPICKER_OPEN_ICON_TITLE); + } + + get dateAriaDescription() { + return this.i18nBundle.getText(DATEPICKER_DATE_ACC_TEXT); + } + _getPopover() { return this.shadowRoot.querySelector("ui5-popover"); } @@ -544,6 +568,7 @@ class DatePicker extends UI5Element { Popover.define(), Calendar.define(), Input.define(), + fetchI18nBundle("@ui5/webcomponents"), ]); super.define(...params); diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index e362d20dee33..eaf02bd056e0 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -16,10 +16,13 @@ ?required="{{required}}" .value="{{value}}" placeholder="{{inputPlaceholder}}" - aria-invalid="{{ariaInvalid}}" - aria-haspopup="{{ariaHasPopup}}" - aria-describedby="{{ariaDescribedBy}}" - aria-autocomplete="{{ariaAutoComplete}}" + role="{{accInfo.input.role}}" + aria-owns="{{accInfo.input.ariaOwns}}" + aria-invalid="{{accInfo.input.ariaInvalid}}" + aria-haspopup="{{accInfo.input.ariaHasPopup}}" + aria-describedby="{{accInfo.input.ariaDescribedBy}}" + aria-autocomplete="{{accInfo.input.ariaAutoComplete}}" + aria-expanded="{{accInfo.input.ariaExpanded}}" @input="{{_handleInput}}" @change="{{_handleChange}}" data-sap-no-tab-ref @@ -35,6 +38,10 @@ {{suggestionsText}} {{/if}} + {{#if accInfo.input.ariaDescribedBy}} + {{accInfo.input.ariaDescription}} + {{/if}} + {{#if hasValueState}} {{valueStateText}} {{/if}} diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 27088e4b7f7d..dfa4bab1efa1 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -220,6 +220,14 @@ const metadata = { _popover: { type: Object, }, + + _inputAccInfo: { + type: Object, + }, + + _wrapperAccInfo: { + type: Object, + }, }, events: /** @lends sap.ui.webcomponents.main.Input.prototype */ { /** @@ -568,28 +576,31 @@ class Input extends UI5Element { return this.type.toLowerCase(); } - get ariaInvalid() { - return this.valueState === ValueState.Error ? "true" : undefined; - } - get suggestionsTextId() { return this.showSuggestions ? `${this._id}-suggestionsText` : ""; - } + } get valueStateTextId() { return this.hasValueState ? `${this._id}-descr` : ""; } - get ariaDescribedBy() { - return `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(); - } - - get ariaHasPopup() { - return this.showSuggestions ? "true" : undefined; - } - - get ariaAutoComplete() { - return this.showSuggestions ? "list" : undefined; + get accInfo() { + const ariaHasPopupDefault = this.showSuggestions ? "true" : undefined; + const ariaAutoCompleteDefault = this.showSuggestions ? "list" : undefined; + return { + "wrapper": { + }, + "input": { + "ariaDescribedBy": this._inputAccInfo ? `${this.suggestionsTextId} ${this.valueStateTextId} ${this._inputAccInfo.ariaDescribedBy}`.trim() : `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(), + "ariaInvalid": this.valueState === ValueState.Error ? "true" : undefined, + "ariaHasPopup": this._inputAccInfo ? this._inputAccInfo.ariaHasPopup : ariaHasPopupDefault, + "ariaAutoComplete": this._inputAccInfo ? this._inputAccInfo.ariaAutoComplete : ariaAutoCompleteDefault, + "role": this._inputAccInfo && this._inputAccInfo.role, + "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, + "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, + "ariaDescription": this._inputAccInfo && this._inputAccInfo.ariaDescription, + }, + }; } get hasValueState() { diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 85ef7abbc110..29f343b711b6 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -25,6 +25,12 @@ BUTTON_ARIA_TYPE_REJECT=Negative Action #XACT: ARIA announcement for the emphasized button BUTTON_ARIA_TYPE_EMPHASIZED=Emphasized +#XACT: Date +DATEPICKER_DATE_ACC_TEXT=Date + +#XACT: DatePicker 'Open Picker' icon title +DATEPICKER_OPEN_ICON_TITLE=Open Picker + #XTXT ICON_ACTION_SETTINGS=Settings diff --git a/packages/main/src/themes/DatePicker.css b/packages/main/src/themes/DatePicker.css index a99da7fde36f..2d47a667550f 100644 --- a/packages/main/src/themes/DatePicker.css +++ b/packages/main/src/themes/DatePicker.css @@ -1,3 +1,5 @@ +@import "./InvisibleTextStyles.css"; + :host(:not([hidden])) { display: inline-block; }