fix: remeasure container-width Vega charts when host gains size#10266
Conversation
Vega-Lite only updates width:"container" on window.resize, so charts that mount in a zero-size parent stay at 0px. Observe the embed host and dispatch resize when it gains width; drop the slides-only triggerResize hack. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Addresses a Vega/Vega-Lite rendering issue where width: "container" charts can remain stuck at 0px when initially mounted in a zero-sized/hidden host (since Vega-Lite only remeasures on window.resize). The PR adds a ResizeObserver-based hook to proactively trigger Vega’s existing resize pathway when the embed host gains width, and wires it into both the plugin-rendered and mime-rendered Vega surfaces.
Changes:
- Add
useVegaContainerRemeasurehook to observe the chart host element and dispatchwindow.resizeon meaningful width changes. - Integrate the hook into the plugin Vega render path (
vega-component.tsx) and the mime path by wrappingreact-vega’sVegaEmbed(VegaEmbedContainer+ updatedLazyVegaEmbed). - Remove the slides-only
triggerResize()workaround fromreveal-component.tsxand add unit tests for the new hook.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/plugins/impl/vega/vega-component.tsx | Enables container-width remeasurement for plugin-based Vega rendering (mo.ui.altair_chart). |
| frontend/src/plugins/impl/vega/use-vega-container-remeasure.ts | New hook to observe host width changes and trigger Vega’s resize behavior. |
| frontend/src/plugins/impl/vega/tests/use-vega-container-remeasure.test.ts | Adds unit tests validating resize dispatch behavior and the disabled no-op path. |
| frontend/src/components/slides/reveal-component.tsx | Removes the slides-specific resize hack now that remeasurement is handled at the chart layer. |
| frontend/src/components/charts/vega-embed-container.tsx | Adds a wrapper around VegaEmbed to apply remeasurement behavior for mime-rendered Vega. |
| frontend/src/components/charts/lazy.tsx | Switches lazy Vega embed import to the new wrapper so the mime path benefits automatically. |
There was a problem hiding this comment.
No issues found across 6 files
Architecture diagram
sequenceDiagram
participant UI as React Component
participant VCI as VegaEmbedContainer (VCI)
participant VE as VegaEmbed
participant HOOK as useVegaContainerRemeasure
participant RO as ResizeObserver
participant W as Window
participant VL as Vega-Lite Internal
Note over UI,VL: Host gains size (e.g. display:none → visible)
UI->>VCI: Render with spec
alt spec width: "container"
VCI->>HOOK: useContainerRemeasure(ref, enabled=true)
HOOK->>RO: observe(host element)
VCI->>VE: Render VegaEmbed
VE->>VL: Embed chart (reads clientWidth)
Note over VL: Initially 0px → canvas stuck at 0
else fixed width
VCI->>VE: Render VegaEmbed (no observer)
end
Note over UI,VL: Later — parent gains layout width
RO->>HOOK: ResizeObserverEntry (contentRect.width > 0)
HOOK->>HOOK: Check width changed from last known
alt Width increased from 0 to positive
HOOK->>W: dispatchEvent(new Event("resize"))
W->>VL: window.resize listener fires
VL->>VL: Remeasure container → update canvas width
else Width unchanged (debounce)
HOOK->>HOOK: Skip dispatch
end
Note over UI,VL: Variation: mo.ui.altair_chart (VegaComponent)
participant VC as VegaComponent
participant LV as LoadedVegaComponent
UI->>VC: Render mo.ui.altair_chart
VC->>LV: Render LoadedVegaComponent
LV->>HOOK: useVegaContainerRemeasure(ref, containerWidth==="container")
HOOK->>RO: observe(vegaRef element)
Note over RO,W: Same path as above on resize
Bundle ReportChanges will increase total bundle size by 10.91kB (0.04%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: marimo-esmAssets Changed:
Files in
Files in
Files in
Files in
Files in
|
📝 Summary
This is only reproducible in some specific scenarios, marimo run mode with slides view with container chart widths
Vega-Lite only remeasures
width: "container"charts onwindow.resize. Charts that mount inside a zero-size parent (e.g.display: none) stick at a 0px canvas until something dispatches that event.useVegaContainerRemeasureto observe the embed host and dispatchwindow.resizewhen it gains a real widthLazyVegaEmbed/Output.tsx) andmo.ui.altair_chart(VegaComponent)triggerResize()hack inreveal-component.tsx, which raced on fast navigation and only covered one surfaceSlides CSS already keeps past/future sections laid out (
display: block !important), so the deck often masks this; the failure still shows for true zero-size hosts (hidden tabs, cloned/offscreen mounts, etc.).📋 Pre-Review Checklist
✅ Merge Checklist
Made with Cursor