Skip to content

refactor(Resizable): ResizeHandle's input moves into resizeGesture.ts - #9680

Merged
cixzhang merged 5 commits into
meta:mainfrom
vjeux:resize-handle-input-module
Nov 3, 2026
Merged

cixzhang merged 5 commits into
meta:mainfrom
vjeux:resize-handle-input-module

Conversation

@vjeux

@vjeux vjeux commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

The first pull request of the createResizable stack, split out of #9297. ResizeHandle's window splitter input moves into one module with no React, so the internal resize factory (#9297) and the ref form (#9370) can share it.

Maintainer impact

ResizeHandle held the pointer drag, the keys, Enter and the double-click in its own handlers. architecture:public-component-api INV22 has every public interaction hook delegate to a create…(element, options) factory (spec:AST-107 FR6), and useResizable's factory needs the same input. Moving the input first lets the factory reuse it instead of keeping a second copy, and lets this move be reviewed on its own.

Intended invariant

No public API or record change, and one behavior change. ResizeHandle's drag still holds its pointer, the arrow keys step 10px (50px with Shift), Home and End reach the bounds, Enter and a double-click collapse and restore, and the page's body gets the drag cursor.

The behavior change is a [fix] that restores what component:Resizable FR3 promises for the drag (spec:AST-017 FR5): a ResizeHandle whose resizable prop goes away mid-drag ends the drag as it does on unmount. It releases the page's cursor and text selection, and the region hears that its gesture is over.

Change

  • resizeGesture.ts holds the input. It reads a model of the region at each input, so a drag sees the region as it is now, and it takes pointer capture on any element with the capture API, an iframe's included.
  • ResizeHandle forwards its React events to it, over a model of the region its resizable prop describes.
  • A [chore] changeset records the move, and a [fix] changeset the mid-drag release.

Evidence

  • Failure before the change: a ResizeHandle that loses its resizable prop mid-drag keeps the page's resize cursor, and the region never hears that the drag ended. The test fails at the refactor commit.
  • Success after the change: that test passes after the fix commit.
  • Product/runtime behavior verified unchanged: the ResizeHandle, useResizable, Layout, SideNav and AppShell suites pass unchanged.

Scope

  • No intended public API, visual direction, or policy change. The behavior change is the one [fix] above.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

Local gates at df1bb8f, on main d0b6e0f (the head, fde4ded, changes only three comments on top of it): unit tests (test:ui, 18,330 passed), check:repo, check:i18n-runtime, check:knowledge, check:changesets, check:sync, strict lint (0 errors), root build then typecheck, the core API report regenerated from this build (it differs from main's committed report only by main's own drift: the hashed --x1ue0wla, which #9602 renamed without regenerating the report), the node project (16,034 passed), the docsite build and tests (774 passed), the Storybook build, accessibility in Chromium (88 passed), SideNav's rail motion in Chromium (10/10), and the accessibility audit of Resizable, SideNav and Layout (0 new) and of every story (0 new). The branch merges cleanly with main e70d5dc, which changes no Resizable, Layout or SideNav source.

vjeux added 4 commits November 2, 2026 15:35
The window splitter's input, the pointer drag that holds its pointer,
the arrow keys, Home, End, Enter and a double-click, and the body's drag
cursor, moves out of ResizeHandle into resizeGesture.ts, a module with no
React. ResizeHandle forwards its React events to it, over a model of the
region its resizable prop describes, read at each input. The gesture
takes pointer capture on any element with the capture API, a handle in
an iframe or a popup included. Behavior is unchanged, and a [chore]
changeset records the move.
…ag ends the drag

A ResizeHandle that loses its resizable prop in the middle of a drag
keeps the page's resize cursor and text selection, and the region never
hears that its gesture is over. It fails here.
…g ends the drag

The handle ends the drag as it does on unmount: it releases the page's
resize cursor and text selection, and the region the drag started on
hears that its gesture is over. A [fix] changeset records it.
… warns about its axis through useDevWarning

With the input in resizeGesture.ts, ResizeHandle has one gesture, so it
keeps no aliases that name a second path: gesture, isDragging and
isDisabled say what they are. The warning for a direction that disagrees
with the region's axis goes through useDevWarning, which already warns
once per mount; its message is unchanged.
@vercel

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 3, 2026 4:30am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 3, 2026
@astracat-bot

astracat-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 3, 2026, 4:38 AM UTC

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · fde4ded

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC Visual · A11y · RTL
ResizeHandle 19.2 kB (+488 B) · 4.0 kB CSS (0) — ✓ · ✓ · ✓
SideNav 63.8 kB (+363 B) · 10.9 kB CSS (0) — — · — · —

Package size: @astryxdesign/core 5.91 MB packed (+3.0 kB); no new dependencies.

API changes: none in this pull request

Committed API report behind this build: core 1 row; run pnpm api:report.

Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ready to approve: moving ResizeHandle's input into resizeGesture.ts keeps the pointer drag, arrow keys, Home, End, Enter and double-click working as before, and the mid-drag fix restores the Resizable contract that a drag's final size reaches storage once when the drag ends or is cancelled.

Nothing blocks. Three optional comment-style suggestions are inline: a JSDoc that restates step, a pointer-capture explanation repeated in three places, and one long two-topic sentence.

[Automated review]

return ahead[Math.min(count, ahead.length) - 1];
}

/** One step of a gesture: start, move by `delta`, end. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional (comment style): this JSDoc restates the three lines of step. The name and the body already say it, so the comment can go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed in fde4ded.

Comment on lines +225 to +227
// Take the pointer for the whole gesture. Without capture the browser
// re-hit-tests every move, so a frame anywhere under the drag path
// swallows the rest of it into the guest document.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional (comment style): this repeats the pointer-capture reason from createResizeGesture's JSDoc above and from the ResizeHandle header. Keeping it once, in the JSDoc, is enough; "swallows the rest of it" is also an idiom the comment style avoids.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed in fde4ded; the reason stays once, in createResizeGesture's JSDoc.

Comment on lines +477 to +479
// the region measures percentage bounds on the other. `ResizableProps` is
// exported, so `_direction` is optional for old hand-built objects; absent
// means there is no region axis to compare, not that it is horizontal.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional (comment style): the second sentence carries two topics in about 26 words. Suggested:

// `ResizableProps` is exported, so `_direction` is optional for old
// hand-built objects. Without it there is no axis to compare.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Taken in fde4ded, with your wording.

…say less

The JSDoc on step restated its three lines, and the comment at the
pointer capture repeated the reason createResizeGesture's JSDoc gives, so
both go. The axis warning's comment keeps one topic per sentence.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ready to approve: moving ResizeHandle's input into resizeGesture.ts keeps the pointer drag, arrow keys, Home, End, Enter and double-click working as before, and a handle whose resizable prop goes away mid-drag now releases the page cursor and lets the region save the dragged size, as the Resizable contract requires.

Nothing blocks, and the three comment suggestions from the earlier review are addressed.

[Automated review]

@vjeux
vjeux marked this pull request as ready for review November 3, 2026 04:40
@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 3, 2026
@cixzhang
cixzhang marked this pull request as draft November 3, 2026 05:20
@cixzhang
cixzhang marked this pull request as ready for review November 3, 2026 05:20
@cixzhang
cixzhang merged commit 30bae0c into meta:main Nov 3, 2026
190 of 201 checks passed
@vjeux
vjeux deleted the resize-handle-input-module branch November 3, 2026 07:44

This branch was successfully deployed

1 active deployment
Preview — fde4dedb Deployed Nov 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants