Skip to content

feat(site): native picker, [now] shortcut, and Now label in DateTimeRangeFilter - #28318

Closed
johnstcn wants to merge 3 commits into
mainfrom
cian/datetime-range-filter-followups
Closed

feat(site): native picker, [now] shortcut, and Now label in DateTimeRangeFilter#28318
johnstcn wants to merge 3 commits into
mainfrom
cian/datetime-range-filter-followups

Conversation

@johnstcn

@johnstcn johnstcn commented Aug 19, 2026

Copy link
Copy Markdown
Member

Follow-ups to #28255

Native picker alongside free text. Each From/To field keeps its free-text grammar (now, HH:mm, ISO date/datetime) and gains a calendar icon that opens the native datetime-local picker via showPicker() on a hidden input seeded from the current text. The picker commits to the text field on the input event and marks the field touched so Apply enables. The calendar icons are tabIndex={-1} so Tab still moves From to To directly. The grammar also accepts YYYY-MM-DDTHH:mm, the picker's machine format and a pasteable ISO form.

[now] shortcut. A right-aligned [now] button on the To label fills the field with the literal now expression, the live bound the picker cannot express. The clickable datetime examples are gone; the picker covers them, and blur auto-fill made the explanatory footer text redundant.

Trigger reads "- Now" for a live bound. A shared isLiveNow (one-minute tolerance) drives both the popover prefill and the trigger label, so a To bound at the current moment reads MMM D - Now instead of MMM D - Today. A frozen earlier-today bound still reads Today.

Partial ranges. TimeRange bounds are now optional. Before, a hand-written one-sided query (only started_after in the search box) showed "Last 24 hours" on the trigger while the query stayed one-sided. Now the trigger shows Custom and the popover shows the present bound with an empty field for the missing one. Apply requires both bounds, so the popover always commits a full range; one-sided queries stay a deliberate free-text-only escape hatch. The page's parseTimeRange returns partial ranges so the trigger reflects the query. A FullTimeRange type (both bounds present) covers the committed value and query builders while TimeRange stays partial for the display value.

Open questions: how best to style the native picker?

Screenshots

image image

Generated by Coder Agents on behalf of @johnstcn.

The examples footer is now clickable: Now fills To, the current
HH:mm and a datetime 24 hours ago fill From, each derived from the
current time. TimeRange bounds are now optional; a partial range
(from a hand-written one-sided filter query) shows Custom in the
trigger and an empty field in the popover, with Apply requiring both
bounds so the popover always commits a full range.
@linear-code

linear-code Bot commented Aug 19, 2026

Copy link
Copy Markdown

AIGOV-580

@johnstcn johnstcn changed the title feat(site): clickable examples and partial ranges in DateTimeRangeFilter feat(site): native picker, [now] shortcut, and Now label in DateTimeRangeFilter Aug 19, 2026
@johnstcn
johnstcn marked this pull request as ready for review August 19, 2026 22:56
Copilot AI lite review requested due to automatic review settings August 19, 2026 22:56
Comment on lines +231 to +240
<input
ref={fromPickerRef}
type="datetime-local"
tabIndex={-1}
aria-hidden="true"
className="pointer-events-none absolute h-0 w-0 opacity-0"
// Chrome and WebKit fire input per pick; change fires only
// on dismissal, which is too late for live feedback.
onInput={(event) => pickFrom(event.currentTarget.value)}
/>

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.

Open question: this seems to render in the OS-specific colour theme (light / dark). I haven't figured out how to make it sync with the site theme without touching index.css. I'm open to other suggestions.

Copilot AI 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.

Pull request overview

This PR enhances the shared DateTimeRangeFilter used on the AI Gateway Sessions page by combining free-text time expressions with a native datetime-local picker, improving “now” UX, and correctly reflecting partial (one-sided) time ranges in the trigger and popover.

Changes:

  • Introduces FullTimeRange (committed ranges) alongside TimeRange (optionally partial/display ranges), and updates Sessions page parsing to support partial ranges.
  • Adds native datetime pickers (via hidden datetime-local inputs) next to From/To fields, plus a [now] shortcut for the To bound.
  • Updates trigger labeling to show Now for live end bounds (with a tolerance window) and Custom for partial ranges; updates tests/stories accordingly.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
site/src/pages/AIBridgePage/ListSessionsPage/timeRange.ts Makes default/query builders require FullTimeRange and updates parsing to return partial ranges for display.
site/src/pages/AIBridgePage/ListSessionsPage/timeRange.test.ts Updates tests for partial-range parsing and malformed-bound behavior.
site/src/pages/AIBridgePage/ListSessionsPage/ListSessionsPageView.stories.tsx Updates story fixtures to use FullTimeRange where committed values are required.
site/src/pages/AIBridgePage/ListSessionsPage/ListSessionsFilter.tsx Adjusts filter props to accept partial timeRange while committing FullTimeRange on change.
site/src/pages/AIBridgePage/ListSessionsPage/ListSessionsFilter.stories.tsx Updates story fixtures to use FullTimeRange.
site/src/components/DateTimeRangeFilter/timeRange.ts Adds FullTimeRange, supports T-separated picker format, and introduces isLiveNow + Custom labeling for partial ranges.
site/src/components/DateTimeRangeFilter/timeRange.test.ts Adds coverage for picker datetime parsing, partial-range trigger label, and “Now” labeling behavior.
site/src/components/DateTimeRangeFilter/DateTimeRangeFilter.tsx Implements native picker integration, [now] shortcut, partial-range UI behavior, and Apply gating requiring full valid bounds.
site/src/components/DateTimeRangeFilter/DateTimeRangeFilter.stories.tsx Updates stories to reflect removed examples footer and adds stories for “Now” and partial-range behaviors.

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

Comment on lines +76 to +86
const openPicker = (input: HTMLInputElement | null, seed: string) => {
if (!input) {
return;
}
// Seed the picker from the current text so it opens on the right moment;
// fall back to now for empty or non-absolute expressions. The picker
// uses "YYYY-MM-DDTHH:mm" in browser-local time.
const parsed = parseTimeExpression(seed, currentTime);
input.value = dayjs(parsed ?? currentTime).format("YYYY-MM-DDTHH:mm");
input.showPicker();
};
Comment on lines +88 to +100
const pickFrom = useEffectEvent((value: string) => {
const parsed = parseTimeExpression(value, currentTime);
if (parsed !== null) {
setFromField({ text: formatDateTime(parsed), touched: true });
}
});

const pickTo = useEffectEvent((value: string) => {
const parsed = parseTimeExpression(value, currentTime);
if (parsed !== null) {
setToField({ text: formatDateTime(parsed), touched: true });
}
});
Comment on lines 7 to 16
export type TimeRange = {
startedAfter?: Date;
startedBefore?: Date;
};

/** A range with both bounds present, as committed by the popover. */
export type FullTimeRange = {
startedAfter: Date;
startedBefore: Date;
};

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.

instead of two types, you could make use of Required or Partial, whichever direction makes the most sense to you: https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype

@johnstcn

Copy link
Copy Markdown
Member Author

Closing in favour of #28392

@johnstcn johnstcn closed this Aug 20, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants