@ui5/webcomponents 0.31.14 → 0.31.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +1 -1
  3. package/dist/Avatar.js +8 -6
  4. package/dist/CalendarHeader.js +75 -1
  5. package/dist/Card.js +19 -2
  6. package/dist/ComboBox.js +10 -0
  7. package/dist/DateComponentBase.js +12 -0
  8. package/dist/DatePicker.js +48 -9
  9. package/dist/DayPicker.js +21 -2
  10. package/dist/FileUploader.js +8 -0
  11. package/dist/GroupHeaderListItem.js +4 -0
  12. package/dist/Icon.js +6 -6
  13. package/dist/Input.js +10 -2
  14. package/dist/Label.js +1 -1
  15. package/dist/List.js +8 -5
  16. package/dist/ListItem.js +25 -4
  17. package/dist/Panel.js +17 -5
  18. package/dist/Popup.js +16 -5
  19. package/dist/RadioButton.js +15 -2
  20. package/dist/ResponsivePopover.js +3 -2
  21. package/dist/SegmentedButton.js +85 -53
  22. package/dist/SegmentedButtonItem.js +112 -0
  23. package/dist/Toast.js +11 -0
  24. package/dist/TreeListItem.js +2 -12
  25. package/dist/api.json +1 -1
  26. package/dist/generated/assets/themes/sap_belize/parameters-bundle.css.json +1 -1
  27. package/dist/generated/assets/themes/sap_belize_hcb/parameters-bundle.css.json +1 -1
  28. package/dist/generated/assets/themes/sap_belize_hcw/parameters-bundle.css.json +1 -1
  29. package/dist/generated/assets/themes/sap_fiori_3/parameters-bundle.css.json +1 -1
  30. package/dist/generated/assets/themes/sap_fiori_3_dark/parameters-bundle.css.json +1 -1
  31. package/dist/generated/assets/themes/sap_fiori_3_hcb/parameters-bundle.css.json +1 -1
  32. package/dist/generated/assets/themes/sap_fiori_3_hcw/parameters-bundle.css.json +1 -1
  33. package/dist/generated/i18n/i18n-defaults.js +2 -2
  34. package/dist/generated/templates/CalendarHeaderTemplate.lit.js +3 -1
  35. package/dist/generated/templates/CalendarTemplate.lit.js +1 -1
  36. package/dist/generated/templates/CardTemplate.lit.js +1 -1
  37. package/dist/generated/templates/CustomListItemTemplate.lit.js +3 -3
  38. package/dist/generated/templates/DatePickerPopoverTemplate.lit.js +1 -1
  39. package/dist/generated/templates/DateTimePickerPopoverTemplate.lit.js +1 -1
  40. package/dist/generated/templates/DayPickerTemplate.lit.js +7 -6
  41. package/dist/generated/templates/FileUploaderTemplate.lit.js +1 -1
  42. package/dist/generated/templates/GroupHeaderListItemTemplate.lit.js +1 -1
  43. package/dist/generated/templates/ListItemTemplate.lit.js +3 -3
  44. package/dist/generated/templates/ListTemplate.lit.js +1 -1
  45. package/dist/generated/templates/RadioButtonTemplate.lit.js +1 -1
  46. package/dist/generated/templates/SegmentedButtonItemTemplate.lit.js +15 -0
  47. package/dist/generated/templates/SegmentedButtonTemplate.lit.js +1 -1
  48. package/dist/generated/templates/StandardListItemTemplate.lit.js +3 -3
  49. package/dist/generated/templates/SuggestionListItemTemplate.lit.js +3 -3
  50. package/dist/generated/templates/ToastTemplate.lit.js +2 -1
  51. package/dist/generated/templates/TreeListItemTemplate.lit.js +3 -3
  52. package/dist/generated/templates/TreeTemplate.lit.js +1 -1
  53. package/dist/generated/themes/Badge.css.js +1 -1
  54. package/dist/generated/themes/Button.css.js +1 -1
  55. package/dist/generated/themes/CalendarHeader.css.js +1 -1
  56. package/dist/generated/themes/Card.css.js +1 -1
  57. package/dist/generated/themes/CheckBox.css.js +1 -1
  58. package/dist/generated/themes/ComboBox.css.js +1 -1
  59. package/dist/generated/themes/DatePicker.css.js +1 -1
  60. package/dist/generated/themes/DayPicker.css.js +1 -1
  61. package/dist/generated/themes/GroupHeaderListItem.css.js +1 -1
  62. package/dist/generated/themes/Input.css.js +1 -1
  63. package/dist/generated/themes/InvisibleTextStyles.css.js +1 -1
  64. package/dist/generated/themes/Label.css.js +1 -1
  65. package/dist/generated/themes/Link.css.js +1 -1
  66. package/dist/generated/themes/ListItem.css.js +1 -1
  67. package/dist/generated/themes/MessageStrip.css.js +1 -1
  68. package/dist/generated/themes/MultiComboBox.css.js +1 -1
  69. package/dist/generated/themes/Panel.css.js +1 -1
  70. package/dist/generated/themes/RadioButton.css.js +1 -1
  71. package/dist/generated/themes/SegmentedButton.css.js +1 -1
  72. package/dist/generated/themes/Select.css.js +1 -1
  73. package/dist/generated/themes/SliderBase.css.js +1 -1
  74. package/dist/generated/themes/StepInput.css.js +1 -1
  75. package/dist/generated/themes/Switch.css.js +1 -1
  76. package/dist/generated/themes/TextArea.css.js +1 -1
  77. package/dist/generated/themes/Tokenizer.css.js +1 -1
  78. package/dist/generated/themes/Tree.css.js +1 -1
  79. package/dist/generated/themes/TreeListItem.css.js +1 -1
  80. package/dist/generated/themes/ValueStateMessage.css.js +1 -1
  81. package/dist/generated/themes/sap_belize/parameters-bundle.css.js +1 -1
  82. package/dist/generated/themes/sap_belize_hcb/parameters-bundle.css.js +1 -1
  83. package/dist/generated/themes/sap_belize_hcw/parameters-bundle.css.js +1 -1
  84. package/dist/generated/themes/sap_fiori_3/parameters-bundle.css.js +1 -1
  85. package/dist/generated/themes/sap_fiori_3_dark/parameters-bundle.css.js +1 -1
  86. package/dist/generated/themes/sap_fiori_3_hcb/parameters-bundle.css.js +1 -1
  87. package/dist/generated/themes/sap_fiori_3_hcw/parameters-bundle.css.js +1 -1
  88. package/dist/i18n/messagebundle.properties +13 -1
  89. package/dist/popup-utils/OpenedPopupsRegistry.js +1 -1
  90. package/package.json +7 -7
  91. package/src/Avatar.js +8 -6
  92. package/src/Calendar.hbs +2 -0
  93. package/src/CalendarHeader.hbs +11 -4
  94. package/src/CalendarHeader.js +75 -1
  95. package/src/Card.hbs +1 -1
  96. package/src/Card.js +19 -2
  97. package/src/ComboBox.js +10 -0
  98. package/src/DateComponentBase.js +12 -0
  99. package/src/DatePicker.js +48 -9
  100. package/src/DatePickerPopover.hbs +1 -0
  101. package/src/DateTimePickerPopover.hbs +4 -4
  102. package/src/DayPicker.hbs +6 -1
  103. package/src/DayPicker.js +21 -2
  104. package/src/FileUploader.hbs +1 -0
  105. package/src/FileUploader.js +8 -0
  106. package/src/GroupHeaderListItem.hbs +3 -3
  107. package/src/GroupHeaderListItem.js +4 -0
  108. package/src/Icon.js +6 -6
  109. package/src/Input.js +10 -2
  110. package/src/Label.js +1 -1
  111. package/src/List.hbs +1 -2
  112. package/src/List.js +8 -5
  113. package/src/ListItem.hbs +3 -1
  114. package/src/ListItem.js +25 -4
  115. package/src/Panel.js +17 -5
  116. package/src/Popup.js +16 -5
  117. package/src/RadioButton.hbs +1 -1
  118. package/src/RadioButton.js +15 -2
  119. package/src/ResponsivePopover.js +3 -2
  120. package/src/SegmentedButton.hbs +12 -5
  121. package/src/SegmentedButton.js +85 -53
  122. package/src/SegmentedButtonItem.hbs +42 -0
  123. package/src/SegmentedButtonItem.js +112 -0
  124. package/src/Toast.hbs +13 -11
  125. package/src/Toast.js +11 -0
  126. package/src/Tree.hbs +1 -1
  127. package/src/TreeListItem.js +2 -12
  128. package/src/i18n/messagebundle.properties +13 -1
  129. package/src/popup-utils/OpenedPopupsRegistry.js +1 -1
@@ -26,6 +26,18 @@ const metadata = {
26
26
  type: CalendarType,
27
27
  },
28
28
 
29
+ /**
30
+ * Defines the secondary calendar type.
31
+ * If not set, the calendar will only show the primary calendar type.
32
+ * @type {CalendarType}
33
+ * @since 1.0.0-rc.16
34
+ * @defaultvalue undefined
35
+ * @public
36
+ */
37
+ secondaryCalendarType: {
38
+ type: CalendarType,
39
+ },
40
+
29
41
  /**
30
42
  * Determines the мinimum date available for selection.
31
43
  *
package/src/DatePicker.js CHANGED
@@ -230,17 +230,41 @@ const metadata = {
230
230
  * Fired when the input operation has finished by pressing Enter or on focusout.
231
231
  *
232
232
  * @event
233
+ * @allowPreventDefault
233
234
  * @public
235
+ * @param {String} value The submitted value.
236
+ * @param {Boolean} valid Indicator if the value is in correct format pattern and in valid range.
234
237
  */
235
- change: {},
238
+ change: {
239
+ details: {
240
+ value: {
241
+ type: String,
242
+ },
243
+ valid: {
244
+ type: Boolean,
245
+ },
246
+ },
247
+ },
236
248
 
237
249
  /**
238
250
  * Fired when the value of the <code>ui5-date-picker</code> is changed at each key stroke.
239
251
  *
240
252
  * @event
253
+ * @allowPreventDefault
241
254
  * @public
255
+ * @param {String} value The submitted value.
256
+ * @param {Boolean} valid Indicator if the value is in correct format pattern and in valid range.
242
257
  */
243
- input: {},
258
+ input: {
259
+ details: {
260
+ value: {
261
+ type: String,
262
+ },
263
+ valid: {
264
+ type: Boolean,
265
+ },
266
+ },
267
+ },
244
268
  },
245
269
  };
246
270
 
@@ -379,6 +403,8 @@ class DatePicker extends DateComponentBase {
379
403
  } else if (this.name) {
380
404
  console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js";`); // eslint-disable-line
381
405
  }
406
+
407
+ this.liveValue = this.value;
382
408
  }
383
409
 
384
410
  /**
@@ -471,17 +497,30 @@ class DatePicker extends DateComponentBase {
471
497
  this._updateValueAndFireEvents(newValue, true, ["change", "value-changed"]);
472
498
  }
473
499
 
474
- _updateValueAndFireEvents(value, normalizeValue, events) {
500
+ _updateValueAndFireEvents(value, normalizeValue, events, updateValue = true) {
475
501
  const valid = this._checkValueValidity(value);
502
+
476
503
  if (valid && normalizeValue) {
477
504
  value = this.normalizeValue(value); // transform valid values (in any format) to the correct format
478
505
  }
479
506
 
480
- this.value = value;
481
- this._updateValueState(); // Change the value state to Error/None, but only if needed
507
+ let executeEvent = true;
508
+ this.liveValue = value;
509
+
482
510
  events.forEach(event => {
483
- this.fireEvent(event, { value, valid });
511
+ if (!this.fireEvent(event, { value, valid }, true)) {
512
+ executeEvent = false;
513
+ }
484
514
  });
515
+
516
+ if (!executeEvent) {
517
+ return;
518
+ }
519
+
520
+ if (updateValue) {
521
+ this.value = value;
522
+ this._updateValueState(); // Change the value state to Error/None, but only if needed
523
+ }
485
524
  }
486
525
 
487
526
  _updateValueState() {
@@ -521,7 +560,7 @@ class DatePicker extends DateComponentBase {
521
560
  * @protected
522
561
  */
523
562
  async _onInputInput(event) {
524
- this._updateValueAndFireEvents(event.target.value, false, ["input"]);
563
+ this._updateValueAndFireEvents(event.target.value, false, ["input"], false);
525
564
  }
526
565
 
527
566
  /**
@@ -722,11 +761,11 @@ class DatePicker extends DateComponentBase {
722
761
  * @public
723
762
  */
724
763
  get dateValue() {
725
- return this.getFormat().parse(this.value);
764
+ return this.liveValue ? this.getFormat().parse(this.liveValue) : this.getFormat().parse(this.value);
726
765
  }
727
766
 
728
767
  get dateValueUTC() {
729
- return this.getFormat().parse(this.value, true);
768
+ return this.liveValue ? this.getFormat().parse(this.liveValue, true) : this.getFormat().parse(this.value);
730
769
  }
731
770
 
732
771
  get styles() {
@@ -42,6 +42,7 @@
42
42
  <ui5-calendar
43
43
  id="{{_id}}-calendar"
44
44
  primary-calendar-type="{{_primaryCalendarType}}"
45
+ secondary-calendar-type="{{secondaryCalendarType}}"
45
46
  format-pattern="{{_formatPattern}}"
46
47
  timestamp="{{_calendarTimestamp}}"
47
48
  .selectionMode="{{_calendarSelectionMode}}"
@@ -4,10 +4,10 @@
4
4
  {{#*inline "header"}}
5
5
  {{#if phone}}
6
6
  <div class="ui5-dt-picker-header">
7
- <ui5-segmentedbutton style="width: 8rem">
8
- <ui5-togglebutton key="Date" ?pressed="{{showDateView}}" @click="{{_dateTimeSwitchChange}}">{{btnDateLabel}}</ui5-togglebutton>
9
- <ui5-togglebutton key="Time" ?pressed="{{showTimeView}}" @click="{{_dateTimeSwitchChange}}">{{btnTimeLabel}}</ui5-togglebutton>
10
- </ui5-segmentedbutton>
7
+ <ui5-segmented-button style="width: 8rem">
8
+ <ui5-segmented-button-item key="Date" ?pressed="{{showDateView}}" @click="{{_dateTimeSwitchChange}}">{{btnDateLabel}}</ui5-segmented-button-item>
9
+ <ui5-segmented-button-item key="Time" ?pressed="{{showTimeView}}" @click="{{_dateTimeSwitchChange}}">{{btnTimeLabel}}</ui5-segmented-button-item>
10
+ </ui5-segmented-button>
11
11
  </div>
12
12
  {{/if}}
13
13
  {{/inline}}
package/src/DayPicker.hbs CHANGED
@@ -38,8 +38,13 @@
38
38
  class="ui5-dp-daytext"
39
39
  data-sap-timestamp="{{this.timestamp}}"
40
40
  >
41
- {{this.iDay}}
41
+ {{this.day}}
42
42
  </span>
43
+ {{#if this._isSecondaryCalendarType}}
44
+ <span class="ui5-dp-daytext ui5-dp-daysectext" >
45
+ {{this.secondDay}}
46
+ </span>
47
+ {{/if}}
43
48
  </div>
44
49
  {{else}}
45
50
  {{#unless this.isHidden}}
package/src/DayPicker.js CHANGED
@@ -184,6 +184,7 @@ class DayPicker extends CalendarPart {
184
184
 
185
185
  const firstDayOfWeek = this._getFirstDayOfWeek();
186
186
  const monthsNames = localeData.getMonths("wide", this._primaryCalendarType);
187
+ const secondaryMonthsNames = this.hasSecondaryCalendarType && localeData.getMonths("wide", this.secondaryCalendarType);
187
188
  const nonWorkingDayLabel = this.i18nBundle.getText(DAY_PICKER_NON_WORKING_DAY);
188
189
  const todayLabel = this.i18nBundle.getText(DAY_PICKER_TODAY);
189
190
  const tempDate = this._getFirstDay(); // date that will be changed by 1 day 42 times
@@ -192,6 +193,8 @@ class DayPicker extends CalendarPart {
192
193
  const minDate = this._minDate; // store the _minDate (expensive getter)
193
194
  const maxDate = this._maxDate; // store the _maxDate (expensive getter)
194
195
 
196
+ const tempSecondDate = this.hasSecondaryCalendarType && this._getSecondaryDay(tempDate);
197
+
195
198
  let week = [];
196
199
  for (let i = 0; i < DAYS_IN_WEEK * 6; i++) { // always show 6 weeks total, 42 days to avoid jumping
197
200
  const timestamp = tempDate.valueOf() / 1000; // no need to round because CalendarDate does it
@@ -212,15 +215,20 @@ class DayPicker extends CalendarPart {
212
215
 
213
216
  const nonWorkingAriaLabel = isWeekend ? `${nonWorkingDayLabel} ` : "";
214
217
  const todayAriaLabel = isToday ? `${todayLabel} ` : "";
218
+ const ariaLabel = this.hasSecondaryCalendarType
219
+ ? `${todayAriaLabel}${nonWorkingAriaLabel}${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()} ${secondaryMonthsNames[tempSecondDate.getMonth()]} ${tempSecondDate.getDate()}, ${tempSecondDate.getYear()}`
220
+ : `${todayAriaLabel}${nonWorkingAriaLabel}${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}`;
215
221
 
216
222
  const day = {
217
223
  timestamp: timestamp.toString(),
218
224
  focusRef: isFocused,
219
225
  _tabIndex: isFocused ? "0" : "-1",
220
226
  selected: isSelected,
221
- iDay: tempDate.getDate(),
227
+ day: tempDate.getDate(),
228
+ secondDay: this.hasSecondaryCalendarType && tempSecondDate.getDate(),
229
+ _isSecondaryCalendarType: this.hasSecondaryCalendarType,
222
230
  classes: `ui5-dp-item ui5-dp-wday${dayOfTheWeek}`,
223
- ariaLabel: `${todayAriaLabel}${nonWorkingAriaLabel}${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}`,
231
+ ariaLabel,
224
232
  ariaSelected: isSelected ? "true" : "false",
225
233
  ariaDisabled: isOtherMonth ? "true" : undefined,
226
234
  disabled: isDisabled,
@@ -268,6 +276,9 @@ class DayPicker extends CalendarPart {
268
276
  }
269
277
 
270
278
  tempDate.setDate(tempDate.getDate() + 1);
279
+ if (this.hasSecondaryCalendarType) {
280
+ tempSecondDate.setDate(tempSecondDate.getDate() + 1);
281
+ }
271
282
  }
272
283
  }
273
284
 
@@ -656,6 +667,10 @@ class DayPicker extends CalendarPart {
656
667
  return this.hideWeekNumbers;
657
668
  }
658
669
 
670
+ get hasSecondaryCalendarType() {
671
+ return !!this.secondaryCalendarType;
672
+ }
673
+
659
674
  _isWeekend(oDate) {
660
675
  const localeData = getCachedLocaleDataInstance(getLocale());
661
676
 
@@ -672,6 +687,10 @@ class DayPicker extends CalendarPart {
672
687
  return (target.className.indexOf("ui5-dp-item") > -1) || (targetParent && targetParent.classList && targetParent.classList.contains("ui5-dp-item"));
673
688
  }
674
689
 
690
+ _getSecondaryDay(tempDate) {
691
+ return new CalendarDate(tempDate, this.secondaryCalendarType);
692
+ }
693
+
675
694
  _getFirstDay() {
676
695
  let daysFromPreviousMonth;
677
696
 
@@ -6,6 +6,7 @@
6
6
  @focusout="{{_onfocusout}}"
7
7
  @keydown="{{_onkeydown}}"
8
8
  @keyup="{{_onkeyup}}"
9
+ @click="{{_onclick}}"
9
10
  >
10
11
  <div class="ui5-file-uploader-mask">
11
12
  {{#unless hideInput}}
@@ -274,15 +274,23 @@ class FileUploader extends UI5Element {
274
274
  });
275
275
  }
276
276
 
277
+ _onclick(event) {
278
+ if (event.isMarked === "button") {
279
+ this._input.click(event);
280
+ }
281
+ }
282
+
277
283
  _onkeydown(event) {
278
284
  if (isEnter(event)) {
279
285
  this._input.click(event);
286
+ event.preventDefault();
280
287
  }
281
288
  }
282
289
 
283
290
  _onkeyup(event) {
284
291
  if (isSpace(event)) {
285
292
  this._input.click(event);
293
+ event.preventDefault();
286
294
  }
287
295
  }
288
296
 
@@ -4,11 +4,11 @@
4
4
  @focusin="{{_onfocusin}}"
5
5
  @focusout="{{_onfocusout}}"
6
6
  @keydown="{{_onkeydown}}"
7
- role="option"
7
+ aria-label="{{ariaLabelText}}"
8
+ aria-roledescription="{{groupHeaderText}}"
9
+ role="group"
8
10
  style="list-style-type: none;"
9
11
  >
10
- <span class="ui5-hidden-text">{{groupHeaderText}} {{accessibleName}}</span>
11
-
12
12
  <div id="{{_id}}-content" class="ui5-li-content">
13
13
  <span class="ui5-ghli-title"><slot></slot></span>
14
14
  </div>
@@ -85,6 +85,10 @@ class GroupHeaderListItem extends ListItemBase {
85
85
  return this.i18nBundle.getText(GROUP_HEADER_TEXT);
86
86
  }
87
87
 
88
+ get ariaLabelText() {
89
+ return [this.textContent, this.accessibleName].filter(Boolean).join(" ");
90
+ }
91
+
88
92
  static async onDefine() {
89
93
  await Promise.all([
90
94
  fetchI18nBundle("@ui5/webcomponents"),
package/src/Icon.js CHANGED
@@ -237,12 +237,10 @@ class Icon extends UI5Element {
237
237
  }
238
238
  }
239
239
 
240
- _onclick(event) {
241
- if (this.interactive) {
242
- // prevent the native event and fire custom event to ensure the noConfict "ui5-click" is fired
243
- event.stopPropagation();
244
- this.fireEvent("click");
245
- }
240
+ _onClickHandler(event) {
241
+ // prevent the native event and fire custom event to ensure the noConfict "ui5-click" is fired
242
+ event.stopPropagation();
243
+ this.fireEvent("click");
246
244
  }
247
245
 
248
246
  get _dir() {
@@ -329,6 +327,8 @@ class Icon extends UI5Element {
329
327
  this.ltr = iconData.ltr;
330
328
  this.packageName = iconData.packageName;
331
329
 
330
+ this._onclick = this.interactive ? this._onClickHandler.bind(this) : undefined;
331
+
332
332
  if (this.accessibleName) {
333
333
  this.effectiveAccessibleName = this.accessibleName;
334
334
  } else if (this.accData) {
package/src/Input.js CHANGED
@@ -836,6 +836,14 @@ class Input extends UI5Element {
836
836
  return !!this._isPopoverOpen;
837
837
  }
838
838
 
839
+ /**
840
+ * Checks if the value state popover is open.
841
+ * @returns {boolean} true if the value state popover is open, false otherwise
842
+ */
843
+ isValueStateOpened() {
844
+ return !!this._isPopoverOpen;
845
+ }
846
+
839
847
  async openPopover() {
840
848
  const popover = await this._getPopover();
841
849
 
@@ -1168,7 +1176,8 @@ class Input extends UI5Element {
1168
1176
  return {
1169
1177
  popoverValueState: {
1170
1178
  "ui5-valuestatemessage-root": true,
1171
- "ui5-responsive-popover-header": !this.isOpen(),
1179
+ "ui5-valuestatemessage-header": true,
1180
+ "ui5-responsive-popover-header": !this.isValueStateOpened(),
1172
1181
  "ui5-valuestatemessage--success": this.valueState === ValueState.Success,
1173
1182
  "ui5-valuestatemessage--error": this.valueState === ValueState.Error,
1174
1183
  "ui5-valuestatemessage--warning": this.valueState === ValueState.Warning,
@@ -1185,7 +1194,6 @@ class Input extends UI5Element {
1185
1194
  suggestionPopoverHeader: {
1186
1195
  "display": this._listWidth === 0 ? "none" : "inline-block",
1187
1196
  "width": `${this._listWidth}px`,
1188
- "padding": "0.925rem 1rem",
1189
1197
  },
1190
1198
  suggestionsPopover: {
1191
1199
  "max-width": `${this._inputWidth}px`,
package/src/Label.js CHANGED
@@ -42,7 +42,7 @@ const metadata = {
42
42
  },
43
43
 
44
44
  /**
45
- * Defines whether semi-colon is added to the <code>ui5-label</code> text.
45
+ * Defines whether colon is added to the component text.
46
46
  * <br><br>
47
47
  * <b>Note:</b> Usually used in forms.
48
48
  * @type {boolean}
package/src/List.hbs CHANGED
@@ -20,10 +20,9 @@
20
20
 
21
21
  <ul id="{{_id}}-listUl"
22
22
  class="ui5-list-ul"
23
- role="{{accRole}}"
23
+ role="{{accessibleRole}}"
24
24
  aria-label="{{ariaLabelТxt}}"
25
25
  aria-labelledby="{{ariaLabelledBy}}"
26
- aria-multiselectable="{{isMultiSelect}}"
27
26
  >
28
27
  <slot></slot>
29
28
 
package/src/List.js CHANGED
@@ -208,16 +208,19 @@ const metadata = {
208
208
  },
209
209
 
210
210
  /**
211
- * Used to externally manipulate the role of the list
211
+ * Defines the accessible role of the component.
212
+ * <br><br>
213
+ * <b>Note:</b> If you use notification list items,
214
+ * it's recommended to set <code>accessible-role="list"</code> for better accessibility.
212
215
  *
213
216
  * @private
214
217
  * @type {String}
215
- * @defaultvalue "listbox"
216
- * @since 1.0.0-rc.9
218
+ * @defaultvalue "list"
219
+ * @since 1.0.0-rc.15
217
220
  */
218
- accRole: {
221
+ accessibleRole: {
219
222
  type: String,
220
- defaultValue: "listbox",
223
+ defaultValue: "list",
221
224
  },
222
225
 
223
226
  /**
package/src/ListItem.hbs CHANGED
@@ -11,13 +11,13 @@
11
11
  @touchstart="{{_ontouchstart}}"
12
12
  @touchend="{{_ontouchend}}"
13
13
  @click="{{_onclick}}"
14
- aria-selected="{{ariaSelected}}"
15
14
  role="{{_accInfo.role}}"
16
15
  aria-expanded="{{_accInfo.ariaExpanded}}"
17
16
  title="{{title}}"
18
17
  aria-level="{{_accInfo.ariaLevel}}"
19
18
  aria-posinset="{{_accInfo.posinset}}"
20
19
  aria-setsize="{{_accInfo.setsize}}"
20
+ aria-describedby="{{_id}}-invisibleText-describedby"
21
21
  aria-labelledby="{{_id}}-invisibleText {{_id}}-content"
22
22
  aria-disabled="{{ariaDisabled}}"
23
23
  style="list-style-type: none;"
@@ -50,6 +50,7 @@
50
50
  {{/if}}
51
51
 
52
52
  <span id="{{_id}}-invisibleText" class="ui5-hidden-text">{{_accInfo.listItemAriaLabel}} {{accessibleName}}</span>
53
+ <span id="{{_id}}-invisibleText-describedby" class="ui5-hidden-text">{{_accInfo.ariaSelectedText}}</span>
53
54
  </li>
54
55
 
55
56
  {{#*inline "listItemPreContent"}}{{/inline}}
@@ -62,6 +63,7 @@
62
63
  {{#if modeSingleSelect}}
63
64
  <ui5-radiobutton
64
65
  ?disabled="{{isInactive}}"
66
+ accessible-name="{{_accInfo.ariaLabelRadioButton}}"
65
67
  tabindex="-1"
66
68
  id="{{_id}}-singleSelectionElement"
67
69
  class="ui5-li-singlesel-radiobtn"
package/src/ListItem.js CHANGED
@@ -8,7 +8,13 @@ import ListItemBase from "./ListItemBase.js";
8
8
  import RadioButton from "./RadioButton.js";
9
9
  import CheckBox from "./CheckBox.js";
10
10
  import Button from "./Button.js";
11
- import { DELETE, ARIA_LABEL_LIST_ITEM_CHECKBOX } from "./generated/i18n/i18n-defaults.js";
11
+ import {
12
+ DELETE,
13
+ ARIA_LABEL_LIST_ITEM_CHECKBOX,
14
+ ARIA_LABEL_LIST_ITEM_RADIO_BUTTON,
15
+ LIST_ITEM_SELECTED,
16
+ LIST_ITEM_NOT_SELECTED,
17
+ } from "./generated/i18n/i18n-defaults.js";
12
18
 
13
19
  // Styles
14
20
  import styles from "./generated/themes/ListItem.css.js";
@@ -72,13 +78,13 @@ const metadata = {
72
78
  *
73
79
  * @private
74
80
  * @type {String}
75
- * @defaultvalue "option"
81
+ * @defaultvalue "listitem"
76
82
  * @since 1.0.0-rc.9
77
83
  *
78
84
  */
79
85
  role: {
80
86
  type: String,
81
- defaultValue: "option",
87
+ defaultValue: "listitem",
82
88
  },
83
89
 
84
90
  _mode: {
@@ -312,6 +318,20 @@ class ListItem extends ListItemBase {
312
318
  return undefined;
313
319
  }
314
320
 
321
+ get ariaSelectedText() {
322
+ let ariaSelectedText;
323
+
324
+ // Selected state needs to be supported separately since now the role mapping is list -> listitem[]
325
+ // to avoid the issue of nesting interactive elements, ex. (option -> radio/checkbox);
326
+ // The text is added to aria-describedby because as part of the aria-labelledby
327
+ // the whole content of the item is readout when the aria-labelledby value is changed.
328
+ if (this.ariaSelected !== undefined) {
329
+ ariaSelectedText = this.ariaSelected ? this.i18nBundle.getText(LIST_ITEM_SELECTED) : this.i18nBundle.getText(LIST_ITEM_NOT_SELECTED);
330
+ }
331
+
332
+ return ariaSelectedText;
333
+ }
334
+
315
335
  get deleteText() {
316
336
  return this.i18nBundle.getText(DELETE);
317
337
  }
@@ -322,7 +342,8 @@ class ListItem extends ListItemBase {
322
342
  ariaExpanded: undefined,
323
343
  ariaLevel: undefined,
324
344
  ariaLabel: this.i18nBundle.getText(ARIA_LABEL_LIST_ITEM_CHECKBOX),
325
- listItemAriaLabel: undefined,
345
+ ariaLabelRadioButton: this.i18nBundle.getText(ARIA_LABEL_LIST_ITEM_RADIO_BUTTON),
346
+ ariaSelectedText: this.ariaSelectedText,
326
347
  };
327
348
  }
328
349
 
package/src/Panel.js CHANGED
@@ -95,7 +95,19 @@ const metadata = {
95
95
  },
96
96
 
97
97
  /**
98
- * Sets the accessible aria role of the <code>ui5-panel</code>.
98
+ * Indicates whether the transition between the expanded and the collapsed state of the component is animated. By default the animation is enabled.
99
+ *
100
+ * @type {boolean}
101
+ * @defaultvalue false
102
+ * @public
103
+ * @since 1.0.0-rc.16
104
+ */
105
+ noAnimation: {
106
+ type: Boolean,
107
+ },
108
+
109
+ /**
110
+ * Sets the accessible aria role of the component.
99
111
  * Depending on the usage, you can change the role from the default <code>Form</code>
100
112
  * to <code>Region</code> or <code>Complementary</code>.
101
113
  *
@@ -282,8 +294,8 @@ class Panel extends UI5Element {
282
294
  return true;
283
295
  }
284
296
 
285
- shouldAnimate() {
286
- return getAnimationMode() !== AnimationMode.None;
297
+ shouldNotAnimate() {
298
+ return this.noAnimation || getAnimationMode() === AnimationMode.None;
287
299
  }
288
300
 
289
301
  _headerClick(event) {
@@ -332,7 +344,7 @@ class Panel extends UI5Element {
332
344
 
333
345
  this.collapsed = !this.collapsed;
334
346
 
335
- if (!this.shouldAnimate()) {
347
+ if (this.shouldNotAnimate()) {
336
348
  this.fireEvent("toggle");
337
349
  return;
338
350
  }
@@ -368,7 +380,7 @@ class Panel extends UI5Element {
368
380
  get classes() {
369
381
  return {
370
382
  headerBtn: {
371
- "ui5-panel-header-button-animated": this.shouldAnimate(),
383
+ "ui5-panel-header-button-animated": !this.shouldNotAnimate(),
372
384
  },
373
385
  };
374
386
  }
package/src/Popup.js CHANGED
@@ -9,7 +9,7 @@ import { isTabPrevious } from "@ui5/webcomponents-base/dist/Keys.js";
9
9
  import { getNextZIndex, getFocusedElement, isFocusedElementWithinNode } from "@ui5/webcomponents-base/dist/util/PopupUtils.js";
10
10
  import PopupTemplate from "./generated/templates/PopupTemplate.lit.js";
11
11
  import PopupBlockLayer from "./generated/templates/PopupBlockLayerTemplate.lit.js";
12
- import { getOpenedPopups, addOpenedPopup, removeOpenedPopup } from "./popup-utils/OpenedPopupsRegistry.js";
12
+ import { addOpenedPopup, removeOpenedPopup } from "./popup-utils/OpenedPopupsRegistry.js";
13
13
 
14
14
  // Styles
15
15
  import styles from "./generated/themes/Popup.css.js";
@@ -150,6 +150,8 @@ const createBlockingStyle = () => {
150
150
 
151
151
  createBlockingStyle();
152
152
 
153
+ let bodyScrollingBlockers = 0;
154
+
153
155
  /**
154
156
  * @class
155
157
  * <h3 class="comment-api-title">Overview</h3>
@@ -237,6 +239,12 @@ class Popup extends UI5Element {
237
239
  * @protected
238
240
  */
239
241
  static blockBodyScrolling() {
242
+ bodyScrollingBlockers++;
243
+
244
+ if (bodyScrollingBlockers !== 1) {
245
+ return;
246
+ }
247
+
240
248
  if (window.pageYOffset > 0) {
241
249
  document.body.style.top = `-${window.pageYOffset}px`;
242
250
  }
@@ -248,6 +256,12 @@ class Popup extends UI5Element {
248
256
  * @protected
249
257
  */
250
258
  static unblockBodyScrolling() {
259
+ bodyScrollingBlockers--;
260
+
261
+ if (bodyScrollingBlockers !== 0) {
262
+ return;
263
+ }
264
+
251
265
  document.body.classList.remove("ui5-popup-scroll-blocker");
252
266
  window.scrollTo(0, -parseFloat(document.body.style.top));
253
267
  document.body.style.top = "";
@@ -422,12 +436,9 @@ class Popup extends UI5Element {
422
436
  return;
423
437
  }
424
438
 
425
- const openedPopups = getOpenedPopups();
426
439
  if (this.isModal) {
427
440
  this._blockLayerHidden = true;
428
- if (openedPopups.length === 1) {
429
- Popup.unblockBodyScrolling();
430
- }
441
+ Popup.unblockBodyScrolling();
431
442
  }
432
443
 
433
444
  this.hide();
@@ -3,7 +3,7 @@
3
3
  aria-checked="{{selected}}"
4
4
  aria-readonly="{{ariaReadonly}}"
5
5
  aria-disabled="{{ariaDisabled}}"
6
- aria-labelledby="{{ariaLabelledBy}}"
6
+ aria-label="{{ariaLabelText}}"
7
7
  aria-describedby="{{ariaDescribedBy}}"
8
8
  tabindex="{{tabIndex}}"
9
9
  dir="{{effectiveDir}}"
@@ -162,6 +162,19 @@ const metadata = {
162
162
  type: Boolean,
163
163
  },
164
164
 
165
+ /**
166
+ * Defines the text alternative of the component.
167
+ * If not provided a default text alternative will be set, if present.
168
+ *
169
+ * @type {string}
170
+ * @defaultvalue ""
171
+ * @private
172
+ * @since 1.0.0-rc.16
173
+ */
174
+ accessibleName: {
175
+ type: String,
176
+ },
177
+
165
178
  _tabIndex: {
166
179
  type: String,
167
180
  defaultValue: "-1",
@@ -383,8 +396,8 @@ class RadioButton extends UI5Element {
383
396
  return this.disabled ? "true" : undefined;
384
397
  }
385
398
 
386
- get ariaLabelledBy() {
387
- return this.text ? `${this._id}-label` : undefined;
399
+ get ariaLabelText() {
400
+ return [this.text, this.accessibleName].filter(Boolean).join(" ");
388
401
  }
389
402
 
390
403
  get ariaDescribedBy() {
@@ -116,9 +116,10 @@ class ResponsivePopover extends Popover {
116
116
  /**
117
117
  * Opens popover on desktop and dialog on mobile.
118
118
  * @param {HTMLElement} opener the element that the popover is opened by
119
+ * @param {boolean} preventInitialFocus prevents applying the focus inside the popup
119
120
  * @public
120
121
  */
121
- open(opener) {
122
+ open(opener, preventInitialFocus = false) {
122
123
  this.style.display = this._isPhone ? "contents" : "";
123
124
 
124
125
  if (this.isOpen() || (this._dialog && this._dialog.isOpen())) {
@@ -131,7 +132,7 @@ class ResponsivePopover extends Popover {
131
132
  this._minWidth = Math.max(POPOVER_MIN_WIDTH, opener.getBoundingClientRect().width);
132
133
  }
133
134
 
134
- this.openBy(opener);
135
+ this.openBy(opener, preventInitialFocus);
135
136
  } else {
136
137
  this.style.zIndex = getNextZIndex();
137
138
  this._dialog.open();