From 038d8aad6ac264f11b4cf156453627a46808a80a Mon Sep 17 00:00:00 2001 From: Nishant Bangarwa Date: Thu, 25 Jun 2026 18:21:56 +0530 Subject: [PATCH] feat: resizable divider in Time Dimension Detail view Add a draggable divider between the timeseries chart and the detail table in the Time Dimension Detail view, mirroring the resizable split between timeseries and leaderboards in explore. Persist both the TDD chart height and the explore timeseries width to localStorage so the split is preserved across navigation. --- .../TimeDimensionDisplay.svelte | 2 +- .../MetricsTimeSeriesCharts.svelte | 4 ++ .../measure-chart/MeasureChart.svelte | 16 +++---- .../measure-chart/MeasureChartBody.svelte | 5 ++- .../dashboards/workspace/Dashboard.svelte | 44 ++++++++++++++++--- .../workspace/dashboard-layout-store.ts | 30 +++++++++++++ 6 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 web-common/src/features/dashboards/workspace/dashboard-layout-store.ts diff --git a/web-common/src/features/dashboards/time-dimension-details/TimeDimensionDisplay.svelte b/web-common/src/features/dashboards/time-dimension-details/TimeDimensionDisplay.svelte index c76aa87ec8ee..83b5d9e959ae 100644 --- a/web-common/src/features/dashboards/time-dimension-details/TimeDimensionDisplay.svelte +++ b/web-common/src/features/dashboards/time-dimension-details/TimeDimensionDisplay.svelte @@ -196,7 +196,7 @@
handlePan("right")} {showComparison} {showTimeDimensionDetail} + {tddChartHeight} dynamicYAxis={dynamicYAxisScale} onScrub={handleScrub} onScrubClear={() => { diff --git a/web-common/src/features/dashboards/time-series/measure-chart/MeasureChart.svelte b/web-common/src/features/dashboards/time-series/measure-chart/MeasureChart.svelte index f630666f2f8f..fd17152f60cb 100644 --- a/web-common/src/features/dashboards/time-series/measure-chart/MeasureChart.svelte +++ b/web-common/src/features/dashboards/time-series/measure-chart/MeasureChart.svelte @@ -64,6 +64,9 @@ export let scrubController: ScrubController | undefined = undefined; export let connectNulls: boolean = true; export let dynamicYAxis: boolean = false; + // Chart height when expanded in the Time Dimension Detail view. Driven by the + // resizable divider between the timeseries and the detail table. + export let tddChartHeight: number = 245; const client = useRuntimeClient(); const { visible, observe } = createVisibilityObserver(VISIBILITY_ROOT_MARGIN); @@ -80,7 +83,7 @@ }); $: measureName = measure.name ?? ""; - $: height = showTimeDimensionDetail ? 245 : 145; + $: height = showTimeDimensionDetail ? tddChartHeight : 145; $: effectiveChartType = resolveEffectiveChartType( tddChartType, @@ -316,17 +319,11 @@
{#if !$visible || (isFetching && data.length === 0)} -
+
{:else if isError} -
+
{:else if usesVegaChart && data.length > 0} @@ -375,6 +372,7 @@ {connectNulls} {dynamicYAxis} {tddChartType} + {tddChartHeight} /> {:else}
diff --git a/web-common/src/features/dashboards/time-series/measure-chart/MeasureChartBody.svelte b/web-common/src/features/dashboards/time-series/measure-chart/MeasureChartBody.svelte index 55ed21bdf38e..8932fab36fcb 100644 --- a/web-common/src/features/dashboards/time-series/measure-chart/MeasureChartBody.svelte +++ b/web-common/src/features/dashboards/time-series/measure-chart/MeasureChartBody.svelte @@ -89,6 +89,9 @@ export let connectNulls: boolean = true; export let dynamicYAxis: boolean = false; export let tddChartType: TDDChart = TDDChart.DEFAULT; + // Chart height when expanded in the Time Dimension Detail view. Driven by the + // resizable divider between the timeseries and the detail table. + export let tddChartHeight: number = 245; const annotationPopover = new AnnotationPopoverController(); const hoveredAnnotationGroup = annotationPopover.hoveredGroup; @@ -111,7 +114,7 @@ annotationPopover.destroy(); }); - $: height = showTimeDimensionDetail ? 245 : 145; + $: height = showTimeDimensionDetail ? tddChartHeight : 145; $: config = computeChartConfig(clientWidth, height, showTimeDimensionDetail); $: pb = config.plotBounds; diff --git a/web-common/src/features/dashboards/workspace/Dashboard.svelte b/web-common/src/features/dashboards/workspace/Dashboard.svelte index 760fed085813..cbac3e2f4682 100644 --- a/web-common/src/features/dashboards/workspace/Dashboard.svelte +++ b/web-common/src/features/dashboards/workspace/Dashboard.svelte @@ -30,14 +30,23 @@ import { useTimeControlStore } from "../time-controls/time-control-store"; import TimeDimensionDisplay from "../time-dimension-details/TimeDimensionDisplay.svelte"; import MetricsTimeSeriesCharts from "../time-series/MetricsTimeSeriesCharts.svelte"; + import { + DEFAULT_TDD_CHART_HEIGHT, + DEFAULT_TIMESERIES_WIDTH, + MIN_TDD_CHART_HEIGHT, + MIN_TIMESERIES_WIDTH, + exploreTimeseriesWidth, + tddChartHeight, + } from "./dashboard-layout-store"; export let exploreName: string; export let metricsViewName: string; export let isEmbedded: boolean = false; export let embedThemeName: Readable | null = null; - const DEFAULT_TIMESERIES_WIDTH = 580; - const MIN_TIMESERIES_WIDTH = 440; + // Vertical space reserved below the chart for the chart toolbar, axis, big + // number, and a minimum detail table height when computing the drag maximum. + const TDD_RESERVED_HEIGHT = 280; const StateManagers = getStateManagers(); const { selectors: { @@ -53,7 +62,7 @@ const timeControlsStore = useTimeControlStore(StateManagers); let exploreContainerWidth: number; - let metricsWidth = DEFAULT_TIMESERIES_WIDTH; + let exploreContainerHeight: number; let resizing = false; const client = useRuntimeClient(); @@ -184,17 +193,21 @@ class:left-shift={extraLeftPadding} class:w-full={$dynamicHeight} class:size-full={!$dynamicHeight} + bind:clientHeight={exploreContainerHeight} >
{#key exploreName} {#if hasTimeSeries} {:else} @@ -203,6 +216,23 @@
{#if showTimeDimensionDetail && expandedMeasureName} +
+ { + tddChartHeight.set(height); + }} + /> +
{ - metricsWidth = width; + onUpdate={(width: number) => { + exploreTimeseriesWidth.set(width); }} />
diff --git a/web-common/src/features/dashboards/workspace/dashboard-layout-store.ts b/web-common/src/features/dashboards/workspace/dashboard-layout-store.ts new file mode 100644 index 000000000000..02e942c4ea5c --- /dev/null +++ b/web-common/src/features/dashboards/workspace/dashboard-layout-store.ts @@ -0,0 +1,30 @@ +import { localStorageStore } from "@rilldata/web-common/lib/store-utils/local-storage"; + +// Explore view: width (px) of the timeseries charts beside the leaderboards. +export const DEFAULT_TIMESERIES_WIDTH = 580; +export const MIN_TIMESERIES_WIDTH = 440; + +// Time Dimension Detail view: height (px) of the timeseries chart above the +// detail table. +export const DEFAULT_TDD_CHART_HEIGHT = 245; +export const MIN_TDD_CHART_HEIGHT = 145; + +/** + * Width of the timeseries charts in the explore view, controlled by the + * resizable divider between the charts and the leaderboards. Persisted so the + * split is preserved as the user navigates back and forth. + */ +export const exploreTimeseriesWidth = localStorageStore( + "explore-timeseries-width", + DEFAULT_TIMESERIES_WIDTH, +); + +/** + * Height of the expanded timeseries chart in the Time Dimension Detail view, + * controlled by the resizable divider between the chart and the detail table. + * Persisted so the split is preserved as the user navigates back and forth. + */ +export const tddChartHeight = localStorageStore( + "tdd-chart-height", + DEFAULT_TDD_CHART_HEIGHT, +);