From fc16088603bec914909f374e80e3c398a2f8e8fa Mon Sep 17 00:00:00 2001 From: Stoyan Date: Fri, 15 May 2026 10:43:21 +0300 Subject: [PATCH 1/2] fix(ui5-calendar): set timestamp of daypicker on mousedown --- packages/main/src/DayPicker.ts | 14 ++++++++++++++ packages/main/src/DayPickerTemplate.tsx | 1 + 2 files changed, 15 insertions(+) diff --git a/packages/main/src/DayPicker.ts b/packages/main/src/DayPicker.ts index affaeaaca9a5..98b668c2b126 100644 --- a/packages/main/src/DayPicker.ts +++ b/packages/main/src/DayPicker.ts @@ -593,6 +593,20 @@ class DayPicker extends CalendarPart implements ICalendarPicker { this.selectedDates = this.selectedDates.filter(value => value !== timestamp); } + _onmousedown(e: MouseEvent) { + let target = e.target as HTMLElement; + + if (!target.hasAttribute("data-sap-timestamp")) { + target = target.parentNode as HTMLElement; + } + + if (!this._isDayPressed(target)) { + return; + } + + this._safelySetTimestamp(this._getTimestampFromDom(target)); + } + /** * Called when at least one day is selected and the user presses "Shift". * @param timestamp diff --git a/packages/main/src/DayPickerTemplate.tsx b/packages/main/src/DayPickerTemplate.tsx index 40be6e05d6ad..dcb22972dee1 100644 --- a/packages/main/src/DayPickerTemplate.tsx +++ b/packages/main/src/DayPickerTemplate.tsx @@ -13,6 +13,7 @@ export default function DayPickerTemplate(this: DayPicker) { }} onKeyDown={this._onkeydown} onKeyUp={this._onkeyup} + onMouseDown={this._onmousedown} onClick={this._onclick} onMouseOver={this._onmouseover} > From 0ca6f7e89558905b3bd30f5d434bc7cd178c1002 Mon Sep 17 00:00:00 2001 From: Stoyan Date: Thu, 21 May 2026 10:53:53 +0300 Subject: [PATCH 2/2] address discussion changes --- packages/main/cypress/specs/Calendar.cy.tsx | 30 +++++++++++++++++++++ packages/main/src/DayPicker.ts | 10 ++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/main/cypress/specs/Calendar.cy.tsx b/packages/main/cypress/specs/Calendar.cy.tsx index f53b10890dcb..9ed1429585ac 100644 --- a/packages/main/cypress/specs/Calendar.cy.tsx +++ b/packages/main/cypress/specs/Calendar.cy.tsx @@ -1760,6 +1760,36 @@ describe("Day Picker Tests", () => { expect(todayFromTimestamp.getFullYear()).to.equal(actualToday.getFullYear()); }); }); + + it("mousedown + arrow navigation + click keeps focus at navigated cell, selection on clicked cell", () => { + const date = new Date(Date.UTC(2000, 9, 10, 0, 0, 0)); + cy.mount(getDefaultCalendar(date)); + + const day15Timestamp = new Date(Date.UTC(2000, 9, 15, 0, 0, 0)).valueOf() / 1000; + const day12Timestamp = new Date(Date.UTC(2000, 9, 12, 0, 0, 0)).valueOf() / 1000; + + // mousedown on 15th — focus moves to 15th + cy.ui5CalendarGetDay("#calendar1", day15Timestamp.toString()) + .realMouseDown(); + + // press arrow left three times — focus moves to 12th + cy.realPress("ArrowLeft"); + cy.realPress("ArrowLeft"); + cy.realPress("ArrowLeft"); + + cy.ui5CalendarGetDay("#calendar1", day12Timestamp.toString()) + .should("have.focus"); + + // mouseup on 15th — selection goes to 15th, focus stays on 12th + cy.ui5CalendarGetDay("#calendar1", day15Timestamp.toString()) + .realMouseUp(); + + cy.ui5CalendarGetDay("#calendar1", day12Timestamp.toString()) + .should("have.focus"); + + cy.ui5CalendarGetDay("#calendar1", day15Timestamp.toString()) + .should("have.class", "ui5-dp-item--selected"); + }); }); describe("Calendar Global Configuration", () => { diff --git a/packages/main/src/DayPicker.ts b/packages/main/src/DayPicker.ts index 98b668c2b126..151eda7b607c 100644 --- a/packages/main/src/DayPicker.ts +++ b/packages/main/src/DayPicker.ts @@ -499,9 +499,10 @@ class DayPicker extends CalendarPart implements ICalendarPicker { * Selects/deselects a day. * @param e * @param isShift true if the user did Click+Shift or Enter+Shift (but not Space+Shift) + * @param setTimestamp whether to move focus (timestamp) to the selected day; false for mouse clicks where focus is independent * @private */ - _selectDate(e: Event, isShift: boolean) { + _selectDate(e: Event, isShift: boolean, setTimestamp = true) { let target = e.target as HTMLElement; if (!target.hasAttribute("data-sap-timestamp")) { @@ -514,7 +515,9 @@ class DayPicker extends CalendarPart implements ICalendarPicker { const timestamp = this._getTimestampFromDom(target); - this._safelySetTimestamp(timestamp); + if (setTimestamp) { + this._safelySetTimestamp(timestamp); + } this._updateSecondTimestamp(); this._updateSelectedDates(timestamp, isShift); @@ -605,6 +608,7 @@ class DayPicker extends CalendarPart implements ICalendarPicker { } this._safelySetTimestamp(this._getTimestampFromDom(target)); + this.fireDecoratorEvent("navigate", { timestamp: this.timestamp! }); } /** @@ -724,7 +728,7 @@ class DayPicker extends CalendarPart implements ICalendarPicker { * @private */ _onclick(e: MouseEvent) { - this._selectDate(e, e.shiftKey); + this._selectDate(e, e.shiftKey, false); } /**