Skip to content

fix: chart resize and dynamic y-axis for non-line chart types in Explore - #9808

Merged
nishantmonu51 merged 3 commits into
mainfrom
nishant/fix-explore-chart-resize-and-dynamic-y-axis
Aug 18, 2026
Merged

fix: chart resize and dynamic y-axis for non-line chart types in Explore#9808
nishantmonu51 merged 3 commits into
mainfrom
nishant/fix-explore-chart-resize-and-dynamic-y-axis

Conversation

@nishantmonu51

Copy link
Copy Markdown
Collaborator

Explore's timeseries area has two renderers: a custom SVG one for the default/line types, and Vega-Lite for grouped bar, stacked bar and stacked area (usesVegaRenderer in chart-series.ts). Neither the resize divider nor the dynamic y-axis toggle was wired into the Vega path.

  • Resize. Added min-w-0 to the chart grid cells in MetricsTimeSeriesCharts.svelte. A 1fr track's floor is its item's min-content size, and the Vega <canvas> has an intrinsic pixel width, so the column could grow but never shrink past the last width Vega drew at. The container therefore never shrank, bind:contentRect never fired, and the chart never re-rendered smaller. The SVG chart is a w-full <svg> with no intrinsic width, which is why only the line chart resized correctly.
  • Dynamic y-axis. Threaded dynamicYAxis through MeasureChart and TDDChart into createTDDCartesianSpec as zeroBasedOrigin. The field was previously never set, and builder.ts emits zero: false whenever it is not true, so every Vega chart was permanently dynamic — bar charts drew from a non-zero baseline even with the toggle off, and toggling it had no effect.
  • Zero baseline in the SVG marks. Clamped zeroY in BarChart.svelte and the area generator's y0 in TimeSeriesChart.svelte via a new clampToRange helper. With a dynamic axis the domain can exclude zero, putting yScale(0) outside the clipped plot, which rendered bars as full-height slabs and flooded the area fill. MeasureChartBody and MeasureChartTooltip already clamped the same value. Reachable in Explore whenever the default chart type falls under six points.
  • Vega resize path. Split createEmbedOptions into createBaseEmbedOptions plus a width/height spread at the call site. svelte-vega compares options key by key with ===, ignoring width and height, so the fresh tooltip/loader/config objects made it tear down and re-embed the whole view on every frame of a drag. It now calls view.width() on the existing view, which also fixes brush state being lost on resize — something the existing spec/colorMapping memoization was already trying to achieve. Applied to VegaRenderer.svelte too, since canvas dashboards hit the same path.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

https://claude.ai/code/session_01DT291cEZct4NiwpGFbyq7o

The explore timeseries area has two renderers: a custom SVG one for the
default/line types, and Vega-Lite for grouped bar, stacked bar and stacked
area. Neither the resize divider nor the dynamic y-axis toggle was wired into
the Vega path.

- Add `min-w-0` to the chart grid cells in `MetricsTimeSeriesCharts`. The
  `1fr` track's floor is its item's min-content size; the Vega `<canvas>` has
  an intrinsic pixel width, so the column could grow but never shrink past the
  last width Vega drew at. The container therefore never shrank, `contentRect`
  never fired, and the chart never re-rendered smaller.
- Thread `dynamicYAxis` through `MeasureChart` and `TDDChart` into
  `createTDDCartesianSpec` as `zeroBasedOrigin`. The field was previously
  unset, and `builder.ts` emits `zero: false` whenever it is not `true`, so
  every Vega chart was permanently dynamic and bar charts drew from a non-zero
  baseline even with the toggle off.
- Clamp the zero baseline in `BarChart` and the area generator in
  `TimeSeriesChart`. With a dynamic axis the domain can exclude zero, putting
  `yScale(0)` outside the clipped plot, which rendered bars as full-height
  slabs and flooded the area fill. `MeasureChartBody` and `MeasureChartTooltip`
  already clamped the same value.
- Split `createEmbedOptions` into `createBaseEmbedOptions` plus a width/height
  spread at the call site. svelte-vega compares options key by key with `===`,
  ignoring width and height, so the fresh `tooltip`/`loader`/`config` objects
  made it tear down and re-embed the whole view on every frame of a drag.
  It now resizes the existing view and keeps brush state.

Claude-Session: https://claude.ai/code/session_01DT291cEZct4NiwpGFbyq7o
Wiring `zeroBasedOrigin` through to the spec was not enough. Vega-Lite stacks
bar and area marks by default, and a stacked scale derives its domain from the
stack's start/end fields, which always span zero. `scale.zero: false` was
compiled into the Vega spec but had nothing to act on, so the toggle stayed
inert. Compiling the spec confirms it: the domain was
`{fields: ["total_start", "total_end"]}` in both states.

Add `createStackOverride`, which emits `stack: null` when the origin is not
zero-based, and apply it in the grouped bar, stacked bar and area builders. It
is guarded on the absence of a color field: un-stacking a multi-series chart
would overlap its marks rather than stack them, so those stay zero-based.

The single-series bar chart now compiles to `{field: "total_sales"}` with
`zero: false`. Covered by tests that compile all the way down to Vega, since
the `zero` flag alone does not tell you whether the axis is actually dynamic.

Claude-Session: https://claude.ai/code/session_01DT291cEZct4NiwpGFbyq7o
@nishantmonu51
nishantmonu51 merged commit ce24ebc into main Aug 18, 2026
10 checks passed
@nishantmonu51
nishantmonu51 deleted the nishant/fix-explore-chart-resize-and-dynamic-y-axis branch August 18, 2026 08:53
nishantmonu51 added a commit that referenced this pull request Aug 18, 2026
…ore (#9808)

* fix: chart resize and dynamic y-axis for non-line explore chart types

The explore timeseries area has two renderers: a custom SVG one for the
default/line types, and Vega-Lite for grouped bar, stacked bar and stacked
area. Neither the resize divider nor the dynamic y-axis toggle was wired into
the Vega path.

- Add `min-w-0` to the chart grid cells in `MetricsTimeSeriesCharts`. The
  `1fr` track's floor is its item's min-content size; the Vega `<canvas>` has
  an intrinsic pixel width, so the column could grow but never shrink past the
  last width Vega drew at. The container therefore never shrank, `contentRect`
  never fired, and the chart never re-rendered smaller.
- Thread `dynamicYAxis` through `MeasureChart` and `TDDChart` into
  `createTDDCartesianSpec` as `zeroBasedOrigin`. The field was previously
  unset, and `builder.ts` emits `zero: false` whenever it is not `true`, so
  every Vega chart was permanently dynamic and bar charts drew from a non-zero
  baseline even with the toggle off.
- Clamp the zero baseline in `BarChart` and the area generator in
  `TimeSeriesChart`. With a dynamic axis the domain can exclude zero, putting
  `yScale(0)` outside the clipped plot, which rendered bars as full-height
  slabs and flooded the area fill. `MeasureChartBody` and `MeasureChartTooltip`
  already clamped the same value.
- Split `createEmbedOptions` into `createBaseEmbedOptions` plus a width/height
  spread at the call site. svelte-vega compares options key by key with `===`,
  ignoring width and height, so the fresh `tooltip`/`loader`/`config` objects
  made it tear down and re-embed the whole view on every frame of a drag.
  It now resizes the existing view and keeps brush state.

Claude-Session: https://claude.ai/code/session_01DT291cEZct4NiwpGFbyq7o

* fix: disable implicit stacking so the dynamic y-axis takes effect

Wiring `zeroBasedOrigin` through to the spec was not enough. Vega-Lite stacks
bar and area marks by default, and a stacked scale derives its domain from the
stack's start/end fields, which always span zero. `scale.zero: false` was
compiled into the Vega spec but had nothing to act on, so the toggle stayed
inert. Compiling the spec confirms it: the domain was
`{fields: ["total_start", "total_end"]}` in both states.

Add `createStackOverride`, which emits `stack: null` when the origin is not
zero-based, and apply it in the grouped bar, stacked bar and area builders. It
is guarded on the absence of a color field: un-stacking a multi-series chart
would overlap its marks rather than stack them, so those stay zero-based.

The single-series bar chart now compiles to `{field: "total_sales"}` with
`zero: false`. Covered by tests that compile all the way down to Vega, since
the `zero` flag alone does not tell you whether the axis is actually dynamic.

Claude-Session: https://claude.ai/code/session_01DT291cEZct4NiwpGFbyq7o

* chore: fix prettier formatting in tdd-chart-config.spec.ts

Claude-Session: https://claude.ai/code/session_01Mj1YdKjgEEEwHNXwdhob6E
(cherry picked from commit ce24ebc)
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.

2 participants