diff --git a/packages/main/src/Calendar.ts b/packages/main/src/Calendar.ts index a362831dd106..7028f9313a37 100644 --- a/packages/main/src/Calendar.ts +++ b/packages/main/src/Calendar.ts @@ -78,6 +78,7 @@ type CalendarSelectionChangeEventDetail = { type SpecialCalendarDateT = { specialDateTimestamp: number; type: `${CalendarLegendItemType}`; + tooltip?: string; }; /** @@ -274,7 +275,7 @@ class Calendar extends CalendarPart { * @public * @since 1.23.0 */ - @slot({ type: HTMLElement }) + @slot({ type: HTMLElement, invalidateOnChildChange: true }) calendarLegend!: Array; /** @@ -409,6 +410,11 @@ class Calendar extends CalendarPart { return isTypeMatch && dateValue && this._isValidCalendarDate(dateValue); }); + validSpecialDates.forEach(date => { + const refLegendItem = this.calendarLegend.length ? this.calendarLegend[0].items.find(item => item.type === date.type) : undefined; + date._tooltip = refLegendItem?.text || ""; + }); + const uniqueDates = new Set(); const uniqueSpecialDates: Array = []; @@ -420,7 +426,8 @@ class Calendar extends CalendarPart { uniqueDates.add(timestamp); const specialDateTimestamp = CalendarDateComponent.fromLocalJSDate(dateFromValue).valueOf() / 1000; const type = date.type; - uniqueSpecialDates.push({ specialDateTimestamp, type }); + const tooltip = date._tooltip; + uniqueSpecialDates.push({ specialDateTimestamp, type, tooltip }); } }); diff --git a/packages/main/src/DayPicker.ts b/packages/main/src/DayPicker.ts index ac3f4bca945d..196cf8b12f42 100644 --- a/packages/main/src/DayPicker.ts +++ b/packages/main/src/DayPicker.ts @@ -72,6 +72,7 @@ type Day = { selected: boolean, _isSecondaryCalendarType: boolean, classes: string, + tooltip?: string, ariaLabel: string, ariaSelected: boolean, ariaDisabled: boolean | undefined, @@ -238,6 +239,8 @@ class DayPicker extends CalendarPart implements ICalendarPicker { const specialCalendarDate = specialCalendarDates.find(specialDate => specialDate.specialDateTimestamp === timestamp); const specialDayType = specialCalendarDate ? specialCalendarDate.type : ""; + const specialDayTooltip = specialCalendarDate ? specialCalendarDate.tooltip : ""; + const unnamedCalendarTypeLabel = specialDayTooltip && !this._isDefaultCalendarLegendType(specialDayType) ? specialDayTooltip : ""; const isFocused = tempDate.getMonth() === calendarDate.getMonth() && tempDate.getDate() === calendarDate.getDate(); const isSelected = this._isDaySelected(timestamp); @@ -248,16 +251,20 @@ class DayPicker extends CalendarPart implements ICalendarPicker { const isToday = tempDate.isSame(todayDate); const isFirstDayOfWeek = tempDate.getDay() === firstDayOfWeek; - const nonWorkingAriaLabel = isWeekend ? `${nonWorkingDayLabel} ` : ""; + const nonWorkingAriaLabel = (isWeekend || specialDayType === "NonWorking") && specialDayType !== "Working" + ? `${nonWorkingDayLabel} ` + : ""; const todayAriaLabel = isToday ? `${todayLabel} ` : ""; const tempSecondDateNumber = tempSecondDate ? tempSecondDate.getDate() : ""; const tempSecondYearNumber = tempSecondDate ? tempSecondDate.getYear() : ""; const secondaryMonthsNamesString = secondaryMonthsNames.length > 0 ? secondaryMonthsNames[tempSecondDate!.getMonth()] : ""; + const tooltip = `${todayAriaLabel}${nonWorkingAriaLabel}${unnamedCalendarTypeLabel}`; + const ariaLabel = this.hasSecondaryCalendarType - ? `${todayAriaLabel}${nonWorkingAriaLabel}${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}; ${secondaryMonthsNamesString} ${tempSecondDateNumber}, ${tempSecondYearNumber}` - : `${todayAriaLabel}${nonWorkingAriaLabel}${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}`; + ? `${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()}; ${secondaryMonthsNamesString} ${tempSecondDateNumber}, ${tempSecondYearNumber} ${tooltip} ` + : `${monthsNames[tempDate.getMonth()]} ${tempDate.getDate()}, ${tempDate.getYear()} ${tooltip}`; const day: Day = { timestamp: timestamp.toString(), @@ -268,6 +275,7 @@ class DayPicker extends CalendarPart implements ICalendarPicker { secondDay: this.hasSecondaryCalendarType ? (tempSecondDate as CalendarDate).getDate() : undefined, _isSecondaryCalendarType: this.hasSecondaryCalendarType, classes: `ui5-dp-item ui5-dp-wday${dayOfTheWeek}`, + tooltip, ariaLabel, ariaSelected: isSelected || isSelectedBetween, ariaDisabled: isDisabled || isOtherMonth, @@ -784,6 +792,10 @@ class DayPicker extends CalendarPart implements ICalendarPicker { return (target.className.indexOf("ui5-dp-item") > -1) || (targetParent && targetParent.classList && targetParent.classList.contains("ui5-dp-item")); } + _isDefaultCalendarLegendType(type: string): boolean { + return ["NonWorking", "Working", "Today", "Selected", "None"].includes(type); + } + _getSecondaryDay(tempDate: CalendarDate): CalendarDate { return new CalendarDate(tempDate, this.secondaryCalendarType); } diff --git a/packages/main/src/DayPickerTemplate.tsx b/packages/main/src/DayPickerTemplate.tsx index ade2d29cee59..6e9735d12493 100644 --- a/packages/main/src/DayPickerTemplate.tsx +++ b/packages/main/src/DayPickerTemplate.tsx @@ -42,6 +42,7 @@ export default function DayPickerTemplate(this: DayPicker) { data-sap-focus-ref={day.focusRef ? "true" : undefined} data-sap-timestamp={day.timestamp} role="gridcell" + title={day.tooltip} aria-selected={day.ariaSelected} aria-label={day.ariaLabel} aria-disabled={day.ariaDisabled} diff --git a/packages/main/src/SpecialCalendarDate.ts b/packages/main/src/SpecialCalendarDate.ts index 9aa53478b65c..23450a158f2b 100644 --- a/packages/main/src/SpecialCalendarDate.ts +++ b/packages/main/src/SpecialCalendarDate.ts @@ -33,6 +33,14 @@ class SpecialCalendarDate extends UI5Element { */ @property() type: `${CalendarLegendItemType}` = "None"; + + /** + * Defines a tooltip text for the special date. + * @default "" + * @private + */ + @property() + _tooltip = ""; } SpecialCalendarDate.define(); diff --git a/packages/main/src/themes/DayPicker.css b/packages/main/src/themes/DayPicker.css index eba1f0617ae7..794ab1b9c9e0 100644 --- a/packages/main/src/themes/DayPicker.css +++ b/packages/main/src/themes/DayPicker.css @@ -87,6 +87,7 @@ font-size: var(--sapFontSize); border: var(--_ui5_daypicker_item_border); border-radius: var(--_ui5_daypicker_item_border_radius); + cursor: pointer; } .ui5-dp-item:hover {