Related
No open issue asks a corner drag to keep the image ratio. Issue 151 is closed. It covers Markdown import keeping image width and height. It is not this change.
What happened
This changes a documented default in the published package @docs.plus/extension-hypermultimedia. It needs a maintainer ruling on the release and the semantic version. The target is the next release of that package.
Edward Saperia reported this on 2026-09-26. When he resizes an image, the drag does not keep the aspect ratio. He wrote: "also, when I'm resizing an image, it doesn't maintain aspect ratio. pretty rare that I want that behaviour!"
What we expect
A corner drag on an image keeps the width and height in the same ratio. The minimum and maximum limits keep that ratio too. Shift is one candidate for free resize. The side-handle rule is a separate maintainer decision. The docs and the changelog match the ruling.
Steps to reproduce
- Open a pad you can edit.
- Insert an image that is wider than it is tall.
- Drag a corner handle without holding Shift.
- Read the width and the height.
Expected by the report: the ratio stays the ratio of the image before the drag. Current result: width and height each follow the pointer.
Findings
Read from the package source on 2026-09-29. Not re-run in a browser.
computeCornerBox in gripperDrag.ts locks the ratio only while Shift is held (state.isShiftPressed && state.aspectRatio). A plain corner drag sets width from the horizontal delta and height from the vertical delta. computeSideBox changes one axis only. Its comment says one axis, and no aspect ratio.
calculateAspectRatioDimensions lets the larger pointer delta drive the other axis. If the horizontal delta is larger, height becomes width divided by the ratio. If the vertical delta is larger, width becomes height times the ratio.
clampDimensionsToConstraints uses a minimum width of 160 and a minimum height of 80. Those two floors are separate Math.max calls. The maximum width comes from the editor column. fitDimensionsToBounds scales both axes together for that maximum. updateNodeDimensions runs the same clamp again when the drag commits. A ratio-locked drag can still break the ratio at a floor. A wide image that cannot reach the minimum width at its own ratio is one example.
The same gripper is MediaResizeGripper. The kit adds a node when resizeGripper is not false and the node name is not x. The nodes are image, video, audio, youtube, vimeo, soundcloud, spotify, and loom. The pad configure call does not turn any of those off. soundcloud and spotify raise the height floor above 80.
The docs state the current rule. src/nodes/image/README.md says hold Shift to lock the aspect ratio. docs/resize-and-loading.md says the same. docs/api.md has a Shift row for a corner drag.
cypress/e2e/resize/gripper.cy.ts encodes the current rule. The bottom-right corner test expects both width and height to grow. The side tests expect one axis.
The repo package version is 2.1.0. The [Unreleased] changelog section is documentation only. RELEASE_POLICY.md is still Phase 1, so this package can ship without the other four. Phase 2 lockstep is not on. A patch is a bug fix. A minor is a backward-compatible feature. A major is a breaking change. Highlights are mandatory for a minor or a major. [Unreleased] must become a real version heading before publish. This task does not cut that release.
Reference points
extensions/extension-hypermultimedia/src/extensions/decoration/gripperDrag.ts
extensions/extension-hypermultimedia/src/extensions/decoration/utils.ts
extensions/extension-hypermultimedia/src/hyperMultimediaKit.ts
extensions/extension-hypermultimedia/src/nodes/image/README.md
extensions/extension-hypermultimedia/docs/resize-and-loading.md
extensions/extension-hypermultimedia/docs/api.md
extensions/extension-hypermultimedia/cypress/e2e/resize/gripper.cy.ts
extensions/extension-hypermultimedia/CHANGELOG.md
RELEASE_POLICY.md
- Word picture size
- Notion images
- Google Docs crop and adjust
Word help says hold Shift while you drag a sizing handle to keep the proportions. To resize freely, turn off Lock aspect ratio. If height and width will not change on their own, clear that checkbox.
Notion help shows two guides, on the left edge and the right edge. Drag either guide to make the block bigger or smaller. That page does not mention a corner handle, Shift, or aspect ratio.
The Google Docs desktop page that was read covers crop, mask, border, and color. It does not state what a corner drag does to the ratio. Slack was not cited, because no Slack help page was read for this.
The corner default and the Shift gesture do not match across those pages. Word uses Shift to keep the ratio. The report asks for the opposite gesture. The maintainer picks one rule.
Acceptance criteria
Blocked by
None — can start now.
Agent brief
Type: HITL for the corner rule, the side-handle rule, the node scope, and the semantic version. AFK for the drag math, the docs, and the spec after that comment.
Category: enhancement
Current behavior: See Findings. A plain corner drag changes width and height independently. Shift locks the ratio. The minimum width and the minimum height can break a locked ratio.
Desired behavior: The maintainer's written rule. The proposal is that an image corner keeps the ratio, and Shift resizes freely. Limits keep the ratio. The rendered size matches the attributes.
Where to start: computeCornerBox and computeSideBox in gripperDrag.ts. clampDimensionsToConstraints and calculateAspectRatioDimensions in utils.ts. MediaResizeGripper acceptedNodes in hyperMultimediaKit.ts. gripper.cy.ts. Search by symbol. File names are hints as of 2026-09-29.
Rules that apply: extensions/CLAUDE.md §Hypermultimedia Extension. A resize spec asserts the rendered DOM size, not node attributes alone. Read the inline style width and height, or getBoundingClientRect on img. Update the image README and the package docs in the same change. RELEASE_POLICY.md and the release-extensions skill: put the behavior change under a real version heading, with Highlights if the bump is minor or major. Do not run a release step in the fix. Phase 1 lets this package ship alone. AGENTS.md §Test Policy allows the new spec, because it pins a reported behavior change.
Verify: Run the package clean-room resize specs after bunx tsup in extensions/extension-hypermultimedia. The new ratio spec must fail on the current drag and pass after the change. resize-undo.cy.ts and resize-stale-pos.cy.ts must still pass. In a pad, drag an image corner with and without Shift, in light and dark, and check the rendered box.
Related
No open issue asks a corner drag to keep the image ratio. Issue 151 is closed. It covers Markdown import keeping image width and height. It is not this change.
What happened
This changes a documented default in the published package
@docs.plus/extension-hypermultimedia. It needs a maintainer ruling on the release and the semantic version. The target is the next release of that package.Edward Saperia reported this on 2026-09-26. When he resizes an image, the drag does not keep the aspect ratio. He wrote: "also, when I'm resizing an image, it doesn't maintain aspect ratio. pretty rare that I want that behaviour!"
What we expect
A corner drag on an image keeps the width and height in the same ratio. The minimum and maximum limits keep that ratio too. Shift is one candidate for free resize. The side-handle rule is a separate maintainer decision. The docs and the changelog match the ruling.
Steps to reproduce
Expected by the report: the ratio stays the ratio of the image before the drag. Current result: width and height each follow the pointer.
Findings
Read from the package source on 2026-09-29. Not re-run in a browser.
computeCornerBoxingripperDrag.tslocks the ratio only while Shift is held (state.isShiftPressed && state.aspectRatio). A plain corner drag sets width from the horizontal delta and height from the vertical delta.computeSideBoxchanges one axis only. Its comment says one axis, and no aspect ratio.calculateAspectRatioDimensionslets the larger pointer delta drive the other axis. If the horizontal delta is larger, height becomes width divided by the ratio. If the vertical delta is larger, width becomes height times the ratio.clampDimensionsToConstraintsuses a minimum width of 160 and a minimum height of 80. Those two floors are separateMath.maxcalls. The maximum width comes from the editor column.fitDimensionsToBoundsscales both axes together for that maximum.updateNodeDimensionsruns the same clamp again when the drag commits. A ratio-locked drag can still break the ratio at a floor. A wide image that cannot reach the minimum width at its own ratio is one example.The same gripper is
MediaResizeGripper. The kit adds a node whenresizeGripperis not false and the node name is notx. The nodes areimage,video,audio,youtube,vimeo,soundcloud,spotify, andloom. The pad configure call does not turn any of those off.soundcloudandspotifyraise the height floor above 80.The docs state the current rule.
src/nodes/image/README.mdsays hold Shift to lock the aspect ratio.docs/resize-and-loading.mdsays the same.docs/api.mdhas a Shift row for a corner drag.cypress/e2e/resize/gripper.cy.tsencodes the current rule. The bottom-right corner test expects both width and height to grow. The side tests expect one axis.The repo package version is
2.1.0. The[Unreleased]changelog section is documentation only.RELEASE_POLICY.mdis still Phase 1, so this package can ship without the other four. Phase 2 lockstep is not on. A patch is a bug fix. A minor is a backward-compatible feature. A major is a breaking change. Highlights are mandatory for a minor or a major.[Unreleased]must become a real version heading before publish. This task does not cut that release.Reference points
extensions/extension-hypermultimedia/src/extensions/decoration/gripperDrag.tsextensions/extension-hypermultimedia/src/extensions/decoration/utils.tsextensions/extension-hypermultimedia/src/hyperMultimediaKit.tsextensions/extension-hypermultimedia/src/nodes/image/README.mdextensions/extension-hypermultimedia/docs/resize-and-loading.mdextensions/extension-hypermultimedia/docs/api.mdextensions/extension-hypermultimedia/cypress/e2e/resize/gripper.cy.tsextensions/extension-hypermultimedia/CHANGELOG.mdRELEASE_POLICY.mdWord help says hold Shift while you drag a sizing handle to keep the proportions. To resize freely, turn off Lock aspect ratio. If height and width will not change on their own, clear that checkbox.
Notion help shows two guides, on the left edge and the right edge. Drag either guide to make the block bigger or smaller. That page does not mention a corner handle, Shift, or aspect ratio.
The Google Docs desktop page that was read covers crop, mask, border, and color. It does not state what a corner drag does to the ratio. Slack was not cited, because no Slack help page was read for this.
The corner default and the Shift gesture do not match across those pages. Word uses Shift to keep the ratio. The report asks for the opposite gesture. The maintainer picks one rule.
Acceptance criteria
video,audio, and the iframe embeds follow the image rule. They sharecomputeCornerBox.widthandheightkeep the ratio. The rendered DOM size keeps the ratio too. Assert the rendered size, not only the attributes.cypress/e2e/resize/resize-undo.cy.tsandcypress/e2e/resize/resize-stale-pos.cy.tsstill pass.docs/api.md,docs/resize-and-loading.md, and the CHANGELOG match the ruling.Blocked by
None — can start now.
Agent brief
Type: HITL for the corner rule, the side-handle rule, the node scope, and the semantic version. AFK for the drag math, the docs, and the spec after that comment.
Category: enhancement
Current behavior: See Findings. A plain corner drag changes width and height independently. Shift locks the ratio. The minimum width and the minimum height can break a locked ratio.
Desired behavior: The maintainer's written rule. The proposal is that an image corner keeps the ratio, and Shift resizes freely. Limits keep the ratio. The rendered size matches the attributes.
Where to start:
computeCornerBoxandcomputeSideBoxingripperDrag.ts.clampDimensionsToConstraintsandcalculateAspectRatioDimensionsinutils.ts.MediaResizeGripperacceptedNodesinhyperMultimediaKit.ts.gripper.cy.ts. Search by symbol. File names are hints as of 2026-09-29.Rules that apply:
extensions/CLAUDE.md§Hypermultimedia Extension. A resize spec asserts the rendered DOM size, not node attributes alone. Read the inlinestylewidth and height, orgetBoundingClientRectonimg. Update the image README and the package docs in the same change.RELEASE_POLICY.mdand therelease-extensionsskill: put the behavior change under a real version heading, with Highlights if the bump is minor or major. Do not run a release step in the fix. Phase 1 lets this package ship alone.AGENTS.md§Test Policy allows the new spec, because it pins a reported behavior change.Verify: Run the package clean-room resize specs after
bunx tsupinextensions/extension-hypermultimedia. The new ratio spec must fail on the current drag and pass after the change.resize-undo.cy.tsandresize-stale-pos.cy.tsmust still pass. In a pad, drag an image corner with and without Shift, in light and dark, and check the rendered box.