-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slot/Fill: Add a constrained version #14408
Conversation
Ignore the React upgrade changes as these were cherry-picked, the PR is not merged yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this (good example of using the new React hooks api as well). What's not immediately clear to me is:
- Is this intended to eventually replace the existing
createSlotFill
? - If not intended to eventually replace, what criteria determines when the new constrained slot fill is used vs the original
createSlotFill
? I realize the use-case currently is allowing for multiple editor instances, but that appears to me to indicate this might eventually deprecate the use ofcreateSlotFill
?
useEffect( () => { | ||
dispatch( { type: 'add', key: instanceId, children } ); | ||
return () => dispatch( { type: 'remove', key: instanceId } ); | ||
}, [ instanceId, children ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I realize it's not needed (because it's "guaranteed" to be static), convention seems to be to include dispatch
as a dependency here. Should we included it along with [ instanceId, children ]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right 👍 Seems like a good thing to add.
I think this new version is a bit superior in terms of API (and even simplicity of the implementation). The problem is that we can't remove the old one (BC) so we might have to support both even if we update all of our current slots with the new API. |
571a2e0
to
90388ec
Compare
My reading of this must be wrong, since it seems we want certain fills within an embedded editor (i.e. inspector controls) to reach outside into the one slot rendered by the parent editor. Or, at least, there should be at most one slot of this given name. Which, based on your further remarks and specifics notes about inspector controls, sounds like it's what you've implemented here? I'm not in a well-adjusted mindstate to delve into this now, but wanted to at least remark on it. I could have sworn something like this had been considered with previous efforts for the embedded reusable blocks editor (#7453), but I can't find but a few mentions of it, no implementations.
|
So, yes but we don't want them to reach it directly. With this PR, we'll be using a "Slot" for the inner inspector inside a "Fill" for the parent block inspector "Slot". Maybe it's confusing at the moment, but I can go ahead, cherry-pick and implement it in the other PR to clarify. |
After testing this in #14367 I'm having some issues:
|
This also makes me wonder if we shouldn't always use "bubblesVirtually". Doing so means when we do things like |
Anyway, I'd appreciate some thoughts because I feel like I'm going on a rabbit hole and not sure what's the path forward. |
I think generally yes, Edit: I may have read your comment as proposing the opposite of what I thought (i.e. are you suggesting we don't use the virtual bubbling?). I still think that |
I need to look closer at this, but I wonder: Why are there two of each slot? If we'd just render the one (in the top editor), wouldn't those fills rendered in the embedded editor find their way correctly to the sidebar inspector controls? That's what we want, isn't it?
Can you expand on this? I guess as I see it, the fills would be coordinated by whichever closest |
You read right! I was proposing we only use bubblesVirtually. but I'm not certain how much work this involves as we have a lot of DOM tree related behaviors.
That's not the direction I was going, I was trying to use two provides and two slots and render the inner Slot inside the parent fill to cascade. but rendering a Slot inside a Fill don't work unless we use "bubblesVirtually" in my testing. |
This would be a solution (alternative in the precedent comment) but the alternative I was trying to implement is more "controlled" for example, it would allow us to say: the inner inspector could go in a modal while the outer one stays at its position, we could have had more "control" |
A question I might have then is: Do we need it now? And even for hypothetical other usages of a Block Editor, the current behavior could still support placing inspector controls in a modal, just not a combination of differing placements for nested editors. To this end, I might wonder if we need it ever (is there some proposal for a varying placement slot?). |
There are discussions here and there. Customizer inspector, widgets... but not specifically reusable blocks. I agree that if we can solve the reusable blocks issue without this, we can move forward and rethink this when needed. |
In my work related to #14367, I've been running into similar issues to what's considered here. While I'm still inclined toward the idea of a single In this scenario, either we:
The first option would lead down a path toward something more like what's explored in this pull request. In my mind though, I'm wondering if it could be implemented like something of a whitelisted proxy: a limited SlotFillProvider which handles some slots (block controls) but then passes others up to its own context provider (inspector controls). It could even be an overloaded form of <SlotFillProvider slots=[ 'BlockControls' ]>{ children }</SlotFillProvider Edit:
This line of thinking also has me considering whether, if selection is meant to be considered more "global", that it be considered as part of state separate from an individual registry's block editor store. |
I don't think we should be shared between from the embedded editor and the parent editor. (I think a lot of reusable blocks open issues are due to this). I feel the first option the most logical for me.
This is not that different from the current PR, what I like about the current PR is that it removes the need for these strings, thus simplifying the implementation and solving this use-case. The only downside I see for the current approach compared to this proposal, is that it will force us to use a Provider for each slot but ultimately I think it's a good thing because these providers in a lot of cases can be embedded in reusable components:
I think it clarifies where we should include these providers instead of blindly adding them to the root level like we do today and making our components less reusable. |
Yeah, it occurred to me after I left my comment that the strings are considered an internal implementation detail. At the very least, it should be a reference to the slot component, e.g. That said, I'll plan to revisit next week in mind of your feedback. |
I'm going to close this PR at the moment. I still believe this is a better Slot/Fill implementation but the fact that it doesn't solve the first goal I intended here (the reusable blocks refactoring) makes me thing it's not urgent to provide an alternative implementation if there's no added value for us directly. |
Required for #14367
In #14367 we're building an editor inside another editor which means we'll have two "inspector controls" slots, two "block controls" slots...
Based on the current implementation of Slot/Fill, this means the last rendered Slot will get all the fills and the other one is useless. That's not exactly what we want, we want to be able to assign the Fills in the embedded editor to the embedded slot and the one outside the embedded editor should go into the global slot. If we use another
SlotFillProvider
at the BlockEditorLevel, this will work but the problem is that it will duplicate all the popovers rendered in the embedded block editor won't be shown as there's no slot for them in that provider and the Popover Slot is something global.This led to the decision to create a version of SlotFill that allows only a single Slot inside its assigned provider. The API looks like this:
This means the PopoverSlot will have its own PopoverSlotProvider, the InspectorControlsSlot will have its own InspectorControlsProvider...
The implementation here is made very simple by leveraging React hooks.
To do