Fix Block Settings sidebar unexpectedly collapsing #34543
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Peek.2021-09-02.13-49-wporg-settings-move.mp4
In this video, I visit the widgets area, pick a block, visit the Block Settings area, make a change and publish. So far, all is well. Note the publish button is now disabled. Now I visit the Block Settings area and make another change. I intend to stay in the area, but I am sent back to the paragraph block. This can be disrupting if you are intending to make several changes in the Block Settings area but you're unexpectedly sent out of the area.
Now we can discuss the exact circumstances that cause the bug to happen. In this video, when I make a change the second time and I'm sent back, the publish button is also moving from disabled to enabled. Being sent back is a side effect of this change.
How often the bug happens depends on the active theme's capabilities. There are two cases:
customize-selective-refresh-widgets
: The bug only happens when the publish button moves from disabled to enabled. Thankfully, most modern themes, including the defaults like twentynineteen, twentytwenty, and twentytwentyone have this setting.customize-selective-refresh-widgets
: The bug happens whenever making a change in the block settings area, making it more disruptive. These are older themes and some custom themes.Now, to discuss the mechanism and why it happens. The root cause is the customizer running
reflowPaneContents
, which means it takes some time to figure out what should and shouldn't be visible.At one point, all panels and sections run through this little bit of code, which figures out if they're active, and then calls
onChangeActive
accordingly. What's happening in this case is that it incorrectly determines the Block Settings section is not active, and calls.onChangeActive( active=false, args )
, even though that section is up front and I am interacting with the controls in that section. This ends up calling this.collapse()
call, which moves me out of the section. And this block is entered because active is false (but it should be true).So why is active false? Let's go back to the block that is figuring out the active value. For the Block Settings Sidebar, it is actually considering two active values and needs them to both be on: see this line of code. The first
active
, is coming from a function argument, and in the case of the Block Settings section which I am interacting with, istrue
and is totally fine. What's happening is the second check, thecontainer.isContextuallyActive()
is always returning false, which in turn setsactive
to be false, and causes the section to collapse.What is
isContextuallyActive()
doing? Through the magic of inheritance, even though the Block Settings Sidebar is defined in gutenberg, its definition forisContextuallyActive()
comes from the base class in the customizer: default isContextuallyActive(). Here, it is calling.controls()
to look through all of the controls belonging to the section, checking if at least one is active. The problem is this is a customizer specific abstraction. Even though Gutenberg's Block Settings section has a number of controls, none of them are returned by.controls()
. It's just not a part of the integration that fits cleanly.So, my solution is to override
isContextuallyActive()
for the sections that are defined in Gutenberg, and have them only return if the section itself is active, while ignoring the.controls()
check. Note that this is not without precendent, as themes in the customizer had to do the same thing. This completely fixes the problem and stops me from unexpectedly being sent away from the block settings. It works in both cases of the theme supporting and not supportingcustomize-selective-refresh-widgets
as mentioned above.How has this been tested?
.wp-env.json
has"."
listed in pluginswp-env destroy && wp-env start
to create a clean WPTo test this branch, check it out,
npm run dev
, and redo the steps.To add debugging code in the customizer,
docker ps | grep wordpress | grep 8888 | cut -d' ' -f1
to get the container id, thendocker exec -it container_id /bin/bash
. Inside the container,apt update && apt install vim
, thenvim /www/html/wp-admin/js/customize-controls.js
.Screenshots
See Video
Types of changes
Bug Fix
Checklist:
*.native.js
files for terms that need renaming or removal).