Skip to content

feat: date-picker - #332

Open
Olaf (olaf-k) wants to merge 17 commits into
mainfrom
olaf/feat/datepicker
Open

feat: date-picker#332
Olaf (olaf-k) wants to merge 17 commits into
mainfrom
olaf/feat/datepicker

Conversation

@olaf-k

@olaf-k Olaf (olaf-k) commented Aug 3, 2026

Copy link
Copy Markdown
Member

QUI-related changes

these commits are independent of the feature and reviewable on their own:

  1. fix(machine): only clear an element id when it is still the registered one: fixes a lost id registration when an element replaces another (happens when changing the datepicker's selection mode at runtime).

  2. fix(machine): keep the api context view instead of rebuilding it: Angular's *xContext directive recreated its content on every state change, causing lost focuses and badly positioned popups.

  3. feat(tag): allow customizing the dismiss button label: adds a dismissLabel prop to replace the hardcoded aria-label="Dismiss".

  4. feat(select): label remove buttons with the selected item text: applies the above-mentioned fix to the multiple Select component (which works the same way as the multiple datepicker).

  5. fix(forms): flush the pending value when a child part reports blur: Angular composite components that have a focusable child didn't handle updateOn: 'blur' properly: this fix exposes the CVA onTouched to them so they can. note that only the datepicker is wired up and other components will be updated in an upcoming PR.

  6. fix(docs-plugin): index component types for lookup without emitting rows: to prevent the prop indexer from creating "ghost anchor ids" in doc pages (explains the progress-ring page edits).

  7. fix(component-explorer): skip highlighting parts that have no visible box: as it says on the tin.

  8. fix: proper positioning defaults in components and JSDoc: as it says on the tin.

  9. fix(angular-core): drop accessSignal falsy guard: was unnecessary and broke TS6 support.

+ two other minor updates that didn't require their own commits: 2 new exports in common/dom and a type-widening for compact.

The PR takes the deprecation inline-icon-button into account.

Compared to zag

  • range datepicker supports incomplete ranges (missing end/start dates).
  • multiple datepicker actually behaves as a form element and uses dismissable tags (like Select).
  • action buttons (OK/Cancel) and associated rollback logic.
  • parts added (hint and error text, presets, headline, a close button for the month/year views) and unneeded parts removed (week numbers, month and year dropdowns).
  • various bug fixes, some of them already pushed upstream.

@olaf-k
Olaf (olaf-k) force-pushed the olaf/feat/datepicker branch 4 times, most recently from 49a8db9 to 623f97b Compare August 5, 2026 16:27
@olaf-k
Olaf (olaf-k) force-pushed the olaf/feat/datepicker branch 2 times, most recently from 5888e6d to 389b795 Compare August 11, 2026 14:59
@olaf-k
Olaf (olaf-k) marked this pull request as ready for review August 11, 2026 15:12
@olaf-k Olaf (olaf-k) changed the title [WIP] feat: date-picker feat: date-picker Aug 11, 2026
Comment thread packages/common/utils/src/date-utils/pagination.ts
Comment thread packages/common/utils/src/date-utils/pagination.ts
Comment thread packages/common/utils/src/date-utils/pagination.ts
export function compact<T extends Record<string, unknown> | undefined>(
obj: T,
): T {
export function compact<T extends object | undefined>(obj: T): T {

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.

oh, why extend object here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

to avoid resorting to any like in toast for instance. interfaces don't have an index signature and compact wasn't using them anyway, so object does the job.
or, better phrased by Claude: "interfaces are open to declaration merging so TS won't infer an index signature for them (unlike type aliases)".

@R-Bower

Copy link
Copy Markdown
Contributor

double-check that keyboard events align with the documented aria datepicker patterns:

@R-Bower

Copy link
Copy Markdown
Contributor

Not sure if this is intentional, but when I press Enter on the selected date in this example, it is unselected when I press Escape.

http://re-qdswc-runner:3000/components/date-picker#custom-trigger

@olaf-k

Copy link
Copy Markdown
Member Author

Not sure if this is intentional, but when I press Enter on the selected date in this example, it is unselected when I press Escape.

http://re-qdswc-runner:3000/components/date-picker#custom-trigger

intentional yes, you'll get the same behavior wherever action buttons are used: you need to commit your choices with OK otherwise the component will revert to the its previous value (none in your case).

@R-Bower

Copy link
Copy Markdown
Contributor

May need to adjust this jsdoc:
image

Comment thread packages/common/core/src/date-picker/date-picker.types.ts Outdated
@olaf-k
Olaf (olaf-k) force-pushed the olaf/feat/datepicker branch 3 times, most recently from c385590 to 0d983ad Compare August 12, 2026 10:43
@olaf-k

Copy link
Copy Markdown
Member Author

May need to adjust this jsdoc

agree it could be clearer. changed it to:

  /**
   * Pass this to support non-Gregorian calendars (Persian, Buddhist, Islamic,
   * etc.), which keeps every calendar out of the bundle unless you opt in. The
   * picker calls it with the calendar identifier resolved from `locale`.
   *
   * @example
   * ```ts
   * import {createCalendar} from "@internationalized/date"
   *
   * const props = {createCalendar, locale: "fa-IR"}
   * ```
   */

@olaf-k

Olaf (olaf-k) commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

double-check that keyboard events align with the documented aria datepicker patterns:

there are interesting things to borrow from these examples (kbd nav & aria attributes) but some of them conflict with the current behavior (inherited from zag). the W3C examples also don't have an inline variant, range or multiple selection modes. so I'll see what we can keep from them where it makes sense. might take a bit of time.

edit: done. the two commits feat(date-picker): focus trap and feat(date-picker): improve screen reader announcements add focus trap to the popup calendar as well as various Aria enhancements.

@olaf-k
Olaf (olaf-k) force-pushed the olaf/feat/datepicker branch 3 times, most recently from 0179db0 to 527f634 Compare August 20, 2026 14:09
…d one

Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Comment thread packages/common/qds-core/src/date-picker/date-picker.classes.ts Outdated
Comment thread packages/common/qds-core/src/date-picker/qds-date-picker.css Outdated
Comment on lines +42 to +53
/**
* A getter, not a snapshot: tracking the read inside the view lets Angular
* update on API change without destroying and rebuilding the DOM.
*/
const viewContext = {
get $implicit() {
return contextService.context()
},
get [contextName]() {
return contextService.context()
},
}

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.

very neat

Comment on lines +85 to +94
/**
* A replacement element registers before the outgoing element's cleanup
* runs. Clearing unconditionally would discard the newer registration.
*/
const clearIfCurrentId = (id: unknown) => () => {
if (configIds?.[key]?.get?.() !== id) {
return
}
configIds?.[key].set?.(undefined)
}

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.

nice

Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
… box

Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
Signed-off-by: Olaf Kappes <okappes@qti.qualcomm.com>
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