Skip to content

fix: remeasure container-width Vega charts when host gains size#10266

Merged
Light2Dark merged 1 commit into
mainfrom
fix/vega-container-remeasure
Jul 22, 2026
Merged

fix: remeasure container-width Vega charts when host gains size#10266
Light2Dark merged 1 commit into
mainfrom
fix/vega-container-remeasure

Conversation

@Light2Dark

@Light2Dark Light2Dark commented Jul 22, 2026

Copy link
Copy Markdown
Member

📝 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 on window.resize. Charts that mount inside a zero-size parent (e.g. display: none) stick at a 0px canvas until something dispatches that event.

  • Add useVegaContainerRemeasure to observe the embed host and dispatch window.resize when it gains a real width
  • Wire it into both render paths: mime (LazyVegaEmbed / Output.tsx) and mo.ui.altair_chart (VegaComponent)
  • Remove the slides-only triggerResize() hack in reveal-component.tsx, which raced on fast navigation and only covered one surface

Slides 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.).

image image

📋 Pre-Review Checklist

  • For large changes, or changes that affect the public API: this change was discussed or approved through an issue, on Discord, or the community discussions (Please provide a link if applicable).
  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • Video or media evidence is provided for any visual changes (optional).

✅ Merge Checklist

  • I have read the contributor guidelines.
  • Documentation has been updated where applicable, including docstrings for API changes.
  • Tests have been added for the changes made.

Made with Cursor

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>
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Jul 22, 2026 4:38am

Request Review

@Light2Dark Light2Dark added bug Something isn't working javascript Pull requests that update javascript code labels Jul 22, 2026
@Light2Dark
Light2Dark requested a review from Copilot July 22, 2026 04:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 useVegaContainerRemeasure hook to observe the chart host element and dispatch window.resize on meaningful width changes.
  • Integrate the hook into the plugin Vega render path (vega-component.tsx) and the mime path by wrapping react-vega’s VegaEmbed (VegaEmbedContainer + updated LazyVegaEmbed).
  • Remove the slides-only triggerResize() workaround from reveal-component.tsx and 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.

Comment thread frontend/src/plugins/impl/vega/use-vega-container-remeasure.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Loading

Re-trigger cubic

@Light2Dark
Light2Dark marked this pull request as ready for review July 22, 2026 05:17
@Light2Dark
Light2Dark requested a review from mscolnick July 22, 2026 05:17
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 10.91kB (0.04%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
marimo-esm 25.41MB 10.91kB (0.04%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: marimo-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/react-*.js 6 bytes 725.17kB 0.0%
assets/react-*.js (Deleted) -264 bytes 0 bytes -100.0% 🗑️
assets/cells-*.js 257 bytes 724.8kB 0.04%
assets/JsonOutput-*.js 89 bytes 573.2kB 0.02%
assets/chunk-*.js 5 bytes 120.28kB 0.0%
assets/index-*.js 1.47kB 432.07kB 0.34%
assets/index-*.css 1.6kB 369.8kB 0.44%
assets/dist-*.js 2 bytes 104 bytes 1.96%
assets/dist-*.js -7 bytes 169 bytes -3.98%
assets/dist-*.js 155 bytes 259 bytes 149.04% ⚠️
assets/dist-*.js -2 bytes 102 bytes -1.92%
assets/dist-*.js 40 bytes 177 bytes 29.2% ⚠️
assets/dist-*.js -95 bytes 164 bytes -36.68%
assets/dist-*.js -220 bytes 183 bytes -54.59%
assets/dist-*.js 139 bytes 276 bytes 101.46% ⚠️
assets/dist-*.js 6 bytes 183 bytes 3.39%
assets/dist-*.js -79 bytes 104 bytes -43.17%
assets/dist-*.js 7 bytes 176 bytes 4.14%
assets/dist-*.js -23 bytes 137 bytes -14.37%
assets/dist-*.js 220 bytes 403 bytes 120.22% ⚠️
assets/dist-*.js -60 bytes 104 bytes -36.59%
assets/dist-*.js 111 bytes 387 bytes 40.22% ⚠️
assets/dist-*.js -227 bytes 160 bytes -58.66%
assets/dist-*.js 33 bytes 137 bytes 31.73% ⚠️
assets/edit-*.js -2.68kB 329.42kB -0.81%
assets/ai-*.js 1 bytes 286.26kB 0.0%
assets/reveal-*.js -165 bytes 250.8kB -0.07%
assets/layout-*.js 39 bytes 205.05kB 0.02%
assets/add-*.js -1.57kB 203.22kB -0.77%
assets/cell-*.js -319 bytes 173.16kB -0.18%
assets/agent-*.js 2 bytes 154.9kB 0.0%
assets/architectureDiagram-*.js 5 bytes 146.48kB 0.0%
assets/ConnectedDataExplorerComponent-*.js 70 bytes 135.56kB 0.05%
assets/file-*.js 10 bytes 51.6kB 0.02%
assets/blockDiagram-*.js 5 bytes 70.91kB 0.01%
assets/c4Diagram-*.js 10 bytes 69.42kB 0.01%
assets/panels-*.js 35 bytes 50.2kB 0.07%
assets/chat-*.js 35 bytes 15.3kB 0.23%
assets/chat-*.js -5 bytes 33.84kB -0.01%
assets/src-*.js -2 bytes 33.42kB -0.01%
assets/state-*.js 180 bytes 32.77kB 0.55%
assets/useNotebookActions-*.js 7.84kB 31.59kB 33.01% ⚠️
assets/session-*.js 2 bytes 28.54kB 0.01%
assets/tooltip-*.js (New) 26.91kB 26.91kB 100.0% 🚀
assets/react-*.browser.esm-Z-MD3n3J.js (New) 25.64kB 25.64kB 100.0% 🚀
assets/home-*.js 35 bytes 24.22kB 0.14%
assets/timeline-*.js 5 bytes 23.27kB 0.02%
assets/journeyDiagram-*.js 5 bytes 23.23kB 0.02%
assets/sankeyDiagram-*.js -5 bytes 21.71kB -0.02%
assets/timer-*.js -1 bytes 20.46kB -0.0%
assets/readonly-*.js 197 bytes 18.8kB 1.06%
assets/command-*.js 42 bytes 9.95kB 0.42%
assets/form-*.js 35 bytes 16.16kB 0.22%
assets/vega-*.js -12.13kB 654 bytes -94.89%
assets/vega-*.js (New) 12.95kB 12.95kB 100.0% 🚀
assets/useEventListener-*.js -695 bytes 12.5kB -5.27%
assets/run-*.js 2 bytes 9.75kB 0.02%
assets/config-*.js 214 bytes 6.65kB 3.32%
assets/scratchpad-*.js 2 bytes 8.46kB 0.02%
assets/utils-*.js -5 bytes 6.37kB -0.08%
assets/utils-*.js -26.85kB 287 bytes -98.94%
assets/skeleton-*.js (New) 4.5kB 4.5kB 100.0% 🚀
assets/error-*.js -1.09kB 1.86kB -36.84%
assets/error-*.js (New) 2.95kB 2.95kB 100.0% 🚀
assets/mermaid-*.core-Dz2GMGqQ.js (New) 2.38kB 2.38kB 100.0% 🚀
assets/use-*.js -1.19kB 617 bytes -65.87%
assets/use-*.js (New) 1.81kB 1.81kB 100.0% 🚀
assets/objects-*.js (New) 751 bytes 751 bytes 100.0% 🚀
assets/constants-*.js 89 bytes 740 bytes 13.67% ⚠️
assets/formats-*.js 2 bytes 264 bytes 0.76%
assets/__vite-*.js -5 bytes 93 bytes -5.1%
assets/__vite-*.js 5 bytes 98 bytes 5.38% ⚠️
assets/react-*.browser.esm-CLyGMTsX.js (Deleted) -25.64kB 0 bytes -100.0% 🗑️
assets/hooks-*.js (Deleted) -4.04kB 0 bytes -100.0% 🗑️
assets/mermaid-*.core-D70sHJeJ.js (Deleted) -2.38kB 0 bytes -100.0% 🗑️
assets/globals-*.js (Deleted) -241 bytes 0 bytes -100.0% 🗑️

Files in assets/JsonOutput-*.js:

  • ./src/components/charts/lazy.tsx → Total Size: 256 bytes

Files in assets/reveal-*.js:

  • ./src/components/slides/reveal-component.tsx → Total Size: 23.41kB

Files in assets/vega-*.js:

  • ./src/components/charts/vega-embed-container.tsx → Total Size: 793 bytes

Files in assets/vega-*.js:

  • ./src/plugins/impl/vega/vega-component.tsx → Total Size: 6.7kB

Files in assets/use-*.js:

  • ./src/plugins/impl/vega/use-vega-container-remeasure.ts → Total Size: 1.36kB

@Light2Dark
Light2Dark merged commit f41d52c into main Jul 22, 2026
42 checks passed
@Light2Dark
Light2Dark deleted the fix/vega-container-remeasure branch July 22, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants