diff --git a/packages/scenes/package.json b/packages/scenes/package.json
index a3c592aad..30400473b 100644
--- a/packages/scenes/package.json
+++ b/packages/scenes/package.json
@@ -48,12 +48,12 @@
"uuid": "^9.0.0"
},
"peerDependencies": {
- "@grafana/data": ">=10.4",
- "@grafana/e2e-selectors": ">=10.4",
+ "@grafana/data": ">=11.5",
+ "@grafana/e2e-selectors": ">=11.5",
"@grafana/i18n": "*",
- "@grafana/runtime": ">=10.4",
- "@grafana/schema": ">=10.4",
- "@grafana/ui": ">=10.4",
+ "@grafana/runtime": ">=11.5",
+ "@grafana/schema": ">=11.5",
+ "@grafana/ui": ">=11.5",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.28.0"
diff --git a/packages/scenes/src/index.ts b/packages/scenes/src/index.ts
index 267a98924..6a6a2fd59 100644
--- a/packages/scenes/src/index.ts
+++ b/packages/scenes/src/index.ts
@@ -78,6 +78,7 @@ export {
} from './variables/variants/MultiValueVariable';
export { LocalValueVariable } from './variables/variants/LocalValueVariable';
export { IntervalVariable } from './variables/variants/IntervalVariable';
+export { ExperimentalIntervalVariable } from './variables/variants/ExperimentalIntervalVariable';
export { AdHocFiltersVariable } from './variables/adhoc/AdHocFiltersVariable';
export type { AdHocFilterWithLabels } from './variables/adhoc/AdHocFiltersVariable';
export type {
diff --git a/packages/scenes/src/variables/variants/ExperimentalIntervalVariable.tsx b/packages/scenes/src/variables/variants/ExperimentalIntervalVariable.tsx
new file mode 100644
index 000000000..224147f15
--- /dev/null
+++ b/packages/scenes/src/variables/variants/ExperimentalIntervalVariable.tsx
@@ -0,0 +1,147 @@
+import { t } from '@grafana/i18n';
+import { rangeUtil } from '@grafana/data';
+import { VariableRefresh } from '@grafana/schema';
+import { Combobox, ComboboxOption } from '@grafana/ui';
+import React from 'react';
+import { Observable, of } from 'rxjs';
+import { sceneGraph } from '../../core/sceneGraph';
+import { SceneObjectBase } from '../../core/SceneObjectBase';
+import { SceneComponentProps, SceneObjectUrlValues } from '../../core/types';
+import { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig';
+import { AUTO_VARIABLE_TEXT, AUTO_VARIABLE_VALUE } from '../constants';
+import {
+ SceneVariable,
+ SceneVariableState,
+ SceneVariableValueChangedEvent,
+ ValidateAndUpdateResult,
+ VariableValue,
+} from '../types';
+
+export interface IntervalVariableState extends SceneVariableState {
+ intervals: string[];
+ value: string;
+ autoEnabled: boolean;
+ autoMinInterval: string;
+ autoStepCount: number;
+ refresh: VariableRefresh;
+}
+
+/**
+ * @experimental Temporary experimental alternative to IntervalVariable
+ * that implements new `` instead of ``
+ */
+
+export class ExperimentalIntervalVariable
+ extends SceneObjectBase
+ implements SceneVariable
+{
+ public constructor(initialState: Partial) {
+ super({
+ type: 'interval',
+ value: '',
+ intervals: ['1m', '10m', '30m', '1h', '6h', '12h', '1d', '7d', '14d', '30d'],
+ name: '',
+ autoStepCount: 30,
+ autoMinInterval: '10s',
+ autoEnabled: false,
+ refresh: VariableRefresh.onTimeRangeChanged,
+ ...initialState,
+ });
+
+ this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: () => [this.getKey()] });
+ }
+
+ private getKey(): string {
+ return `var-${this.state.name}`;
+ }
+
+ public getUrlState() {
+ return { [this.getKey()]: this.state.value };
+ }
+
+ public updateFromUrl(values: SceneObjectUrlValues) {
+ const update: Partial = {};
+ const val = values[this.getKey()];
+ if (typeof val === 'string') {
+ // support old auto interval url value
+ if (val.startsWith('$__auto_interval_')) {
+ update.value = AUTO_VARIABLE_VALUE;
+ } else {
+ update.value = val;
+ }
+ }
+ this.setState(update);
+ }
+
+ public getOptionsForSelect(): Array> {
+ const { value: currentValue, intervals, autoEnabled } = this.state;
+
+ let options = intervals.map((interval) => ({ value: interval, label: interval }));
+
+ if (autoEnabled) {
+ options = [{ value: AUTO_VARIABLE_VALUE, label: AUTO_VARIABLE_TEXT }, ...options];
+ }
+
+ // If the current value is not in the list of intervals, add it to the list
+ if (currentValue && !options.some((option) => option.value === currentValue)) {
+ options.push({ value: currentValue, label: currentValue });
+ }
+
+ return options;
+ }
+
+ public getValue(): VariableValue {
+ const { value, autoStepCount, autoMinInterval } = this.state;
+ if (value === AUTO_VARIABLE_VALUE) {
+ return this.getAutoRefreshInteval(autoStepCount, autoMinInterval);
+ }
+
+ return value;
+ }
+
+ private getAutoRefreshInteval(autoStepCount: number, minRefreshInterval: string) {
+ const timeRange = sceneGraph.getTimeRange(this).state.value;
+ const intervalObject = rangeUtil.calculateInterval(timeRange, autoStepCount, minRefreshInterval);
+ return intervalObject.interval;
+ }
+
+ public _onChange = (value: ComboboxOption) => {
+ this.setState({ value: value.value! });
+ this.publishEvent(new SceneVariableValueChangedEvent(this), true);
+ };
+
+ public validateAndUpdate(): Observable {
+ const { value, intervals } = this.state;
+ let shouldPublish = false;
+
+ if (value === AUTO_VARIABLE_VALUE) {
+ shouldPublish = true;
+ } else if (!value && intervals.length > 0) {
+ const firstOption = intervals[0];
+ this.setState({ value: firstOption });
+ shouldPublish = true;
+ }
+
+ if (shouldPublish) {
+ this.publishEvent(new SceneVariableValueChangedEvent(this), true);
+ }
+
+ return of({});
+ }
+
+ public static Component = ({ model }: SceneComponentProps) => {
+ const { key, value } = model.useState();
+
+ return (
+
+ );
+ };
+}
diff --git a/yarn.lock b/yarn.lock
index afdb77db1..805ce2006 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4047,12 +4047,12 @@ __metadata:
typescript: "npm:5.4.3"
uuid: "npm:^9.0.0"
peerDependencies:
- "@grafana/data": ">=10.4"
- "@grafana/e2e-selectors": ">=10.4"
+ "@grafana/data": ">=11.5"
+ "@grafana/e2e-selectors": ">=11.5"
"@grafana/i18n": "*"
- "@grafana/runtime": ">=10.4"
- "@grafana/schema": ">=10.4"
- "@grafana/ui": ">=10.4"
+ "@grafana/runtime": ">=11.5"
+ "@grafana/schema": ">=11.5"
+ "@grafana/ui": ">=11.5"
react: ^18.0.0
react-dom: ^18.0.0
react-router-dom: ^6.28.0