Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui5-calendar): add tooltips to special dates #10335

Merged
merged 10 commits into from
Jan 31, 2025
11 changes: 9 additions & 2 deletions packages/main/src/Calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type CalendarSelectionChangeEventDetail = {
type SpecialCalendarDateT = {
specialDateTimestamp: number;
type: `${CalendarLegendItemType}`;
tooltip?: string;
};

/**
Expand Down Expand Up @@ -274,7 +275,7 @@ class Calendar extends CalendarPart {
* @public
* @since 1.23.0
*/
@slot({ type: HTMLElement })
@slot({ type: HTMLElement, invalidateOnChildChange: true })
calendarLegend!: Array<CalendarLegend>;

/**
Expand Down Expand Up @@ -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<SpecialCalendarDateT> = [];

Expand All @@ -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 });
}
});

Expand Down
18 changes: 15 additions & 3 deletions packages/main/src/DayPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type Day = {
selected: boolean,
_isSecondaryCalendarType: boolean,
classes: string,
tooltip?: string,
ariaLabel: string,
ariaSelected: boolean,
ariaDisabled: boolean | undefined,
Expand Down Expand Up @@ -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);
Expand All @@ -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(),
Expand All @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/DayPickerTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
8 changes: 8 additions & 0 deletions packages/main/src/SpecialCalendarDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/themes/DayPicker.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down