Skip to content

feat(time-picker): apply relative options on click - #682

Merged
djcouto merged 2 commits into
devfrom
dc/time-picker
Sep 10, 2026
Merged

djcouto merged 2 commits into
devfrom
dc/time-picker

Conversation

@djcouto

@djcouto djcouto commented Sep 8, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

kv-time-picker required a second press on Apply to commit a selection picked from the dropdown list. That confirmation earns its keep in the calendar, where a half-picked range is not yet a valid selection, but it is pure friction in the plain option list where the click is itself the decision.

Apply and Cancel now render only while a calendar is on screen — showCalendar on, or Custom Interval picked. In the option list a click commits and closes, matching kv-single-select-dropdown and every other dropdown in the library.

Note

Behaviour change, not an API change. timeRangeChange keeps its name and its ITimePickerTime payload, and still fires once per selection — only earlier, on the click instead of on Apply. Consumers need no code change, so this is a minor, not a major.

What does change downstream is anything driving the old two-step flow: automation or e2e tests that press Apply in the option list will no longer find the button, and cancelClicked is no longer reachable from that view (dismissal still reports dropdownStateChange(false)). Nothing in this repo consumes kv-time-picker internally.

Changes

  • feat(time-picker) — Apply/Cancel visibility is derived from the view rather than always rendered: isCalendarVisible() is timePickerView !== RelativeTimePicker, which covers exactly the two calendar cases (showCalendar → FullView, Custom Interval → AbsoluteTimePicker). No new prop.
  • feat(time-picker) — onClickApply is split into emitTimeRangeChange (publish) and commitTimeState (publish + dismiss), so the new click path reuses the existing Apply behaviour instead of duplicating it. The Apply payload is unchanged.
  • feat(relative-time-picker) — new relativeTimeOptionClicked event, emitted only from the click handler. This is the crux: selectedRelativeTimeChange is also re-emitted from the component's 10-second setInterval as a "now"-relative range moves (hasRangeChanged compares with seconds zeroed), so committing from it would have made an open panel commit and close itself roughly once a minute. The new event mirrors the existing customizeIntervalClicked intent-event pattern, and fires even when the clicked option is already selected so a re-click still confirms.
  • feat(time-picker) — a timezone change in the option list commits without closing the panel, since no Apply is left to confirm it. The range is re-anchored to the new timezone by reusing getRelativeTimeOption + buildOptionRange/buildTimestampRange, so a boundary-based option like Today shifts correctly.
  • fix(time-picker) — hiding the calendar now discards a pending range via undoLastChanges, which would otherwise be stranded with no Apply to commit it and would leave calendarViewLocked set, disabling the toggle.
  • fix(time-picker) — the footer is dropped entirely when it would hold neither the toggle nor the actions (displayCalendarToggle={false} in the option list), instead of leaving an empty bordered, padded bar.
  • test(time-picker) — 14 new specs, including a regression guard asserting that onSelectedRelativeTimeChange alone (the periodic-refresh path) emits nothing and leaves the panel open.

packages/ui-components/src/components/relative-time-picker/readme.md is regenerated by the build. No enum was added, so packages/react-ui-components/src/ui-components.ts needs no change, and the React binding picks the event up through the generated JSX types.

Test Plan

  • pnpm build:packages — exit 0, no errors
  • pnpm test — 421 specs pass, 123 snapshots pass
  • pnpm lint — clean
  • Manual verification in Storybook (Chromium, no console errors)

Manual steps — pnpm storybook, then Time Picker → Time Picker, watching the Actions panel:

  1. DefaultState — the footer shows only Show Calendar, no Apply/Cancel. Click Last 7 days: exactly one timeRangeChange (key: last-7-d), then dropdownStateChange(false), panel closed, input reads "Last 7 days". Re-open and click the already selected option — it still commits and closes.
  2. Leave the panel open for ~2 minutes without touching it. It must not emit or close itself. The periodic refresh is observably alive during this (the Today row's description advances with the clock), which is exactly the regression the new intent event prevents.
  3. Toggle Show Calendar on — Apply/Cancel appear and option clicks stop auto-committing (Apply becomes enabled); Apply still commits and closes. Toggle it back off — the buttons disappear and the toggle stays enabled.
  4. Click Custom Interval (calendar off) — the calendar slides in with Cancel and a correctly-disabled Apply, and no toggle. Back returns to the option list with the buttons gone.
  5. Change the timezone in the option list — timeRangeChange fires and the panel stays open. Switching between two zones on Today shows the range re-anchor (e.g. Pacific/Honolulu → 2026-09-08T10:00Z, Europe/Lisbon → 2026-09-07T23:00Z).
  6. FutureDurations (displayCalendarToggle: false, displayTimezoneDropdown: false) — no footer bar at all; clicking a duration commits and closes.

Run the suite with pnpm test rather than a bare stencil test: the package script sets TZ=UTC, without which 9 pre-existing timezone-sensitive specs in date.spec / relative-time.spec fail independently of this change.

Copilot AI lite review requested due to automatic review settings September 8, 2026 15:10
@djcouto
djcouto requested a review from a team as a code owner September 8, 2026 15:10
@djcouto djcouto self-assigned this Sep 8, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-08T15:16:18.289672Z 3ff041f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Picking from the dropdown list required a second press on Apply. That
confirmation earns its keep in the calendar, where a half-picked range is
not yet a valid selection, but it is pure friction in the option list where
the click is itself the decision.

Apply and Cancel now render only while a calendar is on screen — `showCalendar`
on, or "Custom Interval" picked. In the plain option list a click commits and
closes, matching `kv-single-select-dropdown` and every other dropdown here. The
footer is dropped entirely when it would hold neither the toggle nor the
actions, instead of leaving an empty bordered bar.

The commit is driven by a new `relativeTimeOptionClicked` event rather than
`selectedRelativeTimeChange`, which `kv-relative-time-picker` also re-emits from
its 10s refresh as a "now"-relative range moves — committing from that would
close an open panel roughly once a minute. It mirrors the existing
`customizeIntervalClicked` intent event, and fires even when the clicked option
is already selected so a re-click still confirms.

A timezone change in the option list commits without closing, since no Apply is
left to confirm it, and re-anchors the range to the new timezone. Hiding the
calendar now also discards a pending range, which would otherwise be stranded
with no way to apply it.

No API change: `timeRangeChange` keeps its name and `ITimePickerTime` payload,
and still fires once per selection — only earlier, on the click instead of on
Apply. Consumers need no code change. What does change downstream is anything
driving the old two-step flow: automation or e2e tests that press Apply in the
option list, and `cancelClicked`, which is no longer reachable from that view
(dismissal still reports `dropdownStateChange(false)`).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

A newly added calendar-mode unit test doesn’t model real click behavior (missing the paired selectedRelativeTimeChange), so it asserts an incorrect state and could mask regressions.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates kv-time-picker and kv-relative-time-picker so that selecting a relative time option commits immediately on click (and closes the dropdown), while Apply/Cancel are only shown when a calendar-based view is active, reducing friction in the simple option-list flow.

Changes:

  • kv-time-picker: commit-and-close on relative option click (when no calendar is visible) and commit-without-close on timezone changes in the option list.
  • kv-time-picker: render footer actions (Apply/Cancel) only for calendar-visible views; drop the footer entirely when it would be empty.
  • kv-relative-time-picker: introduce a new relativeTimeOptionClicked intent event to distinguish real user clicks from the periodic “now-relative” refresh emissions.
File summaries
File Description
packages/ui-components/src/components/time-picker/time-picker.tsx Adds click-to-commit behavior for relative options, restructures commit vs publish logic, and conditionally renders footer/actions based on view.
packages/ui-components/src/components/time-picker/test/time-picker.spec.tsx Adds unit coverage for click-to-commit, timezone commit behavior, calendar-only Apply/Cancel visibility, and calendar-hide rollback behavior.
packages/ui-components/src/components/relative-time-picker/relative-time-picker.types.ts Exposes the new relativeTimeOptionClicked event in the public component event interface.
packages/ui-components/src/components/relative-time-picker/relative-time-picker.tsx Emits relativeTimeOptionClicked on option selection (including re-clicking the already-selected option).
packages/ui-components/src/components/relative-time-picker/readme.md Regenerates docs to include the new event in the Events table.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/ui-components/src/components/time-picker/test/time-picker.spec.tsx Outdated
@djcouto djcouto changed the title feat(time-picker)!: apply relative options on click feat(time-picker): apply relative options on click Sep 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3ff041f8bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/ui-components/src/components/time-picker/time-picker.tsx Outdated
Committing a timezone change in the option list assumed a selection was
already in place. When the given `relativeTimePickerOptions` omit the default
key nothing is preselected — `selectedTimeState` starts as `{ key: '', range: [] }`
— so touching the timezone first emitted a `timeRangeChange` whose empty range
breaks `ITimePickerTime` and hands a consumer an unusable range. The cast in
`getTimePickerEventPayload` kept `tsc` quiet about it.

The commit now needs a complete range as well as a calendar-free view, reusing
the `validateNewRange` check behind Apply. Otherwise the timezone is kept as
draft, so the next option click still carries it.

Also fixes the spec helper, which dispatched only `relativeTimeOptionClicked`.
A real click on a different option emits `selectedRelativeTimeChange` too, so
the calendar-mode test asserted a draft state that cannot happen and would have
masked a regression in it; the helper now models both events, and takes
`changed: false` for a re-click on the selected option.
Copilot AI review requested due to automatic review settings September 8, 2026 15:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The behavior change is implemented with clear separation between “draft updates” and “user intent commits,” and it’s backed by focused regression tests covering the key interaction modes.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@djcouto
djcouto merged commit 306424b into dev Sep 10, 2026
5 checks passed
@djcouto
djcouto deleted the dc/time-picker branch September 10, 2026 15:46
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