You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 92feb24
Browse filesBrowse the repository at this point in the historyBrowse files
perf(workflow): scope resize CSS-var writes to the container, not :root (#5738)
* perf(workflow): scope resize CSS-var writes to the container, not :root
Resizing the editor panel, terminal, output panel, and sidebar was still
laggy on large workflows even after the drag handles stopped re-rendering
React per frame. A CDP trace showed the cost was style recalculation, not
JS or layout: ~3.9s of Document::recalcStyle over a 50-move panel drag.
Root cause: each drag frame wrote its CSS variable to document.documentElement.
On a large document (~42k elements) any inline custom-property write on the
<html> root recalculates style for the whole tree — measured at ~77ms per
write, independent of what actually reads the variable (an unused var costs
the same). Writing the same variable to the element that consumes it recalcs
only that subtree (~0.5ms) — a ~150x reduction.
useDragResize now writes the variable to a caller-provided target element
during the drag and reconciles to :root once on release (so on-demand readers
and the pre-hydration script are unchanged): panel -> .panel-container,
terminal -> .terminal-container, output panel -> .terminal-container (both
consumers inherit it), sidebar -> .sidebar-shell-outer. The terminal's
expanded-threshold sync writes store state directly instead of setTerminalHeight
so it no longer touches :root mid-drag.
Measured (near-empty canvas, 50-move drag): panel style+layout 3891ms -> 56ms,
frame p95 91.6ms -> 8.4ms, main-thread blocking 4566ms -> 0ms; terminal
recalc 3899ms -> 16ms, blocking 5558ms -> 0ms; sidebar recalc ~77ms/frame -> ~1ms/frame.
* perf(workflow): keep float boundary-sync live during scoped resize drags
The resize hooks now write their CSS variable to the consuming container
element during a drag (not :root), so use-float-boundary-sync's MutationObserver
on :root no longer fired mid-drag and open floats (chat, search-replace,
variables) only re-clamped on release. Read each boundary dimension from its
scoped element with a :root fallback, and observe the container elements as
well as :root, so an open float tracks the drag live exactly as before.
* fix(workflow): finalize drag on unmount + clamp reads scoped output width
- useDragResize: unmounting mid-drag now runs endDrag (commit + drop the
scoped override) instead of a bare cleanup, so navigating away can neither
lose the resize nor strand an inline override on a surviving target element.
- terminal output-panel clamp: read the live --output-panel-width from the
terminal element first (where a drag writes its scoped override), then :root,
then the store, so a mid-drag terminal/window resize can't clamp against a
stale value.
* fix(workflow): robust drag finalize — last-applied value, sidebar unmount, clamp skip
Addresses three review findings on the scoped-resize change:
- useDragResize: track the last applied value and commit that on release;
only recompute from the pointer event while the target is still connected.
On an unmount the target's rect can be detached, so a layout-reading compute
(e.g. the output panel's) would return a degenerate MIN — committing the last
shown value avoids persisting the wrong width, and keeps flick-safety on a
normal release.
- use-sidebar-resize: finalize on unmount (run endDrag, not bare cleanup) so a
drag interrupted by unmount persists the width and drops the scoped override.
This matters more than for the panel/terminal because .sidebar-shell-outer
lives in the workspace chrome and outlives the sidebar, so a stranded override
would win over :root.
- terminal output-panel clamp: skip while an output-panel drag is active (its
scoped inline override is present). That drag's own compute clamps every frame
against the live terminal rect, and a store-driven :root write here would be
masked by the inline override anyway.
* fix(workflow): sidebar flick-safety + clamp reads committed :root width
- use-sidebar-resize: compute the clamped width synchronously on each pointer
move (storing lastWidth) and defer only the DOM write to rAF, so a fast flick
released before the frame runs still commits the final pointer position
instead of a stale frame or nothing.
- terminal output-panel clamp: when not mid-drag, read the committed
--output-panel-width from :root (written synchronously by the store setter)
rather than the React store value, which lags a render behind the commit;
fall back to the store before any commit. Comment corrected to match.
0 commit comments