Reset zoom level on component unmount#69087
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Do you know what part of the code disables zoomout mode for smaller screens? Controlling a global state-based component's mounted state is tricky and usually causes more bugs. This bug probably has a different root cause; I suggest finding it and fixing the issue there. |
|
Sure @Mamaduka, I’ll check what disables zoom-out on smaller screens and find the root cause. |
|
Hi @Mamaduka, The useLayoutEffect hook is triggered when the viewport width is at or above 782px. However, the condition: const isMediumOrBigger = window.matchMedia('(min-width: 782px)').matches;does not return false when the viewport width gradually decreases to exactly 782px. This is because the (min-width: 782px) media query does not include 782px itself it applies only to widths greater than 782px. As a result, when resizing the viewport slowly, the condition remains true even at 782px. However, when the viewport is resized quickly, bypassing the 782px threshold, the condition updates correctly and evaluates to false as expected. A fix to this would be to change code like: const isMediumOrBigger = window.matchMedia('(min-width: 783px)').matches;Or const isMediumOrBigger = window.width>=782;Screencast:Screen.Recording.2025-02-12.at.10.53.59.AM.movShould I open an issue about this also I am quite not sure which solution would be better. |
Mamaduka
left a comment
There was a problem hiding this comment.
Thanks for investigating this, @Infinite-Null!
I left a a couple of of notes, but unfortunately, I don't have time to test the proposed solution properly.
Pinging @WordPress/gutenberg-core in case someone has time to have a look.
| } = useDispatch( editorStore ); | ||
| const { get: getPreference } = useSelect( preferencesStore ); | ||
| const registry = useRegistry(); | ||
| const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); |
There was a problem hiding this comment.
The useDispatch( blockEditorStore ) is also defined above. Let's move and combine them in single call.
| const { get: getPreference } = useSelect( preferencesStore ); | ||
| const registry = useRegistry(); | ||
| const { resetZoomLevel } = unlock( useDispatch( blockEditorStore ) ); | ||
| const { isZoomOut } = unlock( select( blockEditorStore ) ); |
There was a problem hiding this comment.
The components shouldn't use global select it doesn't react to store changes.
| const { isZoomOut } = unlock( select( blockEditorStore ) ); | |
| const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); |
|
Hi @Mamaduka, |
I'm trying to reproduce this issue on the trunk branch (ce2a651), but for some reason I can't reproduce it.
Returning it to a wider width will restore the zoom out canvas correctly 🤔 Can you still reproduce this issue in your environment? 8d267d3f50f3ea45b90a09fe75b904b3.mp4 |
|
@t-hamano, Thank you for looking into the issue: Site Editor:Screen.Recording.2025-02-17.at.6.08.07.PM.movBlock Editor:Screen.Recording.2025-02-17.at.6.08.41.PM.movSorry for adding the following to the testing instructions: I have correctly updated the testing instructions in the PR description now! |
|
After looking into this issue in detail, I found that this issue first occurred in #67481. This means that I believe that the Try changing the browser width with the zoom out mode enabled. You should see that the value indicated by I haven't looked into it in detail yet, but I think that the fundamental solution would be to fix the |
|
Hi @t-hamano, As far as I understood, The trigger variable in this In the Site Editor, when we resize the browser window to When looking at the The logic in this hook is actually correct, but here's what happens:
I am unable to find what is causing this mount and unmount in case of Screencast:If
|
|
I found the reason for the mounting and unmounting of the site editor. It is because if this particular condition . Rather than making changes for mounting and unmounting of site editor, I think adding condition would be the ideal choice here: I would really appreciate your opinion and help on this @t-hamano. |
|
@Infinite-Null sorry for the late reply. In my testing, the problem seems to be resolved in the latest Gutenberg. After resizing the browser width from a smaller width to a larger width, the zoom effect persists. Can you also check on your side? 352506f103b41aa90253041d14bb7d24.mp4 |
|
Hi @t-hamano, I revisited this issue and was able to reproduce it successfully. I’ve attached a screencast for reference. Steps to reproduce:
Screen.Recording.2026-05-20.at.9.11.07.PM.movFYI: I have also resolved the merge conflict for the PR. |
|
@Infinite-Null Thanks, I was able to reproduce the issue in the site editor as well. My investigation suggests that the site editor uses different Editor instances for mobile and desktop use, and there's a bug in the logic of Wouldn't this change simply solve the problem? diff --git a/packages/block-editor/src/components/iframe/use-scale-canvas.js b/packages/block-editor/src/components/iframe/use-scale-canvas.js
index 63b03e48924..01bb4e67831 100644
--- a/packages/block-editor/src/components/iframe/use-scale-canvas.js
+++ b/packages/block-editor/src/components/iframe/use-scale-canvas.js
@@ -312,8 +312,14 @@ export function useScaleCanvas( {
* changes due to the container resizing.
*/
useEffect( () => {
- const trigger =
- iframeDocument && previousIsZoomedOut.current !== isZoomedOut;
+ // Wait for the iframe document so a zoom out state that is already
+ // active on mount (e.g. when the canvas is remounted on a viewport
+ // change) is still detected as a transition.
+ if ( ! iframeDocument ) {
+ return;
+ }
+
+ const trigger = previousIsZoomedOut.current !== isZoomedOut;
previousIsZoomedOut.current = isZoomedOut; |
|
Hi @t-hamano, Thanks for the suggestion! I've applied the fix, and it correctly handles the case where the zoom-out state is already active on mount. Here's a screencast: Screen.Recording.2026-05-21.at.7.45.12.PM.movPlease take a look when you get a chance! |
t-hamano
left a comment
There was a problem hiding this comment.
LGTM! I believe this is the ideal approach.
What?
Closes #69086
Reset zoom level when editor component unmounts to prevent stale zoom states.
Why?
The zoom state and button remained active after responsive changes, causing inconsistency between the visual zoom effect and the button state. This led to a confusing user experience in which the zoom button appeared pressed, but no zoom effect was visible.
How?
Added a cleanup effect in the ZoomOutToggle component that calls resetZoomLevel when the component unmounts. This ensures the zoom state is properly reset between editor sessions and responsive changes.
Testing Instructions
Screencast
Screen.Recording.2025-02-07.at.12.27.40.PM.mov