Skip to content

Date and Time zoom support - #13964

Draft
Todor-ads wants to merge 16 commits into
mainfrom
date_time_zoom
Draft

Date and Time zoom support#13964
Todor-ads wants to merge 16 commits into
mainfrom
date_time_zoom

Conversation

@Todor-ads

Copy link
Copy Markdown
Contributor

No description provided.

- 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 GDamyanov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also write cypress tests for high zoom?

Comment thread packages/main/src/types/DateHighZoomInputsTypes.ts
Comment thread packages/main/src/DatePicker.ts Outdated

DATEPICKER_RANGE_UNDERFLOW=Enter a date higher than the minimum value of {0}.

DATEPICKER_HZ_YEAR_LABEL=Year:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They will be removed before merging. They were added for testing purposes.

Comment thread packages/main/src/themes/DateHighZoomInputs.css Outdated
width: 100%;
--_ui5_calendar_width: 100%;
--_ui5_calendar_height: auto;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overriding css variables here is not a good practise.


onExitDOM() {
super.onExitDOM();
ResizeHandler.deregister(document.body, this._handleResizeBound);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same logic should be applied also for super.onExitDOM();

value={this._hzDatePickerValue}
formatPattern={this._formatPattern}
primaryCalendarType={this.primaryCalendarType}
secondaryCalendarType={this.secondaryCalendarType}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread packages/main/src/DateComponentBase.ts Outdated
}

_isHighZoom(): boolean {
return isHighZoom();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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")}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@nnaydenow

Copy link
Copy Markdown
Contributor

I found few visual bugs while reviewing the PR:

  • Dialog is jumping (left / right) when zoom in enabled
  • The icon disappear on some date / time components when popover is opened

@nnaydenow

Copy link
Copy Markdown
Contributor

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:

  • Define an interface (e.g. HighZoomObserver) that components implement — a single _highZoom: boolean property. The interface should document that implementors must declare this property with the @property({ type: Boolean, noAttribute: true }) decorator so that assigning it triggers component invalidation and re-render.
  • subscribeHighZoom(element: HighZoomObserver) / unsubscribeHighZoom(element: HighZoomObserver) — add/remove a subscriber; the underlying window listeners are created on first subscribe and torn down on last unsubscribe; the singleton sets observer._highZoom directly when the state flips
  • Components call subscribeHighZoom(this) in onEnterDOM and unsubscribeHighZoom(this) in onExitDOM

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.
@Todor-ads

Copy link
Copy Markdown
Contributor Author

I found few visual bugs while reviewing the PR:

  • Dialog is jumping (left / right) when zoom in enabled
  • The icon disappear on some date / time components when popover is opened
  1. This only occurs on a real device and the issue is in the behavior of the Dialog.
  2. The ValueHelp icon should not be displayed when zoom is enabled. If this is the comment here - this is the expected behavior.

… 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
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Sample sync reminder

HTML sample changed but React sample (sample.tsx) not updated:

  • fiori/UserSettingsDialog/SaveMode

Please keep both samples in sync, or ignore if the change does not apply to both.

@sap-ui5-webcomponents-release

Copy link
Copy Markdown

…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants