Skip to content
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 a toolbar that affects multiple selected blocks #7635

Closed
wants to merge 2 commits into from

Conversation

notnownikki
Copy link
Member

@notnownikki notnownikki commented Jun 29, 2018

Description

Similar PRs: #1811, #3535.

This adds a new controls option in a block's settings so the toolbar can be reused when multiple blocks of the same type are selected, and have the Edit component render them automatically for individual blocks.

Adds multi block controls and higher order components to deal with multiple block selections, so block developers can define their multi block aware controls in the edit component, and have them used to both single and multiple blocks.

Why a new option in the settings?

I wanted to have an easy way for block developers to define a toolbar and use it in their block, and also have it used by block-list/multi-controls to render a toolbar that can affect multiple blocks. It's optional, so maintains backward compatibility with existing block settings.

There isn't any more! It doesn't change the API.

Why is it just a standalone function?

So that the block can pass in its own props and state if the toolbar needs it, and the multi controls can create props with attributes reduced from the selected blocks.

It's not! It allows you to define a set of multi block aware components in edit and have them reused for single block instances too.

This approach should work for the Inspector controls.

Why does it look so bad?

Because. Help! 😄

It doesn't now!

Works though, doesn't it?

Yep.

@@ -314,6 +322,8 @@ export const settings = {

attributes: schema,

toolbar,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we introduce a toolbar API like this (maybe controls is better thought), Can we just automatically apply it to the block edit function if available?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this idea. I'll see what I can get working 👍

setAttributes( { align: nextAlign } );
} }
/>
{ toolbar( this.props, this.state ) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the second argument is useless here? Since the state is local to a block I believe we shouldn't use it in an API that can be common to multiple components. If block authors need state shared between edit and toolbar, it doesn't make sense to use toolbar, they'll just embed BlockControls in edit

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps... I was looking at #3535 where me and @iseulde came up with very similar approaches, and for the inspector it was said that the block state was needed too, so I figured that perhaps we should keep the signature of "reusable controls" the same?

@notnownikki
Copy link
Member Author

@youknowriad I've moved toolbar to controls and if the block settings define controls, then the Edit component automatically renders them, so block authors don't have to include them in their edit component's render, and the components are reused for the multi block selection.

@notnownikki
Copy link
Member Author

And now the multi-block toolbar shows the number of selected blocks, as @mtias originally requested :)

@ellatrix
Copy link
Member

ellatrix commented Jul 3, 2018

See #1811 and #3535 for previous discussion.

One of the problems with having a toolbar inside the first block wrapper is that it cannot be made sticky for the whole selection. I'm not sure what the solution here could be other than wrapping the selection in a div.

There's also the area in the block inspector which this PR could implement:

screen shot 2018-07-03 at 13 13 02

@@ -314,6 +317,8 @@ export const settings = {

attributes: schema,

controls,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last time there was some discussion for keeping the controls in the edit function: #3535 (comment). Insure if @aduth and @mtias still feel this way.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does get tricky if you want to reuse the same controls for multiple blocks, mostly because you'd create the components with the instance's setAttributes, and I couldn't see a way of nicely injecting a setAttributes that affected multiple blocks that way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In passing: I still don't particularly like this being part of the block API, when otherwise we've included it (and other block controls) as part of the block's own edit rendering. Including it in the block API seems more of a means to an end (being multi-block control) than being strictly "correct". Of course, I don't have a great idea in mind for working around this, aside from... not doing multi-toolbars 😄 Perhaps there is something where we could fake the render once of a given consistent set of selected blocks, inspect the result to see if there are block controls, and use that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried something similar to the fake render, grabbing the controls from <BlockControls> and reusing them, but their onClick handlers were bound to functions that had the setAttributes and values from this.props, and I couldn't make them reusable. That's been what forced me into putting them into the block API - I can grab the controls from the slot, but they're bound to a single block instance.

So while I would rather have them in the edit function too, I can't see a way of reusing them for the multi block toolbar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, we're going to come up against the same thing for the toolbar too. So if there is a way, we should talk about it as much as possible here so we have the right approach :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it could be a separate API for blocks to register themselves as being capable of having multi-select capabilities? My main concern is avoiding introducing an inconsistency both in controls themselves, but also in the general rendering approach to block UI pieces (and the responsibilities of edit).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've also blurred the line between how individual block units relate to one another. The original API was never meant to really support this sort of "apply behaviors to multiple instances", it was designed to support a single instance at a time. Bolting it on at this point will make for something of a Frankenstein API.

To be fair, I also lean more on the end of: If we can't make it work and have a consistent approach to block independence vs. interdependence, it shouldn't be included as a feature at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I agree there. It's a big missing feature for end users, and shouldn't be skipped because of technical purity. Having said that, I do agree that having 90% of the API able to use this and the rest not able to, feels quite wrong!

Perhaps we have block controls as something which decorates a block's settings, to keep the approaches distinct from each other?

From a dev perspective, something like:

// controls.js
export const controls = {
	toolbar: function( attributes, setAttributes ) {
		// ... do your instance agnostic toolbar controls thing there
	},
	inspector: function( attributes, setAttributes ) {
		// ... and inspector things here
	}
}


// index.js
import { withControls } from '../../blocks/api';
import controls from './controls';

const settings = withControls( controls, {
	// block settings here, using `this` happily
} );

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking more into what we can do here today. I feel like I should say, I agree that this shouldn't go in settings, and looking more at how block registration works, I don't think withControls fits either. Perhaps if we define controls as well as settings in a block, that could be passed to registerBlockType, and because it's not inside edit, there's no danger of trying to use this in a context where it shouldn't be used.

I'll put something together for comment :)

const attributes = {};
// Reduce the selected block's attributes, so if they all have the
// same value for an attribute, we get it in the multi toolbar attributes.
for ( let i = 0; i < multiSelectedBlocks.length; i++ ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not possible to use [].reduce here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The special case for index 0 made doing it this way more readable, to my eyes anyway

@notnownikki
Copy link
Member Author

@aduth so, I've tried something slightly different :)

Outside of settings, I've defined controls which has a toolbar property. I think this solves the issue of mixing instance and non-instance code within the settings. It's backward compatible, so if you don't define it and have BlockControls in your edit component, that'll still work.

@notnownikki
Copy link
Member Author

Update after some discussion with the core team : Adding toolbar and inspector to the API has more implications than I thought, other projects consuming the block API would need to revisit what they're doing and at this stage, we want to avoid that.

I'm going to carry on with an experiment to see if block toolbar controls can be multi-block aware, so a block developer doesn't have to think about anything more than putting controls as children of a BlockControls component. I'll start off by doing this with AlignmentToolbar and if it works, it should be an approach that works for the inspector too, without changing the block API.

@notnownikki
Copy link
Member Author

New shiny code with a new approach! All changed, rebased, and squashed.

This is a way of having multi block aware controls without having to repeat control definitions, or change the API.

A new HOC, withMultiBlockSupport can add multi block support to controls that deal with block attribute changes. The decorated controls become able to deal with single blocks, or apply changes to multiple blocks.

Block developers are able to specify controls that apply to single blocks only using BlockControls and put controls that can apply to multiple blocks in MultiBlockControls.

Example from the paragraph block:

<MultiBlockControls>
	<MultiBlockAlignmentToolbar
		value={ align }
		onChange={ ( nextAlign ) => {
			setAttributes( { align: nextAlign } );
		} }
	/>
</MultiBlockControls>
<BlockControls>
	... block specific controls would go here ...
</BlockControls>

In this example, the alignment toolbar will be used for single blocks and multiple blocks, there's no need to define it twice. The new MultiBlockControls slot will be used for both, and the alignment toolbar knows if it should be operating on a single block or the list of selected blocks.

@designsimply designsimply added the [Feature] Block Multi Selection The ability to select and manipulate multiple blocks label Jul 18, 2018
@notnownikki
Copy link
Member Author

Rebased for the clientId stuff.

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not taken this for a spin yet, but am curious: Is this expected to work as-is? I'm really liking the new (limited) impact on block API!

return (
<Fragment>
<BlockControls>
<AlignmentToolbar
<MultiBlockControls>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this still support the use-case of the single block selection?

It also prompts me to think: Can we just build-in multi block controls behavior to <BlockControls /> ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and no, respectively :)

There needs to be some way to show just the multi block controls when multiple blocks are selected. With this approach, it's two slots, one for multi- and one for single- controls. Both are rendered when only one block is selected, and only the multi slot is rendered when we have multiple blocks selected.

I toyed with having some kind of registry, or attribute on elements, but those approaches didn't seem as clean and as obvious to the block developer.

This PR won't work as-is with the current state of master, but I'm really after feedback on the approach at the moment before I go rebasing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There needs to be some way to show just the multi block controls when multiple blocks are selected. With this approach, it's two slots, one for multi- and one for single- controls. Both are rendered when only one block is selected, and only the multi slot is rendered when we have multiple blocks selected.

So is this just a complexity of the implementation? Or is it conceptually important that, as part of the edit interface, a distinction is made between single- and multi- selection?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little from column A and a little from column B.

I'd say that allowing the distinction to be made in edit allows block developers to specify if they want controls to apply to multiple blocks or not, however, do they need to? Is a block developer ever going to say, "I have this control that can update multiple blocks at once, and I really don't want the user to do that!"

Probably not.

I'd be very happy to hear ideas on how we could flag up controls that should apply to multiple blocks and therefore sort out the rendering purely with <BlockControls />. All my previous attempts at that smelled wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the implementation:

const MultiBlockAlignmentToolbar = withMultiBlockSupport( AlignmentToolbar, 'align' );

which effectively adds the attributeName for the toolbar control behind the scenes. I would bet that it is possible to express all this code as follows:

<BlockControls>
    <BlockAlignmentToolbar
        name="align"
        multi={ true }
        value={ align }
        onChange={ onChange }
    />
</BlockControls>

It would require some refactoring for BlockControls which is wrapped with ifBlockEditSelected HOC. It would have to support also the case when block is multi selected and have multi set to true. Finally, it would also have to handle the case when multi is set to false and block is multi selected - not render such control at all.

Still, the biggest challenge would be to iterate over those multiplied controls filled into slot and apply some modifications to the virtual dom tree which would allow to group them, render only one but trigger update for all of them. Basically, replicate what withMultiBlockSupport does.

In the future, we could go even further and hide the need for using value and onChange props since they are usually repeatable so the can be derived from the attribute name as explored in #6705.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, we could go even further and hide the need for using value and onChange props since they are usually repeatable so the can be derived from the attribute name as explored in #6705.

Also #7352

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is heading in the right direction and is going to be a super useful feature. It is very complex one, but very powerful for all plugin developers so let's make sure that public API is as simple as possible.

It would be lovely if we could explore what @aduth suggested:

Can we just build-in multi-block controls behavior to <BlockControls /> ?

I left my comment about that.

return (
<Fragment>
<BlockControls>
<AlignmentToolbar
<MultiBlockControls>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing the implementation:

const MultiBlockAlignmentToolbar = withMultiBlockSupport( AlignmentToolbar, 'align' );

which effectively adds the attributeName for the toolbar control behind the scenes. I would bet that it is possible to express all this code as follows:

<BlockControls>
    <BlockAlignmentToolbar
        name="align"
        multi={ true }
        value={ align }
        onChange={ onChange }
    />
</BlockControls>

It would require some refactoring for BlockControls which is wrapped with ifBlockEditSelected HOC. It would have to support also the case when block is multi selected and have multi set to true. Finally, it would also have to handle the case when multi is set to false and block is multi selected - not render such control at all.

Still, the biggest challenge would be to iterate over those multiplied controls filled into slot and apply some modifications to the virtual dom tree which would allow to group them, render only one but trigger update for all of them. Basically, replicate what withMultiBlockSupport does.

In the future, we could go even further and hide the need for using value and onChange props since they are usually repeatable so the can be derived from the attribute name as explored in #6705.

@aduth
Copy link
Member

aduth commented Aug 10, 2018

It would be lovely if we could explore what @aduth suggested:

Can we just build-in multi-block controls behavior to ?

I left my comment about that.

FWIW, and along the same lines as mentioned in #7635 (comment), in discussing this with @mtias there's may be an argument to be made that the controls for single selection may not be strictly the same as the controls for multi-selection of a block. I'm not entirely sure what the use-case would be. At the very least then, I think we'd want the two sets of controls to be insulated from one another (i.e. MultiControls doesn't also implement singular controls, even if that means duplicating).

@notnownikki
Copy link
Member Author

At the very least then, I think we'd want the two sets of controls to be insulated from one another (i.e. MultiControls doesn't also implement singular controls, even if that means duplicating).

Does this mean that the withMultiBlockSupport HOC is a no-go, or could we provide that for devs to use with simple controls where it fits nicely? If a developer uses that approach and then in the future finds that it's not going to work, they could replace the component it produced with a custom one without impacting anything else. And for those controls which do purely deal with setting an attribute, it seems a nice time saver, but only as an option to use, not a forced part of the API.

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that the withMultiBlockSupport HOC is a no-go, or could we provide that for devs to use with simple controls where it fits nicely

I'm not entirely clear its purpose, and while I think some "magic" for making attribute assignment easier would be a nice addition (explored also in #6705 and #7352), it's important that it's introduced consistently. If a control assigns attribute values for multi blocks, is there a reason it shouldn't for singular? What controls does this cover? What about support for non-standard attribute names?

I wonder if <MultiBlockControls> could provide context by a render prop function which exposes attributes and setAttributes which read from / apply to all blocks in the multi-selection.

<MultiBlockControls>
	{ ( { attributes, setAttributes } ) => (
		<BlockAlignmentToolbar
			value={ attributes.align }
			onChange={ ( nextAlign ) => {
				setAttributes( { align: nextAlign } );
			} }
		/>
	) }
</MultiBlockControls>

There's a potential issue here in variable shadowing.

*/
export const withMultiBlockSupport = ( component, attributeName ) => createHigherOrderComponent( ( OriginalComponent ) => {
const multSelectComponent = ( props ) => {
const newProps = { ...props };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shallow clone may be costly and unnecessary when we don't have a multi selection. I think it should only be done inside the condition.

* @return {Component} Component that can handle multple selected blocks.
*/
export const withMultiBlockSupport = ( component, attributeName ) => createHigherOrderComponent( ( OriginalComponent ) => {
const multSelectComponent = ( props ) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: mult -> multi

*
* @return {Component} Component which renders only when the BlockEdit is selected or it is the first block in a multi selection.
*/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This newline shouldn't be here, at risk of the JSDoc not being associated with the function.

* @return {Component} Component which renders only when the BlockEdit is selected or it is the first block in a multi selection.
*/

const isFirstOrOnlyBlockSelectedHOC = createHigherOrderComponent( ( OriginalComponent ) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: Naming, I tend to encourage avoiding the "HOC" terminology because it's not always obvious to new developers. We already have a convention around the "with" prefix, that I think we could use here as well.

return ( props ) => {
return (
<Consumer>
{ ( { isSelected, clientId } ) => ( isSelected || ( clientId === props.getFirstMultiSelectedBlockClientId && props.allSelectedBlocksOfSameType ) ) && (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line too long.

allSelectedBlocksOfSameType,
};
} ),
] )( isFirstOrOnlyBlockSelectedHOC( component ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what compose serves to eliminate, to rewrite:

a( b( c( d( Component ) ) ) );

...as:

compose( [ a, b, c, d ] )( Component );

In other words, isFirstOrOnlyBlockSelectedHOC could be added as an entry of the compose argument array.

*
* @return {*} Reduced value of attribute.
*/
function reduceAttribute( multiSelectedBlocks, attributeName ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a function called reduceAttribute, why not just Array#reduce ? 😄

return multiSelectedBlocks.reduce( ( attribute, block, i ) => {
	const block = multiSelectedBlocks[ i ];
	if ( block.attributes[ attributeName ] === attribute || 0 === i ) {
		return block.attributes[ attributeName ];
	}

	return undefined;
} );

if ( block.attributes[ attributeName ] === attribute || 0 === i ) {
attribute = block.attributes[ attributeName ];
} else {
attribute = undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW if the idea is to abort with undefined if we encounter a different attribute, this could be a return; statement, which would help avoid needing to iterate the rest of the array.

(This optimization won't be possible if converted to Array#reduce)

return (
<Fragment>
<BlockControls>
<AlignmentToolbar
<MultiBlockControls>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, we could go even further and hide the need for using value and onChange props since they are usually repeatable so the can be derived from the attribute name as explored in #6705.

Also #7352

@notnownikki
Copy link
Member Author

Just to confirm how we want to proceed with this...

  1. Remove the withMultiBlockSupport HOC.
  2. Change <MultiBlockControls> to use a render prop so that the single block toolbar controls get passed the correct reduced attributes, and setAttributes, as shown in Try a toolbar that affects multiple selected blocks #7635 (review)
  3. Rebase on master and apply <MultiBlockControls> on controls that are provided by supports in editor/src/hooks
  4. Address all other review points (typos, code style, etc.)

Does that sound like a plan? Anything that needs to be corrected or added?

@aduth
Copy link
Member

aduth commented Sep 10, 2018

Rebase on master and apply on controls that are provided by supports in editor/src/hooks

Could you elaborate on what this means? I don't recall where this was discussed.

Otherwise seems reasonable. The point on variable shadowing will probably become painfully obvious, and makes me wonder if there are other avenues to explore (or patterns to establish at least) for addressing. More a practical concern than fundamental issue, though one could argue we should do better establishing that in these examples, attributes and setAttributes should be clarified as to apply to multiple blocks (or not? if it's the "consistent value").

@mtias mtias added the Future label Oct 7, 2018
@gziolo gziolo added [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible Needs Decision Needs a decision to be actionable or relevant labels Feb 1, 2019
@gziolo
Copy link
Member

gziolo commented Feb 7, 2019

@mapk and @youknowriad - this is another interesting feature that should be considered as something to work on in phase 2. @notnownikki do you plan to continue working on it? It looks like it wasn't updated since August.

@notnownikki
Copy link
Member Author

Yes I'd like to continue with this. There may be better ways to achieve it now, I'd like to get eyes on it for design and code advice as part of phase 2 if possible.

@mapk
Copy link
Contributor

mapk commented Feb 11, 2019

I'd love to test this out, however, I'm getting some errors.

In the browser:

Fatal error: Cannot declare class WP_REST_Blocks_Controller, because the name is already in use in /var/www/html/wp-content/plugins/gutenberg/lib/class-wp-rest-blocks-controller.php on line 0

When I do a git status, I see some untracked files appear:

packages/block-serialization-spec-parser/parser.js
packages/block-serialization-spec-parser/parser.php
wordpress/

@notnownikki
Copy link
Member Author

Looking at this again, going to sort out the conflicts and try to get it working again.

@notnownikki
Copy link
Member Author

I have rebased this and started to address the review points. Most of the smaller ones have been addressed, and it's working again.

I'll carry on with the points from #7635 (comment) and explain further what I mean about the supports controls as we get there :)

@notnownikki
Copy link
Member Author

@aduth - from #7635 (review)

I'm not entirely clear its purpose, What controls does this cover?

withMultiBlockSupport exists for transparently adding multi block support to any block control where the attribute name coming in from the control matches the attribute name to be stored in the block. Given that requirement, the control will work with single and multiple blocks without any further development effort. The MultiBlockAlignmentToolbar in this PR for example, works with single and multiple blocks, and did not require altering the original toolbar control.

What about support for non-standard attribute names?

Yeah, this is a kind of hand-wavey don't look behind the curtain answer but maybe controls that can be applied to multiple blocks need to have the attribute naming conventions I describe above, for this first iteration. Do we have any controls in core that have these non-standard type names, could apply to multiple selected blocks, and wouldn't work with this approach? If so, ignore this and replace it with "yes, we need to let the control provide some kind of mapping".

Using the render prop approach would make this easier, but I think there it's a trade-off between implementing the controls more easily and implementing the block more easily. I'm more inclined to try to make block development as easy as possible, because we have far more new JS developers coming over from PHPland wanting to implement blocks, than new developers wanting to implement formatting controls and the like.

If a control assigns attribute values for multi blocks, is there a reason it shouldn't for singular?

The naming in this PR is wrong I think. Designating a MultiBlock version of a control as something separate from the single block version doesn't really sit well. A control developer shouldn't need to make two versions when writing the control, and a block developer should only need to put it in the right slot.

apply on controls that are provided by supports in editor/src/hooks

I said I'd explain what I meant here :) So we have the supports block setting, which can automatically set blocks up with various controls, and these controls should automatically be multi block aware when appropriate (depending on the control).

@mapk
Copy link
Contributor

mapk commented Apr 24, 2019

I'm just sharing a gif of what this looks like right now.

multi

Is that all I should be checking for?

@ellatrix ellatrix added [Feature] Writing Flow Block selection, navigation, splitting, merging, deletion... and removed [Feature] Writing Flow Block selection, navigation, splitting, merging, deletion... labels Jun 25, 2019
@notnownikki
Copy link
Member Author

Not sure on the status of this one, I'm not working on WordPress now, so I'll leave this open in case anyone else wants to continue, or happy to close it if other efforts are ongoing for the functionality.

@paaljoachim
Copy link
Contributor

I am wondering if this PR is somewhat similar to what Pascal @swissspidy is working on these days.

@phpbits
Copy link
Contributor

phpbits commented Oct 9, 2019

Would love to follow this as well. MultiBlockControls would be really helpful. Thanks!

@youknowriad
Copy link
Contributor

Trying to triage PRs today. Given that we're not investing in this right now and that the PR needs to be rewritten entirely with all the changes in master. I'm going to close this PR for now. We can reopen if there's a change in priorities. Thanks all for your efforts.

@aduth aduth deleted the try/multi-block-toolbar branch March 18, 2020 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block Multi Selection The ability to select and manipulate multiple blocks [Feature] Writing Flow Block selection, navigation, splitting, merging, deletion... Needs Decision Needs a decision to be actionable or relevant [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.