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

Support drag and drop in horizontal block lists and improve drop zone detection #23020

Merged
merged 10 commits into from
Jun 17, 2020

Conversation

talldan
Copy link
Contributor

@talldan talldan commented Jun 9, 2020

Description

Fixes #22662

This PR adds support for drag and drop in horizontal block lists (buttons, social links, navigation) and also improves how we detect where the user intends to drop a block.

Creating a draft PR for now as this needs tests, but it'd be good to get some feedback.

How does this work

Previously, block drag and drop worked by using the y position of the dragged item, and comparing that to the y position of the blocks being dragged over. When the y position was less than halfway over a block, the block would be dropped before, and when more than halfway dropped after.

For horizontal block lists there are more challenges, this system can't be translated to the x axis because horizontal block lists tend to wrap onto multiple lines (for example, the buttons block).

This PR instead compares the position of the dragged item to the relevant edges of blocks. The top and bottom edges for vertical blocks lists and the left and right edges for horizontal. It picks the edge of the block that's nearest to the dragged item and uses that to determine where the item should be dropped.

Alternatives

I considered a few different alternatives and also tried a few different ways to calculate the drop position. One idea was drawing invisible block drop zones over the block list that can more concretely act as a drop target. This didn't work too badly, but I'd consider it a bigger change and it would also have issues if something has a higher z-index than the drop zone.

Remaining issues

There are still some areas that can be improved:

  • Because of the way the block lists are used as drop zones, it can be a little difficult to drag to the start of an InnerBlocks list when there's not much margin. That seems to be because the cursor has to be within the block list for it to be considered a valid target.
  • The indication of the drop zone area could still be improved quite a bit. I plan to work on this in a separate PR.

How has this been tested?

  1. Add a mixture of blocks preferably using normal blocks and blocks that have inner blocks (e.g buttons, media text, columns, group)
  2. Try dragging blocks around to see the general experience
  3. Try dragging buttons
  4. Observe that dragging in horizontal block lists now works correctly.

Types of changes

Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@talldan talldan added [Type] Bug An existing feature does not function as intended [Feature] Drag and Drop Drag and drop functionality when working with blocks labels Jun 9, 2020
@talldan talldan marked this pull request as draft June 9, 2020 09:54
@talldan talldan self-assigned this Jun 9, 2020
@talldan talldan force-pushed the try/better-block-drop-detection branch from c096ae4 to 64080a6 Compare June 10, 2020 07:25
@github-actions
Copy link

github-actions bot commented Jun 10, 2020

Size Change: +209 B (0%)

Total Size: 1.12 MB

Filename Size Change
build/block-editor/index.js 106 kB +174 B (0%)
build/block-editor/style-rtl.css 10.7 kB +18 B (0%)
build/block-editor/style.css 10.7 kB +17 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.62 kB 0 B
build/api-fetch/index.js 3.4 kB 0 B
build/autop/index.js 2.83 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 7.27 kB 0 B
build/block-directory/style-rtl.css 955 B 0 B
build/block-directory/style.css 955 B 0 B
build/block-library/editor-rtl.css 7.85 kB 0 B
build/block-library/editor.css 7.86 kB 0 B
build/block-library/index.js 129 kB 0 B
build/block-library/style-rtl.css 8.02 kB 0 B
build/block-library/style.css 8.02 kB 0 B
build/block-library/theme-rtl.css 749 B 0 B
build/block-library/theme.css 751 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/blocks/index.js 48.1 kB 0 B
build/components/index.js 195 kB 0 B
build/components/style-rtl.css 15.9 kB 0 B
build/components/style.css 15.9 kB 0 B
build/compose/index.js 9.6 kB 0 B
build/core-data/index.js 11.4 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.45 kB 0 B
build/date/index.js 5.47 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.17 kB 0 B
build/edit-navigation/index.js 8.26 kB 0 B
build/edit-navigation/style-rtl.css 1.04 kB 0 B
build/edit-navigation/style.css 1.04 kB 0 B
build/edit-post/index.js 303 kB 0 B
build/edit-post/style-rtl.css 5.6 kB 0 B
build/edit-post/style.css 5.6 kB 0 B
build/edit-site/index.js 16.6 kB 0 B
build/edit-site/style-rtl.css 3.13 kB 0 B
build/edit-site/style.css 3.13 kB 0 B
build/edit-widgets/index.js 9.33 kB 0 B
build/edit-widgets/style-rtl.css 2.54 kB 0 B
build/edit-widgets/style.css 2.54 kB 0 B
build/editor/editor-styles-rtl.css 486 B 0 B
build/editor/editor-styles.css 487 B 0 B
build/editor/index.js 44.8 kB 0 B
build/editor/style-rtl.css 3.82 kB 0 B
build/editor/style.css 3.82 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/index.js 7.72 kB 0 B
build/format-library/style-rtl.css 561 B 0 B
build/format-library/style.css 562 B 0 B
build/hooks/index.js 2.13 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 2.51 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.13 kB 0 B
build/list-reusable-blocks/style-rtl.css 537 B 0 B
build/list-reusable-blocks/style.css 537 B 0 B
build/media-utils/index.js 5.29 kB 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 681 B 0 B
build/nux/style.css 676 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.5 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/rich-text/index.js 14 kB 0 B
build/server-side-render/index.js 2.68 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.28 kB 0 B
build/url/index.js 4.06 kB 0 B
build/viewport/index.js 1.85 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.17 kB 0 B

compressed-size-action

Copy link
Contributor

@youknowriad youknowriad 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 really cool :) Thanks for working on this.

Ping @jasmussen as he's been working on drag and drop recently too
Ping @ellatrix as she was working on horizontal in between inserters which can be related.

@jasmussen
Copy link
Contributor

Thank you for working on this, this is really cool! This is what I see:

menu

Interestingly, the Navigation Block has that "absorb block toolbar" prop that means child blocks have their toolbar aligned to the parent block. Which is good, except for when you drag and drop :D then it gets a little weird.

Something to think about for the quote block for when that gets child blocks actually, cc: @ellatrix @mtias — we might not want to absorb the child toolbar after all in that block. Probably fine for Navigation, Buttons and Social Links still.

I left a small comment, but this feels pretty good to me. @talldan you may want to have a look at #23024 for what we might end up doing for drag and drop — as far as I can tell it doesn't affect things here, but just as an FYI.

@talldan
Copy link
Contributor Author

talldan commented Jun 10, 2020

Thanks for all the feedback. 😄

Interestingly, the Navigation Block has that "absorb block toolbar" prop that means child blocks have their toolbar aligned to the parent block. Which is good, except for when you drag and drop :D then it gets a little weird.

@jasmussen Yep, I think @tellthemachines spotted that too. Not sure if there's a ticket for it ... possibly not as I think the drag handle and movers were in the process of being changed.

@talldan you may want to have a look at #23024 for what we might end up doing for drag and drop — as far as I can tell it doesn't affect things here, but just as an FYI.

I can't see any overlap between the PRs, but I can double-check, it'll be nice to see the two changes working together.

@talldan talldan force-pushed the try/better-block-drop-detection branch from bfafbdc to ebb1a1a Compare June 11, 2020 09:39
@talldan talldan marked this pull request as ready for review June 11, 2020 09:39
@talldan
Copy link
Contributor Author

talldan commented Jun 11, 2020

I've added some unit tests and JSDocs, so this is ready for review now.

I'm not entirely sure I wrote all the typedefs right for the docs, happy to have feedback on that.

Comment on lines +182 to +183
moverDirection: getBlockListSettings( targetRootClientId )
?.__experimentalMoverDirection,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If this is merged, I think __experimentalMoverDirection could be renamed in a follow-up to something like blockOrientation, as it's now being used more widely than the movers.

Copy link
Member

Choose a reason for hiding this comment

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

How about blockListOrientation or blockFlowOrientation? I agree moverDirection doesn't really fit anymore.

@talldan talldan force-pushed the try/better-block-drop-detection branch from ebb1a1a to 25fe575 Compare June 17, 2020 04:19
Copy link
Member

@noisysocks noisysocks left a comment

Choose a reason for hiding this comment

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

I tested this in Firefox and it works really well. Nice work! 🎉

I noticed just two things, neither are blocking:

  • It can be challenging to drag a block to the bottom of the editor—I have to flail my cursor around like a madman to find the drop zone. It's much better than it is in master, though.

  • I can't ever drag a Column block to the beginning or end of a Columns block. You can't do this at all in master, though.

I think let's merge this early so that it gets some incidental testing by Gutenberg developers before the next plugin release.

} );

return candidateIndex;
}
Copy link
Member

Choose a reason for hiding this comment

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

That was probably the most readable code that deals with geometry I've ever seen! ❤️

// Flip the elementData to make a horizontal block list.
const horizontalElements = elementData.map( mapElements( 'horizontal' ) );

describe( 'getNearestBlockIndex', () => {
Copy link
Member

Choose a reason for hiding this comment

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

You get a 🌮 for adding tests!

@talldan
Copy link
Contributor Author

talldan commented Jun 17, 2020

It can be challenging to drag a block to the bottom of the editor—I have to flail my cursor around like a madman to find the drop zone. It's much better than it is in master, though.

Yeah, it's still not great, but then I'm not sure it was working at all before.

The problem is that as soon as the mouse leaves the drop zone element (which is the block-editor-block-list__layout element) the drag event is ignored. So for blocks that are right up against the edge of that containing element, you have to have the cursor inside the block list, but still close enough to the area you want to drop to.

One way to solve it could be to make the entire editor canvas as a drop zone, and make useBlockDropZone work from the root of the block list on all blocks rather than embedding it into each block list.

It might be a bit detrimental to performance, but could be worth trying.

@jasmussen
Copy link
Contributor

Does this PR change anything with regards to scrolling and dragging? #23082

@talldan
Copy link
Contributor Author

talldan commented Jun 17, 2020

@jasmussen The two PRs don't have any overlap, they should work together well.

@mtias
Copy link
Member

mtias commented Jun 17, 2020

This is great, thanks for working on it. For the main issue @jasmussen highlights we'll need the ability to drag from the block itself (initially only when in select mode).

@talldan talldan merged commit e4343d7 into master Jun 17, 2020
@talldan talldan deleted the try/better-block-drop-detection branch June 17, 2020 11:33
@github-actions github-actions bot added this to the Gutenberg 8.4 milestone Jun 17, 2020
@ellatrix
Copy link
Member

ellatrix commented Jun 17, 2020

@talldan Do you think any e2e tests could be created for drag and drop?

@talldan
Copy link
Contributor Author

talldan commented Jun 18, 2020

@ellatrix Yep, I can give it a go. I imagine it'd be possible to use page.evaluate to determine drop coordinates.

@ellatrix
Copy link
Member

Yes, there's some prior work on dragging in the multi selection e2e tests. Also resizing the spacer block I think.

Comment on lines +273 to +274
( sourceRootClientId === '' &&
targetRootClientId === undefined );
Copy link
Contributor

Choose a reason for hiding this comment

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

@talldan: Could we converge on the types of these two expectably similar variables? If that's not possible, can we add comments explaining the discrepancy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mcsf I've put together this PR that improves things - #24307

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Drag and Drop Drag and drop functionality when working with blocks [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Drag and drop does not work correctly with horizontal block lists
8 participants