Date and Time zoom support - #13964
Conversation
- DateComponentBase: _highZoom property, _isHighZoom(), zoom watch lifecycle - TimePicker: same zoom detection (standalone, no shared base) - DateHighZoomInputs: new internal component with Year/Month/Day selects, YearPicker dialog, validate(), syncStartDate/EndDate(), full public API - YearPicker: _showHeader, _rowSize, _pageSize properties; CalendarHeader CSS included for standalone use - DatePicker: _highZoom integration — DateHighZoomInputs replaces Calendar in popover content, OK/Cancel footer, input click handling at zoom
…r improvements - DatePicker: _hzOkEnabled (disabled until valid), _hzActiveCalType toggle, secondary calendar type icon button in header, _onHzFocusIn to open picker - DateHighZoomInputs: minDate/maxDate as ISO strings, _parseISO without TZ issues, _gregYear/Month/Day source-of-truth for calendar type conversion, _applyCalendarTypeToDisplay using Intl.DateTimeFormat, Intl-based month names - YearPicker: _rowSize, _pageSize, _showHeader properties; CalendarHeader CSS included; CSS item width driven by --_ui5_yp_item_width custom property
- TimePicker: showHeader includes _highZoom, _togglePicker syncs _highZoom, _handleInputClick opens picker at zoom, _onHzFocusIn handler, _onZoomChange reopens picker on resize - TimePickerTemplate: icon hidden at zoom, onFocusIn uses _onHzFocusIn - TimePickerPopoverTemplate: TimeSelectionInputs with _showLabels at zoom - TimeSelectionInputs: _showLabels property, Hz label getters, Label import - TimeSelectionInputsTemplate: labeled layout with Hours/Minutes/Seconds labels, separators between inputs - TimeSelectionInputs.css: --labeled flex-wrap layout, separator centering - i18n: TIMEPICKER_HZ_HOURS/MINUTES/SECONDS keys
At 200% zoom (viewport ≤ 320px), ui5-calendar renders a DatePicker input instead of the full calendar grid. Zoom watching is wired via super.onEnterDOM/onExitDOM (DateComponentBase infrastructure).
GDamyanov
left a comment
There was a problem hiding this comment.
Could we also write cypress tests for high zoom?
|
|
||
| DATEPICKER_RANGE_UNDERFLOW=Enter a date higher than the minimum value of {0}. | ||
|
|
||
| DATEPICKER_HZ_YEAR_LABEL=Year: |
There was a problem hiding this comment.
They will be removed before merging. They were added for testing purposes.
| width: 100%; | ||
| --_ui5_calendar_width: 100%; | ||
| --_ui5_calendar_height: auto; | ||
| } |
There was a problem hiding this comment.
overriding css variables here is not a good practise.
|
|
||
| onExitDOM() { | ||
| super.onExitDOM(); | ||
| ResizeHandler.deregister(document.body, this._handleResizeBound); |
There was a problem hiding this comment.
Same logic should be applied also for super.onExitDOM();
| value={this._hzDatePickerValue} | ||
| formatPattern={this._formatPattern} | ||
| primaryCalendarType={this.primaryCalendarType} | ||
| secondaryCalendarType={this.secondaryCalendarType} |
There was a problem hiding this comment.
We should use the private getters for calendarTypes which comes from DateComponentBase
| import slimArowRight from "@ui5/webcomponents-icons/dist/slim-arrow-right.js"; | ||
|
|
||
| export interface CalendarHeaderHost { | ||
| _previousButtonDisabled: boolean; |
There was a problem hiding this comment.
Could we extract this interface in other file since it is used in other places. Also it will be good to split all the properties into other interfaces
| } | ||
|
|
||
| _isHighZoom(): boolean { | ||
| return isHighZoom(); |
There was a problem hiding this comment.
Do we need this property since we have _highZoom
| function defaultContent(this: DatePicker) { | ||
| if (this._highZoom) { | ||
| const toISO = (cd: CalendarDateLocale) => | ||
| `${String(cd.getYear()).padStart(4, "0")}-${String(cd.getMonth() + 1).padStart(2, "0")}-${String(cd.getDate()).padStart(2, "0")}`; |
There was a problem hiding this comment.
toIso is duplicated, could we extract the logic?
- calendar standalone at high zoom renders a date picker whose value round-trips via ISO value format, defaulting to today when no date is selected. - feed the high-zoom year/month/day inputs from the picker's canonical focus timestamp so the input field and the dialog stay in sync (fixes year 0). - compare the incoming date by value, not reference, so re-renders don't clobber in-progress edits. - restore the calendar width/height overrides on the year picker so it collapses to its content instead of a fixed height; compress cells and suppress scroll. - make the year text non-interactive so clicks land on the selectable cell. - make the range inputs a bounded vertical scroll container.
- center the datetime picker time section on the narrow high-zoom screen and
drop the fixed min-width so it fits.
- add a top padding to the time picker and datetime time inputs to match the
date picker high-zoom inputs.
- shorten the minutes and seconds labels to abbreviations ("min.:", "sec.:")
so they no longer overflow.
|
I found few visual bugs while reviewing the PR:
|
|
startHighZoomWatch attaches two resize event listeners on window (one on window.visualViewport, one on window) per component instance. Every DatePicker, DateTimePicker, TimePicker etc. on the page adds its own pair of listeners, all watching the exact same thing — the global viewport width. Suggested rework: Convert HighZoomWatch.ts into a pub/sub singleton:
This way there is always exactly one pair of resize listeners on window, regardless of how many picker components are on the page. |
Align DateHighZoomInputs dialog padding with the standard PopupsCommon S-range value (1rem). Add overflow-x: hidden to prevent horizontal scrollbar caused by implicit overflow-x: auto from overflow-y: auto.
|
… calendars in high-zoom mode CalendarDate.getYear()/getMonth()/getDate() return calendar-system-specific values (e.g. Hijri year 1447), not Gregorian. When passed as ISO strings to DateHighZoomInputs, the bounds were treated as Gregorian, silently bypassing all min/max validation for non-Gregorian primaryCalendarType. Replace manual formatting with toUTCJSDate().toISOString().slice(0, 10) in DatePickerPopoverTemplate, DateRangePickerTemplate and DateTimePicker, matching the existing correct approach in Calendar.ts. Also guard onExitDOM in DateComponentBase to only call unsubscribeHighZoom when _shouldWatchZoom is true, avoiding spurious cleanup of unrelated observers.
…fter calendar type switch CalendarDate(year, month, day, calendarType) always treats year/month/day as Gregorian values regardless of calendarType, causing _displayToGregorian to return the raw Islamic year (e.g. 390) as a Gregorian year instead of the correct Gregorian equivalent (~1000 CE). Fix both _displayToGregorian and _getDaysInMonth by starting from a known valid Gregorian base date and using setYear/setMonth (which correctly operate in the target calendar type) instead of the constructor.
- HighZoomWatch.ts: fix object-curly-newline lint error in named export - DateRangePicker.ts: remove invalid @OverRide JSDoc tag (TS override keyword remains) - DateTimePicker.ts: remove invalid @OverRide JSDoc tags (TS override keyword remains) - UserSettingsDialog.css (test/sample): fix align-item → align-items typo
…standalone Calendar - DateHighZoomInputs: add UI5Date fallback in syncStartDate/syncEndDate so fields are pre-populated with today when dateValue is null; use _startDateInitialized/_endDateInitialized flags to trigger initial sync regardless of sameDate check - DateHighZoomInputsTemplate: add accessibleName on month/day selects; add headerText on year-picker dialog - SelectPopoverTemplate: use _effectiveListAccessibleName for phone header (was _headerTitleText) - DateHighZoomInputs.css: fix year-picker dialog layout (column, stretch) and remove top padding so YearRangePicker aligns correctly - TimeSelectionInputs.css: fix separator vertical alignment in labeled mode using input-height CSS variable - Test page: add Multiple and Range standalone Calendar examples to verify new zoom UI is skipped for non-Single selectionMode; add selectionMode toggle buttons on cal-std for runtime reactivity check - AGENTS.md: document UI5Date.getInstance() convention in quick-reference table
Sample sync reminderHTML sample changed but React sample (
Please keep both samples in sync, or ignore if the change does not apply to both. |
|
🚀 Deployed on https://pr-13964--ui5-webcomponents-preview.netlify.app |
…nputs - Calendar: serialize _hzDatePickerValue, _hzMinISO, _hzMaxISO using DateFormat with the active calendarType instead of .toISOString() (Gregorian ISO), so the embedded DatePicker receives values in the correct calendar's year numbering (e.g. Islamic 1445, not 2024) - Calendar: replace getISOFormat() in _onHzDatePickerChange with a fresh DateFormat per call, avoiding the stale _isoFormatInstance cached before a primaryCalendarType change - DateHighZoomInputs: convert display year via CalendarDate in _onYearInput and _yearPickerSelectedTimestamp so non-Gregorian years (e.g. Islamic 1445) navigate the year picker correctly - DateHighZoomInputs/DateRangePicker: use UI5Date.getInstance() instead of new Date() in getDateObject() and _onHzOk to respect the SAPUI5 simulated timezone and avoid off-by-one-day errors
No description provided.