Skip to content

feat: scroll constraints refactor#720

Open
barnabasmolnar wants to merge 26 commits into
dwelle:masterfrom
barnabasmolnar:barnabasmolnar/snap-free-scroll-constraints
Open

feat: scroll constraints refactor#720
barnabasmolnar wants to merge 26 commits into
dwelle:masterfrom
barnabasmolnar:barnabasmolnar/snap-free-scroll-constraints

Conversation

@barnabasmolnar
Copy link
Copy Markdown

Real flesh & blood human summary. A bit lengthy but more context:

This PR is a refactor of the scrollConstraints feature. Its main aims are as follows:

  • get rid of snapping behaviour inherent to the original implementation (video of the phenomenon below)
  • extend scrollToContent() with an optional scrollLock mode (especially useful for presentations on E+)
  • disable reset/fit zoom actions and hotkeys while scrollConstraints are set
539244896-6ac91709-6fb7-44ba-a96a-28357384e340.mp4

This behaviour occurs, as far as I can tell, because zooming in non-centre points can easily produce a state in which the constrained area will go out of bounds of the viewport. When you place your mouse cursor somewhere in the scene, that essentially becomes your zoom anchor. In a normal, non-constrained scenario, that's perfectly fine. Here, we have to recalculate the constraints on every zoom level in order to keep the constrained area in the viewport. The original implementation does this in the following way:

  • it allows normal zooming at the anchor (=your cursor)
  • if the result is an out of bounds state, it then corrects it by yanking it back after a small delay (200ms)

My proposed solution for this is to adjust the zoom anchor when a zoom would otherwise produce an out-of-bounds state. This does mean that your mouse cursor will not always be the true anchor for zooming. Initially, I was somewhat worried that it would feel unnatural. But after playing around with it for quite a while, I'm finding this much more preferable and natural to the snapping/yanking back behaviour demonstrated in the video.

These changes will enable the following use cases:

  • During live and readonly shared presentations, users will be able to zoom in on slides. Very useful for those on smaller screens and/or viewing smaller details, reading small text, etc. Zooming and panning will be, of course, constrained to the active slide's dimensions, no zooming or panning will be allowed outside of it.
  • Readonly links can similarly take advantage of this feature. Currently you have two choices: 1) allow interaction and thus zooming/panning but this will be for the entire scene 2) disable interaction, but then you're at the mercy of your screen size & aspect ratio of how much you'll be able to see of the selected area. With this feature, you can "disable interaction" (a more apt label might be needed here) yet still allow zooming and panning inside the selected, constrained area but not outside of it.
  • Marketplace readonly editor will be able to use it to display library items on library pages.

An example of the presentation use case can be seen in this video:

Code.Q0cqgjsfrq.mp4

AI Summary of changes, short and sweet

This PR adds an opt-in way to lock scrollToContent() to the content it just framed, and it also improves scrollConstraints so constrained zooming/panning feels stable instead of snapping the viewport around when the zoom anchor would otherwise move the camera out of bounds.

What changed

  • scrollToContent() now supports an optional scrollLock mode
  • locked scrollToContent() derives its constraints from the same viewport calculation used to frame the target content
  • scrollConstraints now keep the viewport stable by adjusting the zoom anchor when a zoom would otherwise produce an out-of-bounds state
  • reset/fit zoom actions are disabled while constrained scrolling is active

Why

For presentations, host apps often need to:

  1. move to a frame
  2. fit it into the viewport
  3. keep the viewer constrained to that frame

Before this change, host apps had to combine scrollToContent() and setScrollConstraints() manually, which could lead to race conditions and slightly mismatched zoom levels.

At the same time, constrained zooming could feel janky because zooming near the boundary could pull the viewport away from the user’s intended focus. This happened because the previous implementation first applied the normal zoom anchor and only then corrected the viewport back into bounds, which could result in visible snapping near the edges of the constrained area.

This PR makes that flow much smoother:

  • scrollToContent() can now frame and lock in one step
  • constrained zooming behaves more naturally near the edges of the allowed area
  • viewport-changing zoom shortcuts no longer temporarily escape the constrained area

dwelle and others added 26 commits March 12, 2026 13:47
export actions

temp: force production build
fix: exported css variables not compiled into editor

autorelease fix
* Allow clicking links in non-interactive mode.

* better embed ux when interactivity=false

---------

Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
@barnabasmolnar barnabasmolnar changed the title scroll constraints refactor feat: scroll constraints refactor Mar 19, 2026
@dwelle dwelle force-pushed the master branch 3 times, most recently from 75e6d68 to 3ef8ea0 Compare May 12, 2026 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants