fix(core): re-clamp the held resizable size when its bounds move - #5256
Draft
cixzhang wants to merge 1 commit into
Draft
fix(core): re-clamp the held resizable size when its bounds move#5256cixzhang wants to merge 1 commit into
cixzhang wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
useResizable applied minSizePx/maxSizePx at initialization and on every set path, but never to the size it was already holding. A region whose maximum is derived from available width kept a size that became illegal the moment that maximum dropped. The held size now follows the band when the band moves under it, in one direction only: outside the band it is corrected in, and a band that widens again leaves it alone. The correction happens during render, so the out-of-band size is never committed, and it reports through onSizeChange like any other size change.
cixzhang
force-pushed
the
fix/resizable-reclamp-on-bounds-change
branch
from
August 20, 2026 17:22
a3fbf8d to
83a9eb2
Compare
Contributor
PR Analysis Report📚 Storybook PreviewView Storybook for this PR 🧪 Sandbox PreviewView Sandbox for this PR Modified ComponentsResizable (@astryxdesign/core) · View in Storybook
Bundle Size Summary
Accessibility AuditStatus: No accessibility violations detected. Generated by PR Enrichment workflow | Storybook | Sandbox | View full report |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
useResizableappliesminSizePx/maxSizePxwhen it initializes and on everypath that sets the size, but never to the size it is already holding. When the
band itself moves — a resizable side region whose maximum is derived from the
width available to it — the region keeps a size that has become illegal, and the
bound the hook exists to guarantee is silently violated.
Measured in a real browser on a story whose
maxSizePxis half its container,with the panel driven out to the ceiling at a 1400px viewport:
aria-valuemax)At a 700px viewport the panel is 350px past its own ceiling: it covers the whole
shell and the content region is gone.
ResizeHandlereports it faithfully —aria-valuenow=667againstaria-valuemax=317, a value outside its own range.The fix, and the asymmetry that makes it safe
The held size now follows the band when the band moves under it, in one
direction only:
band;
Growing back is what the viewer's choice looks like once the ceiling has moved.
A symmetric re-clamp would restore the pre-clamp size and the region would
rubber-band in and out as a window is dragged; the last row of the table is the
test for that, and it is the one a naive version fails.
The correction runs during render rather than in an effect, so the out-of-band
size is never committed: React re-runs the hook before the commit, nothing
paints at the illegal size, and no observer in the same commit sees it.
The four decisions this raised
snaps— reuseclampSize, don't invent a second rounding rule. Withsnap points the correction lands on the nearest snap inside the new band
(
[100, 300, 500], ceiling drops to 400 → the region rests at 300, not 400).Where no snap fits under the ceiling, the ceiling wins and the region rests off
a snap — which is exactly what
clampSizealready does on the drag path. Theband is a hard constraint; snaps are a preference. One definition of "legal
size" for every path.
onSizeChange— fires. The name says the size changed, and it did. Aconsumer mirroring the size into its own state (a stored width, a label beside
the panel) that does not hear this renders a size the region does not have.
It is delivered as an effect, so the callback is never called during render.
A collapsed region — untouched. Its zero is deliberate, not a size that
drifted out of band, and clamping zero into
[min, max]would silently expand aregion the viewer closed.
expand()already applies the current band when itrestores the pre-collapse size, so the collapsed path was never the leak.
autoSaveId— the clamp is persisted. The alternative is remembering thepre-clamp size and restoring it on reload, which is the rubber-band again with a
page load in the middle: the session already settled that the widened band does
not restore the size. One notion of current size, and it is the one that
persists.
Risk
Behavior only changes for a region whose
minSizePx/maxSizePxactually changeafter mount. Fixed bounds — every configuration in the stories, showcases and
templates — take an identity comparison per render and nothing else.
Testing
New colocated tests for the hook cover both directions,
snaps, the collapsedpath,
onSizeChange, persistence and multi-region; the 20 existingResizeHandletests still pass. Verified in Chromium against local Storybookwith the numbers above; screenshots at 700px show the content region restored.