-
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
Try multi-select inspector for same blocks #3535
Conversation
|
||
const attributeArray = multiSelectedBlocks.map( ( block ) => block.attributes ); | ||
const attributeKeys = uniq( flatten( attributeArray.map( keys ) ) ); | ||
const attributes = attributeKeys.reduce( ( acc, key ) => { |
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.
Attempted to use lodash's intersection
or similar, but not quite sure how to get it to work.
Codecov Report
@@ Coverage Diff @@
## master #3535 +/- ##
==========================================
+ Coverage 34.9% 34.97% +0.06%
==========================================
Files 263 263
Lines 6727 6771 +44
Branches 1227 1235 +8
==========================================
+ Hits 2348 2368 +20
- Misses 3694 3714 +20
- Partials 685 689 +4
Continue to review full report at Codecov.
|
8271c93
to
8b6d3ec
Compare
Any thoughts on this at all? :) |
@@ -93,9 +92,55 @@ registerBlockType( 'core/paragraph', { | |||
} | |||
}, | |||
|
|||
inspector( { attributes, setAttributes } ) { |
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.
A little bit concerned about this. Some times we need local state to be shared beween the inspector, toolbar and the edit
. If we separate this, it's not possible anymore.
Do you think it's possible to add some magic to InspectorControls
to detect if it's a multiselection and only render for one block only or something?
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 tried it before, but can't remember it well, so I'll try it again. Could you give an example of local state, just for me to think about solutions for it? :)
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.
We don't have an exemple with shared local state between the edit
and BlockInspector
but we do have between edit
and BlockControls
(in the audio
or block
blocks) and I believe these two are similar because in the exact same way we can display the same block toolbar in we multi-select similar blocks.
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.
Exactly, what is done here for the inspector should then also be done for the toolbar. The problem with the edit function is that it makes use for focus
. We'd need to remove that and figure out how to do that differently. I'll find the example with shared state and think about it.
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.
@youknowriad Which block are you referring to with the local state? Is there anything that wouldn't be solvable with block attributes? Ideally, we should stick with those for state.
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.
@iseulde block attributes are "state" but they are "state" persisted in post_content or comments or meta. I don't know if it's a good idea to use them for "local state", we may end up serializing useless local state attributes in comments.
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.
For example, the audio
block triggers an editing
local state using a button toolbar. And this local state changes the UI of the block.
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'm looking at this for the block toolbar (so if the selected blocks are of the same type, they get the toolbar and the controls apply changes to all selected blocks.)
It seems to me that having an inspector
and toolbar
function like this is very close to what we need, but as we need to share state between edit and BlockInspector/Toolbar, we need to reuse those functions to fill the appropriate slots.
The render in edit would look like this:
<BlockControls>
{ this.toolbar( { state, attributes, setAttributes } ) }
</BlockControls>
<InspectorControls>
{ this.inspector( { state, attributes, setAttributes } ) }
</InspectorControls>
The slots would get filled as normal, single block selection behaviour in unchanged.
Then, for example, in the block inspector where we currently have "Coming Soon", we'd get the block settings for the type of blocks we have selected, and call settings.inspector
passing an appropriate state, attributes, and a setAttributes function that would set attributes across all selected blocks. The state and attributes could be reduced from the selected blocks, so that if all blocks had the same value for a control, it would get that value (for example, if all paragraphs were the same color, that color would be selected).
I think this does identify an issue with how we're treating edit rendering as a single component tree, since this only really works when inspector rendering is one-to-one, and we don't need to externally isolate just the inspector or toolbar behaviors. While that can work well for operating on single blocks, it doesn't work so well for sharing rendering controls across multiple selected blocks. There's a few reasons I like keeping the slotted elements within
It's quite late to be making these breaking changes to the API, but if we were, I'd suggest at least:
If we were to build support for these to be separated, would we then handle the focus conditional rendering on behalf of the block implementer? Noting that I've had similar issues with |
#3483 also adds an interesting case where the controls would need the node of the block... |
Trying the other approach again. |
If we want to keep all components in one return [
<InspectorControls key="inspector" id={ id }>
{ ( { attributes, setAttributes } ) => [
<BlockDescription>
<p>{ __( 'Text. Great things start here.' ) }</p>
</BlockDescription>,
] }
</InspectorControls>,
]; |
Would it be too much magic for the ID to be "injected" via React context so the block implementer doesn't need to concern themselves with it? Thinking each BlockEdit could provide its block ID as context which The function as child makes sense to me, but I think could be disorienting for block implementers. Also suffers from variable shadowing. |
Should we also close this one in favor of #7635? |
Closing in favour of #7635. |
Description
WIP, only works for the paragraph block.
This is an attempt to add inspector controls when there are multiple blocks selected of the same type. This requires us to move away the inspector rendering to a separate component so that it can be reused
(PR does not include change for the edit component yet). I realise some quite like that everything is rendered in one big edit component, but I don't see how we could achieve this without splitting it up. @aduth @youknowriad @mtias What do you think about this?This only adds the controls to the inspector. The same should then be done for the toolbar on the top.