You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a Dashboard header control for viewing and editing a resolved time-range group, following the established Grafana interaction model:
compact current-range display in the header;
absolute From and To editors;
Apply action;
searchable quick ranges;
recently used absolute ranges;
Back and Forward range history;
zoom out;
multiple independent Dashboard time-range groups;
server-timezone disclosure without changing timezone semantics.
This issue is independent from synchronized chart hover/brush interaction in #334. Both features must bind to one shared DashboardTimeRangeController rather than maintaining separate filter, history, or execution state. Either issue may establish that interface first.
Shared controller contract
Use or introduce a Dashboard-session controller with a narrow API such as:
The exact API may differ, but all range changes must pass through one atomic batch-filter path. The header control must not call two individual filter updates or run queries directly.
#334 may provide group resolution from saved-query timeRanges. If this issue lands first, keep group discovery behind the controller interface so the later metadata implementation replaces the source without rewriting the UI.
Header presentation
When the Dashboard has at least one valid time-range group, add the control near Refresh in the Dashboard header:
[‹] [clock 2026-07-20 10:54:35 to 10:56:02 ▴] [›] [zoom out]
Requirements:
range text is compact but unambiguous;
button opens the time-range popover;
Back and Forward buttons reflect disabled state;
zoom-out has an accessible label;
control remains usable in edit and read-only Dashboard modes;
control is absent when no valid range group exists;
responsive layout may collapse labels/icons but must keep all actions reachable.
Multiple groups
A Dashboard may contain several independent groups.
When exactly one group exists, use it automatically and show no selector.
When several groups exist, include a group selector in the popover and optionally a compact selector adjacent to the header range. Until user-facing range names are added, label groups deterministically as:
from_parameter → to_parameter
Disambiguate duplicate parameter labels with a stable short suffix or query/filter context. Group selection is viewer-session state and is not persisted or exported.
Changing the active group updates the displayed range, history buttons, quick-range application target, and absolute editors. It does not change any filters by itself.
Popover layout
Recommended desktop layout:
Absolute time range Search quick ranges
From [2026-07-20 10:54:35] Last 5 minutes
To [2026-07-20 10:56:02] Last 15 minutes
[Apply time range] Last 30 minutes
Last 1 hour
Recently used absolute ranges Last 3 hours
... ...
Server time zone: <current disclosure>
The visual design may adapt to the project style, but should preserve the Grafana mental model.
On narrow screens, stack the absolute editor and quick-range list vertically or use a full-width anchored sheet. Do not allow the popover to overflow the viewport.
Absolute range editor
Provide From and To text inputs initialized from the active group's current filter values.
Requirements:
use the existing parameter-type validation and date/time serialization pipeline;
accept Date, Date32, DateTime, and DateTime64 variations supported by the shared ClickHouse type parser;
preserve existing server-timezone behavior;
do not introduce browser-timezone conversion;
millisecond precision is sufficient;
editing is staged until Apply;
Apply validates both bounds before changing either;
invalid or incomplete values show field-specific diagnostics;
from > to is rejected;
equal values may be rejected as an empty range unless the existing filter contract explicitly permits it;
successful Apply closes the popover by default and triggers one atomic execution wave;
failed Apply keeps the popover open and leaves the prior range unchanged.
Use text inputs in v1. Calendar/date-time picker buttons may be added only if they can preserve the existing server-timezone semantics without introducing a second date model.
Quick ranges
Add a searchable list of predefined relative ranges. Minimum presets:
Last 5 minutes
Last 15 minutes
Last 30 minutes
Last 1 hour
Last 3 hours
Last 6 hours
Last 12 hours
Last 24 hours
Last 2 days
Last 7 days
Last 30 days
Requirements:
reuse the existing relative-time grammar/resolution helpers;
compute one shared now instant per application;
produce absolute From and To values through the declared parameter types;
apply immediately on selection;
close the popover after successful application;
add the resulting absolute range to history and recent ranges;
search filters by label and expression/amount where useful;
no network request is made merely to display or search presets.
For Date/Date32, serialize through the existing pipeline and do not silently adjust inclusive/exclusive boundaries.
Range history
Maintain Back/Forward history separately per time-range group in the Dashboard session.
History entries contain the successfully committed absolute range, not draft input text.
Rules:
initial resolved range is the first history entry;
applying the same normalized range as current does not create a duplicate entry or query wave;
Back moves to the previous committed range;
Forward restores a range after Back;
applying a new range after Back truncates the forward branch;
failed/cancelled changes do not alter history;
history is not persisted to Dashboard documents, saved queries, workspace storage, URLs, or exports;
history is cleared when the Dashboard session/group identity changes.
Choose a bounded history, for example 50 entries per group.
Recently used absolute ranges
Show a bounded list of recent successful absolute ranges.
Recommended behavior:
maintain recents per browser profile using the existing recent-value preference infrastructure where practical;
key recents by compatible From/To declared type pair, not Dashboard identity;
store only normalized absolute values and last-used ordering;
deduplicate identical ranges;
selecting a recent applies it immediately;
provide a clear-recents action;
do not store SQL, query results, host credentials, or Dashboard identity.
If persistence would complicate the first implementation, session-only recents are acceptable only if called out explicitly in the implementation PR. History and recents remain separate concepts.
Zoom out
Zoom out expands the current absolute interval around its midpoint.
Recommended v1 rule:
new duration = current duration × 2
so each edge moves outward by half of the current duration.
Requirements:
resolve the current values to epoch milliseconds through the shared date/time pipeline;
format the expanded bounds through each declared parameter type;
apply atomically and create one history entry;
disable zoom-out when the current range cannot be resolved to two valid instants;
do not apply hidden min/max limits unless existing filter constraints provide them;
Date/Date32 rounding follows normal serialization with no inferred SQL-bound adjustment.
Reset semantics
Do not add a separate Reset button in this issue unless it has a precisely defined source.
Back to the initial session range is already possible through history. A future reset may target an authored Dashboard default when such a contract exists. Do not invent a persisted default range in the Dashboard schema here.
Timezone disclosure
Show the timezone currently used by the existing parameter/date-time pipeline, described as server/session time rather than browser time.
Requirements:
this issue does not change timezone interpretation;
do not add a browser/server timezone switch;
do not convert existing values into browser local time;
hide or use a neutral label if the current server/session timezone cannot be determined reliably;
a future Change time settings action is out of scope unless it opens an existing settings surface without introducing new semantics.
Execution and atomicity
Every successful range change must:
validate/format both bounds;
update and activate both underlying filters atomically;
update all visible filter fields bound to those filters;
create one Dashboard execution generation;
rerun every dependent tile once;
prevent stale prior results from replacing newer results;
append history only after the candidate commit succeeds.
A persistence or execution-start failure must leave the previous current range and history unchanged.
The control changes runtime filter state only. It does not mutate saved-query timeRanges, Dashboard documents, layouts, workspace revision, or portable bundles.
brush commits use the same controller apply() path;
the header display updates immediately after a successful brush;
brush-created ranges enter Back/Forward history and recents under the same rules;
the popover draft is refreshed on next open;
an already-open popover must not silently overwrite a newer brush range: either update untouched draft fields or mark the draft stale and require explicit reload/cancel.
The header control must not depend on crosshair rendering, and crosshair rendering must not depend on the popover DOM.
Accessibility
header range button exposes the complete current range in its accessible name;
Back, Forward, and zoom-out have clear labels and disabled states;
popover has labelled From/To fields and field diagnostics;
quick-range search/list uses standard combobox/listbox behavior;
keyboard navigation, Enter activation, Escape dismissal, outside click, and focus restoration work;
successful changes are announced in a polite live region;
validation and application failures use an alert/status appropriate to severity;
focus returns to the range trigger after dismissal.
Tests
Controller/history
independent histories for multiple groups;
initial entry, Back, Forward, branch truncation, duplicate suppression, and bounds;
failed atomic apply does not change current/history;
chart-brush integration uses the same path;
session teardown clears transient state.
Absolute editor
valid and invalid Date/Date32/DateTime/DateTime64 forms and wrappers;
From-after-To rejection;
server-timezone behavior remains unchanged;
one batch filter update and one execution wave;
draft cancellation leaves current range unchanged.
Quick ranges and recents
deterministic shared now;
each preset resolves correctly;
search behavior;
immediate successful application;
deduplication, ordering, limits, and clear action;
Date/Date32 serialization without hidden day adjustment.
UI and accessibility
absent with no groups;
one-group and multiple-group presentations;
active-group switching;
Back/Forward/zoom disabled states;
keyboard navigation and focus restoration;
responsive desktop/mobile popover placement;
edit and read-only Dashboard modes;
light and dark themes.
Acceptance criteria
Dashboard header shows a compact current-range control when a valid group exists.
One and multiple independent time-range groups are supported.
Absolute From/To values are staged, jointly validated, and atomically applied.
Quick ranges reuse the existing relative-time/type pipeline.
Back/Forward history is separate per group and session-local.
Zoom-out doubles the current interval around its midpoint.
Recent absolute ranges are available and bounded.
Date, Date32, DateTime, and DateTime64 variations work through shared serialization.
Existing server-timezone behavior is disclosed but not changed.
All successful changes trigger one execution wave and update every dependent tile.
Summary
Add a Dashboard header control for viewing and editing a resolved time-range group, following the established Grafana interaction model:
This issue is independent from synchronized chart hover/brush interaction in #334. Both features must bind to one shared
DashboardTimeRangeControllerrather than maintaining separate filter, history, or execution state. Either issue may establish that interface first.Shared controller contract
Use or introduce a Dashboard-session controller with a narrow API such as:
The exact API may differ, but all range changes must pass through one atomic batch-filter path. The header control must not call two individual filter updates or run queries directly.
#334 may provide group resolution from saved-query
timeRanges. If this issue lands first, keep group discovery behind the controller interface so the later metadata implementation replaces the source without rewriting the UI.Header presentation
When the Dashboard has at least one valid time-range group, add the control near Refresh in the Dashboard header:
Requirements:
Multiple groups
A Dashboard may contain several independent groups.
When exactly one group exists, use it automatically and show no selector.
When several groups exist, include a group selector in the popover and optionally a compact selector adjacent to the header range. Until user-facing range names are added, label groups deterministically as:
Disambiguate duplicate parameter labels with a stable short suffix or query/filter context. Group selection is viewer-session state and is not persisted or exported.
Changing the active group updates the displayed range, history buttons, quick-range application target, and absolute editors. It does not change any filters by itself.
Popover layout
Recommended desktop layout:
The visual design may adapt to the project style, but should preserve the Grafana mental model.
On narrow screens, stack the absolute editor and quick-range list vertically or use a full-width anchored sheet. Do not allow the popover to overflow the viewport.
Absolute range editor
Provide From and To text inputs initialized from the active group's current filter values.
Requirements:
from > tois rejected;Use text inputs in v1. Calendar/date-time picker buttons may be added only if they can preserve the existing server-timezone semantics without introducing a second date model.
Quick ranges
Add a searchable list of predefined relative ranges. Minimum presets:
Requirements:
nowinstant per application;For Date/Date32, serialize through the existing pipeline and do not silently adjust inclusive/exclusive boundaries.
Range history
Maintain Back/Forward history separately per time-range group in the Dashboard session.
History entries contain the successfully committed absolute range, not draft input text.
Rules:
Choose a bounded history, for example 50 entries per group.
Recently used absolute ranges
Show a bounded list of recent successful absolute ranges.
Recommended behavior:
If persistence would complicate the first implementation, session-only recents are acceptable only if called out explicitly in the implementation PR. History and recents remain separate concepts.
Zoom out
Zoom out expands the current absolute interval around its midpoint.
Recommended v1 rule:
so each edge moves outward by half of the current duration.
Requirements:
Reset semantics
Do not add a separate Reset button in this issue unless it has a precisely defined source.
Back to the initial session range is already possible through history. A future reset may target an authored Dashboard default when such a contract exists. Do not invent a persisted default range in the Dashboard schema here.
Timezone disclosure
Show the timezone currently used by the existing parameter/date-time pipeline, described as server/session time rather than browser time.
Requirements:
Change time settingsaction is out of scope unless it opens an existing settings surface without introducing new semantics.Execution and atomicity
Every successful range change must:
A persistence or execution-start failure must leave the previous current range and history unchanged.
The control changes runtime filter state only. It does not mutate saved-query
timeRanges, Dashboard documents, layouts, workspace revision, or portable bundles.Interaction with #334
When synchronized chart brushing is implemented:
apply()path;The header control must not depend on crosshair rendering, and crosshair rendering must not depend on the popover DOM.
Accessibility
Tests
Controller/history
Absolute editor
Quick ranges and recents
now;UI and accessibility
Acceptance criteria
Non-goals