Saving workspace scroll accurately when hiding (and showing) toolbox

128 views
Skip to first unread message

Jing An Tew

unread,
Nov 10, 2025, 11:20:48 PMNov 10
to Blockly
Hi, I've implemented hiding/showing the toolbox, but the blocks shift too (poor UX).
Tried to programmatically scroll the workspace after the toolbox shift
However, as shown in the video (will be attached later as the message is too long or smth), the approach is unreliable after scrolling the workspace?

Thanks.

Jing An Tew

unread,
Nov 10, 2025, 11:23:48 PMNov 10
to Blockly
Code used
Had to downscale the video so forgive the slight blurriness
Video Project 1.mp4
code.png

Jing An Tew

unread,
Nov 13, 2025, 9:25:38 AMNov 13
to Blockly
Does anyone from the Blockly team have any ideas what's happening here?

fu6...@gmail.com

unread,
Nov 13, 2025, 9:55:09 PMNov 13
to Blockly
Hi,

I am sharing the implementation I currently use to effectively show/hide the category toolbox while maintaining the block display position. This code has been working successfully for my block-based platform.

I hope this is helpful to you.


zoomShowHideCategory(){
this.workspace.shiftAllBlocks = function(offsetX) {
this.scrollX = this.scrollX + offsetX;
this.scroll(this.scrollX, this.scrollY);
};

 var toolbox = this.workspace.getToolbox();
 var toolboxElement = toolbox.HtmlDiv;
 if (toolbox.isVisible_) {
  this.workspace.shiftAllBlocks(toolboxElement.offsetWidth);
  toolbox.setVisible(false);
 } else {
  toolbox.setVisible(true);
  this.workspace.shiftAllBlocks(-toolboxElement.offsetWidth);
 }
 this.workspace.resize();
};

Best regards,

fu6...

jinga...@gmail.com 在 2025年11月13日 星期四晚上10:25:38 [UTC+8] 的信中寫道:
Catagory.mp4

Jing An Tew

unread,
Nov 13, 2025, 11:29:40 PMNov 13
to Blockly
Hi, then maybe this is a Blockly issue? There is a slight change in your block position too when the workspace is dragged to the rightmost direction. See the attached video where I replicate the same behaviour in your workspace. It seems like past a arbitrary point blockly will shift blocks back into the workspace view.

Its way worse when I have my workspace in vertical mobile orientation. Even with code similar to yours there is still shifting. Going to have to try and figure out what exactly is happening.

Thanks for sharing your implementation.

Video Project 2.mp4

Ben Henning

unread,
Nov 18, 2025, 4:31:43 PMNov 18
to blo...@googlegroups.com
Hi,

I've tried to repro the same flow (that blocks far to the right of the workspace's center will auto move when hiding/showing the toolbox) with the core Blockly playground but haven't been able to. Are you able to repro this with just core Blockly (the latest v12 release) or does it require specific plugins and/or changes?

Thanks,
Ben

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/blockly/1444e338-24c9-4705-b745-90b8c379b028n%40googlegroups.com.
Message has been deleted

Jing An Tew

unread,
Nov 18, 2025, 9:58:33 PMNov 18
to Blockly
Hey Ben, 
Strange, the core Blockly playground (https://blockly-demo.appspot.com/static/tests/playgrounds/advanced_playground.html#debugEnabled=false) doesn't have this issue as well.
I'm just using core Blockly (v12.3.1), albeit in a React framework (Next.js). I have attached a short snippet of the code I use in my web app, as far as I know, I did not modify any Blockly specific behaviours.

showcase.txt
Code.module.scss

Ben Henning

unread,
Nov 19, 2025, 5:15:49 PM (13 days ago) Nov 19
to blo...@googlegroups.com
Hi,

I spent a little bit of time digging into this. I notice that you're doing a lot of possible modifications to the toolbox size and I'm openly wondering if that might be related to the observed problem, but I'm not certain. I tried reproing roughly the same steps again with one of Blockly's local playgrounds (toggling toolbox visibility and using 'Blockly.svgResize') but can't repro the issue. Watching the video again, however, it's starting to look to me like scrollCenter is being called for some reason:


I can't find an obvious reason why that might be, but it may be worth trying to step debug with a non-minified version of Blockly and see if that function is being called somewhere. I would be suspicious of extensions but I only see one (custom category) and it's not clear to me from the shared snippet if it's actually being used.

If that function isn't actually being called then I suggest taking one of the following two approaches to try and isolate the issue:
  • Start with a fresh simple application of Blockly and add to it until the issue returns.
  • Subtract from your existing project (removing project-specific pieces) until you can isolate the exact bit that's causing the issue. You can then try the first approach (a simple new project) and add the pieces you suspect are causing the issue to verify it.
A hybrid generally works best I think. If you can repro this with a simple Blockly project then we can probably provide more useful suggestions on what to do to try and mitigate the issue (or, if it's a Blockly problem, then we can make sure an issue gets filed to track fixing it).

Sorry this isn't a direct answer but I hope this at least helps provide suggestions on how to get toward one.

Best,
Ben

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Jing An Tew

unread,
Nov 19, 2025, 11:24:49 PM (13 days ago) Nov 19
to Blockly
Hi Ben, thanks for the comments.
I will start a new Blockly project using React to try to replicate this behaviour.
On another note, I seem to be able to reproduce this behaviour using the core Blockly playground. Notice how there's a arbitrary point where the blocks will be "forced" to scrolled back into the center.

The snippet I pasted into the developer console is here:
function toggleToolbox() {
  const width = 107; // found from inspect element
  const workspace = Blockly.getMainWorkspace();
  const toolbox = Blockly.getMainWorkspace().getToolbox();

  if (toolbox.isVisible_) {
    // close the toolbox and slide the workspace to the right by width
    toolbox.setVisible(false);
    workspace.resize();
    workspace.scroll(workspace.scrollX + width, workspace.scrollY);

  } else {
    // open the toolbox and slide the workspace to the left by width
    toolbox.setVisible(true);
    workspace.resize();
    workspace.scroll(workspace.scrollX - width, workspace.scrollY);
  }

  console.log("After Move:");
  console.log(workspace.scrollX, workspace.scrollY);
}

I've attached a video here showcasing the above. I'm guessing, Blockly seems to be able to compensate when the block is moved into the space where the toolbox will exist, but when moved to the extreme right, maybe the block extends past some invisible boundary and is forced to move back to the center. Hopefully this video is more illustrative of the issue.

Regards,
Jing An


Ben Henning

unread,
Nov 20, 2025, 3:28:40 PM (12 days ago) Nov 20
to blo...@googlegroups.com
I see. Both the isolated code and video repro are very helpful. If I am understanding correctly (I probably should have clarified this earlier), your goal here is ultimately to stop the blocks moving? You mention that being bad UX--I'm not 100% sure I agree with that, but I suppose that's a different discussion from trying to reach your actual goal.

What you're seeing isn't actually the blocks moving but, rather, the 'camera'/'viewport' within the Blockly workspace (though it's not actually represented using these terms). How the view position needs to change depends largely on the workspace, and I suspect it's ultimately tied to the resize functionality. Observation suggests that attempting to resize the workspace includes some additional logic to make sure that:
  • If a block is under the toolbox then the view should be shifted over so that it isn't.
  • If a wide block is slightly off screen then shift so that it isn't.
This experiment can actually be tested interestingly in a few ways:
  • Only changing toolbox visibility doesn't move blocks at all (which is ultimately your goal, but you may have other reasons why the workspace resize is needed). You can hide the toolbox, move a block under it, show it, observe the block hasn't moved, call 'Blockly.svgResize', then observe the block has moved.
  • Try your same repro steps but put a copy of the large block on each side of the screen and then use your function. Notice that the blocks barely (if at all) move because both side constraints are trying to apply at the same time and they can't be resolved since shifting to make one side of the screen better makes the other worse.
Here's why this is tricky: resizing the workspace ensures that the workspace now knows the space underneath the toolbox can be used. If you only hide the toolbox then you may observe that the workspace won't let you drag anything underneath it. This is ultimately the way core Blockly is designed to behave. The reason why the resize logic is ultimately what causes this to happen is because that's when the toolbox's width and height are recalculated which, in turn, affect how the view metrics for an item like a block are calculated:


Simply put, the workspace treats the non-toolbox region as the place where blocks are allowed to go while on screen. Removing the toolbox and resizing the workspace provides a larger area for blocks to be, and re-adding the toolbox causes that area to shrink. Blockly then shifts the blocks to ensure they stay on screen because it makes an effort to try and ensure that the workspace origin (0, 0) is never under the toolbox. The reason for this apparently dates all the way back to the very first import of Blockly into Git, so its original reasoning may well be lost to time. :)

I suspect you ultimately don't actually care about how the machinery works. What you're really interested in is stopping the view adjustment to get blocks back on the screen without ignoring the toolbox's impacts on workspace size. Since this is largely an opinionated perspective I don't think it constitutes an actual issue in core Blockly, but it's perhaps a reasonable thing to want to be able to do. To see how that works we need to dig a bit into what can lead to scrolling:
In fact, this is exactly the line that, when commented out, fixes your problem:


Now core Blockly doesn't actually allow you to disable that readjustment logic. However, it does allow you to swap out the metrics function entirely per: https://github.com/RaspberryPiFoundation/blockly/blob/91ef951e92576a090aea7c675bafd37a93ac369a/core/workspace_svg.ts#L370-L371. Now as far as I can tell there isn't an explicit developer documentation page on using this, but you may find references in blockly-samples plugins (I haven't actually checked), or just by following what core Blockly does for recalculating metrics and skipping the extra translation step.

I hope this helps.
Ben

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Jing An Tew

unread,
Nov 20, 2025, 9:21:41 PM (12 days ago) Nov 20
to Blockly
Hi Ben,
The original goal was to "stop the blocks moving" as I was trying to implement a more mobile-friendly interface to hide the toolbox to free up more space for the workspace.

"Try your same repro steps but put a copy of the large block on each side of the screen and then use your function. Notice that the blocks barely (if at all) move because both side constraints are trying to apply at the same time and they can't be resolved since shifting to make one side of the screen better makes the other worse. " 
Interesting, now that explains why my workspace can shift outside of the constraints ONLY and ONLY when there is a larger block that occupies the screen width.

"Simply put, the workspace treats the non-toolbox region as the place where blocks are allowed to go while on screen. Removing the toolbox and resizing the workspace provides a larger area for blocks to be, and re-adding the toolbox causes that area to shrink. Blockly then shifts the blocks to ensure they stay on screen because it makes an effort to try and ensure that the workspace origin (0, 0) is never under the toolbox. The reason for this apparently dates all the way back to the very first import of Blockly into Git, so its original reasoning may well be lost to time. :)"
Maybe another way would be to create a custom toolbox that is overlaid on the workspace instead of co-existing with the workspace.

I would definitely have to take a closer look at how Blockly works internally to implement it better within my existing codebase.
Thanks a lot for the help and in-depth explanation on how Blockly works internally.

Best Regards,
Jing An

Ronald Bourret (xWF)

unread,
Nov 21, 2025, 11:47:41 AM (12 days ago) Nov 21
to blo...@googlegroups.com

For a discussion of the metrics manager, see Metrics Manager.

For a discussion on how to replace the metrics manager, see Replaceable classes.
 
Ronald Bourret
Technical Writer (Provided by Synergis)


Ben Henning

unread,
Nov 24, 2025, 4:42:42 PM (8 days ago) Nov 24
to blo...@googlegroups.com
Thanks Ron.

For what it's worth I was considering linking to the metrics manager documentation, and it may well be the right way to approach this. That being said, WorkspaceSvg allows for direct customization on exactly the metric functionality needed to fix this issue, so it may also be the case that overriding MetricsManager could potentially be overkill. As far as I could tell this customization capability of WorkspaceSvg isn't documented anywhere, but it's possible I've missed it. In fact it's not even listed in https://developers.google.com/blockly/reference/js/blockly.blocklyoptions_interface.md so perhaps caution should be taken in using this route because it may not be something we guarantee continues to function like this in future versions of Blockly.

Reply all
Reply to author
Forward
0 new messages