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

List View: Allow dragging outside the immediate area by passing down a dropZoneElement #50726

Merged

Conversation

andrewserong
Copy link
Contributor

@andrewserong andrewserong commented May 18, 2023

What?

Part of addressing #43881 and #32438, alternative to #49420 and #50689. Overall, this PR makes dragging to the top and bottom positions of the list view easier.

Allow dragging and dropping within the list view, beyond the bounds of the list view itself, when passed a dropZoneElement (an element to be used as the drop zone, typically a parent of the final drop zone ref). Within the list view sidebar, pass the list view container area as a dropZoneElement to the ListView component.

Then, when the mouse leaves that drop zone area, clear the drop target so that the blue line no longer appears. The result should be that the blue drop indicator line within the list view is now accurate — it will only display when a drop will occur, and it displays across the whole list view area, making it easier to drag to the top and bottom-most positions.

Why?

One of the frustrations with drag and drop in the list view is that it's very difficult to drag to the top and bottom-most positions. This PR hopefully makes that experience feel more flexible and accurate.

How?

  • Pass an optional dropZoneElement element to useDropZone and use its element if available, falling back to the one passed down by useDropZone.
  • Allow this prop at the ListView and useListViewDropZone levels.
  • In the post and site editors (and widget editor), pass a ref of the list view container to the ListView.
  • Within the list view drop zone logic, when the user leaves the drop zone area, set the target to null so that the drop indicator disappears.
  • Update nesting logic so that if a user drags below the final item in the list, it won't be treated as a nesting gesture. This helps when a collapsed block is the last item in the list view, as a user dragging all the way to the bottom-most position likely wishes to move the block below rather than nest.

Testing Instructions

  1. In the post editor and site editors, experiment with dragging blocks to the top-most and bottom-most positions. Compared with trunk, it should be a lot easier to drop to these positions.
  2. Test with short list views and really long post content.
  3. If the last block in the list is a collapsed container block (e.g. group), then the nesting gesture should only apply when dragging over the bottom half of that block — if you drag further down, the drop indicator should change to be beneath that block rather than inside it.
  4. If the last block in the list is an expanded container block with some level of nesting, then dragging to parents should still work when dragging well below the bottom block position.
  5. Smoke test that dragging regular blocks in the editor canvas works as on trunk.
  6. Smoke test other list view instances (e.g. navigation in editor browse mode) that nothing breaks elsewhere.

Screenshots or screencast

Note how in the before version, the Heading looks like it can be dropped to the very bottom of the area by dragging well below, but it cannot. In the after version, the drop is respected correctly.

Before After
2023-05-18 17 17 20 2023-05-18 17 13 38

Some more details of the behaviour in this PR:

Dragging up the block hierarchy should still work when cursor is lower than the last block Nesting a collapsed block only happens if the cursor is over the block (makes it easier to drop below)
2023-05-19 12 00 02 2023-05-19 11 59 31

@andrewserong andrewserong added [Type] Enhancement A suggestion for improvement. [Feature] Drag and Drop Drag and drop functionality when working with blocks [Feature] List View Menu item in the top toolbar to select blocks from a list of links. labels May 18, 2023
@andrewserong andrewserong self-assigned this May 18, 2023
@github-actions
Copy link

github-actions bot commented May 18, 2023

Size Change: +22.8 kB (+2%)

Total Size: 1.4 MB

Filename Size Change
build/block-editor/content-rtl.css 4.23 kB +111 B (+3%)
build/block-editor/content.css 4.23 kB +111 B (+3%)
build/block-editor/index.min.js 199 kB +437 B (0%)
build/block-editor/style-rtl.css 15.1 kB +51 B (0%)
build/block-editor/style.css 15.1 kB +50 B (0%)
build/block-library/blocks/file/editor-rtl.css 316 B +16 B (+5%) 🔍
build/block-library/blocks/file/editor.css 316 B +16 B (+5%) 🔍
build/block-library/blocks/file/interactivity.min.js 395 B -6 B (-1%)
build/block-library/blocks/navigation/interactivity.min.js 865 B -7 B (-1%)
build/block-library/blocks/post-comments-form/style-rtl.css 508 B +7 B (+1%)
build/block-library/blocks/post-comments-form/style.css 508 B +7 B (+1%)
build/block-library/editor-rtl.css 12 kB +16 B (0%)
build/block-library/editor.css 12 kB +15 B (0%)
build/block-library/index.min.js 205 kB -59 B (0%)
build/block-library/interactivity/runtime.min.js 2.23 kB +1 B (0%)
build/block-library/style-rtl.css 12.9 kB +125 B (+1%)
build/block-library/style.css 12.9 kB +126 B (+1%)
build/blocks/index.min.js 50.9 kB -14 B (0%)
build/commands/index.min.js 15 kB +3 B (0%)
build/components/index.min.js 232 kB +22.8 kB (+11%) ⚠️
build/components/style-rtl.css 11.7 kB -17 B (0%)
build/components/style.css 11.7 kB -16 B (0%)
build/data/index.min.js 8.68 kB -5 B (0%)
build/edit-post/index.min.js 35.3 kB -7 B (0%)
build/edit-site/index.min.js 63.9 kB -809 B (-1%)
build/edit-site/style-rtl.css 10.5 kB -84 B (-1%)
build/edit-site/style.css 10.5 kB -81 B (-1%)
build/edit-widgets/index.min.js 17.3 kB +17 B (0%)
build/editor/index.min.js 45.8 kB +1 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.33 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 472 B
build/block-directory/index.min.js 7.18 kB
build/block-directory/style-rtl.css 1.02 kB
build/block-directory/style.css 1.02 kB
build/block-editor/default-editor-styles-rtl.css 381 B
build/block-editor/default-editor-styles.css 381 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 126 B
build/block-library/blocks/audio/theme.css 126 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 584 B
build/block-library/blocks/button/editor.css 582 B
build/block-library/blocks/button/style-rtl.css 624 B
build/block-library/blocks/button/style.css 623 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 409 B
build/block-library/blocks/columns/style.css 409 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.61 kB
build/block-library/blocks/cover/style.css 1.6 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 159 B
build/block-library/blocks/details/style.css 159 B
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 126 B
build/block-library/blocks/embed/theme.css 126 B
build/block-library/blocks/file/style-rtl.css 269 B
build/block-library/blocks/file/style.css 270 B
build/block-library/blocks/file/view.min.js 375 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/freeform/style-rtl.css 246 B
build/block-library/blocks/freeform/style.css 246 B
build/block-library/blocks/gallery/editor-rtl.css 947 B
build/block-library/blocks/gallery/editor.css 952 B
build/block-library/blocks/gallery/style-rtl.css 1.53 kB
build/block-library/blocks/gallery/style.css 1.53 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 654 B
build/block-library/blocks/group/editor.css 654 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 336 B
build/block-library/blocks/html/editor.css 337 B
build/block-library/blocks/image/editor-rtl.css 834 B
build/block-library/blocks/image/editor.css 833 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 B
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 507 B
build/block-library/blocks/media-text/style.css 505 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 712 B
build/block-library/blocks/navigation-link/editor.css 711 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/editor-rtl.css 2.33 kB
build/block-library/blocks/navigation/editor.css 2.33 kB
build/block-library/blocks/navigation/style-rtl.css 2.21 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 443 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 401 B
build/block-library/blocks/page-list/editor.css 401 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 588 B
build/block-library/blocks/post-featured-image/editor.css 586 B
build/block-library/blocks/post-featured-image/style-rtl.css 319 B
build/block-library/blocks/post-featured-image/style.css 319 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 281 B
build/block-library/blocks/post-template/style.css 281 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 335 B
build/block-library/blocks/pullquote/style.css 335 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 450 B
build/block-library/blocks/query/editor.css 449 B
build/block-library/blocks/quote/style-rtl.css 222 B
build/block-library/blocks/quote/style.css 222 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 178 B
build/block-library/blocks/search/editor.css 178 B
build/block-library/blocks/search/style-rtl.css 434 B
build/block-library/blocks/search/style.css 432 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 323 B
build/block-library/blocks/shortcode/editor.css 323 B
build/block-library/blocks/site-logo/editor-rtl.css 754 B
build/block-library/blocks/site-logo/editor.css 754 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 348 B
build/block-library/blocks/spacer/editor.css 348 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 645 B
build/block-library/blocks/table/style.css 644 B
build/block-library/blocks/table/theme-rtl.css 146 B
build/block-library/blocks/table/theme.css 146 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 403 B
build/block-library/blocks/template-part/editor.css 403 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 174 B
build/block-library/blocks/video/style.css 174 B
build/block-library/blocks/video/theme-rtl.css 126 B
build/block-library/blocks/video/theme.css 126 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.1 kB
build/block-library/common.css 1.1 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/interactivity/vendors.min.js 8.15 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/theme-rtl.css 686 B
build/block-library/theme.css 691 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/commands/style-rtl.css 827 B
build/commands/style.css 827 B
build/compose/index.min.js 12.4 kB
build/core-commands/index.min.js 1.8 kB
build/core-data/index.min.js 16.5 kB
build/customize-widgets/index.min.js 12.2 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 kB
build/data-controls/index.min.js 708 B
build/date/index.min.js 40.5 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.72 kB
build/edit-post/classic-rtl.css 544 B
build/edit-post/classic.css 545 B
build/edit-post/style-rtl.css 7.76 kB
build/edit-post/style.css 7.75 kB
build/edit-widgets/style-rtl.css 4.53 kB
build/edit-widgets/style.css 4.53 kB
build/editor/style-rtl.css 3.54 kB
build/editor/style.css 3.53 kB
build/element/index.min.js 4.89 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 7.77 kB
build/format-library/style-rtl.css 554 B
build/format-library/style.css 553 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.73 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/keycodes/index.min.js 1.91 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 836 B
build/list-reusable-blocks/style.css 836 B
build/media-utils/index.min.js 2.97 kB
build/notices/index.min.js 963 B
build/plugins/index.min.js 1.85 kB
build/preferences-persistence/index.min.js 2.22 kB
build/preferences/index.min.js 1.33 kB
build/primitives/index.min.js 944 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 939 B
build/react-i18n/index.min.js 696 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.74 kB
build/reusable-blocks/index.min.js 2.25 kB
build/reusable-blocks/style-rtl.css 243 B
build/reusable-blocks/style.css 243 B
build/rich-text/index.min.js 11 kB
build/router/index.min.js 1.78 kB
build/server-side-render/index.min.js 2.08 kB
build/shortcode/index.min.js 1.42 kB
build/style-engine/index.min.js 1.52 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.65 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.08 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.28 kB
build/widgets/style-rtl.css 1.15 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@andrewserong andrewserong force-pushed the try/list-view-drop-zone-allow-passing-in-a-drop-zone-ref branch from 9f0599e to d925f68 Compare May 18, 2023 23:58
@jasmussen
Copy link
Contributor

From the GIFs this feels like a substantial improvement, and something that I've wrestled with countless times. In testing I can't get it to work, though. Testing the post editor:

branch

What am I doing wrong?

Copy link
Contributor

@apeatling apeatling left a comment

Choose a reason for hiding this comment

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

Confirming what @jasmussen sees. I can't seem to trigger this change either when dragging past the last item in the list. Everything built and working correctly from what I can see?

2023-05-19 09 54 33

@andrewserong
Copy link
Contributor Author

Thanks folks! Sounds like I might have broken something in the latests commits, I'll dig into it 👍

@github-actions
Copy link

github-actions bot commented May 22, 2023

Flaky tests detected in 4eb834d.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5051597076
📝 Reported issues:

@andrewserong
Copy link
Contributor Author

andrewserong commented May 22, 2023

Thanks again for testing and flagging the issue @jasmussen and @apeatling — it turns out I was testing with the Always open list view preference running, and so I didn't notice that I missed updating the dependency array in useDropZone so that the logic would refresh when the ref for the drop zone area changes (which occurs when opening / closing the list view).

I've pushed a fix in 970217e, so it should be working now, but do let me know if you still run into any issues!

Updated: I've added a couple of simple tests in 84ac583 to test that the drop zone is flagged correctly.

Copy link
Contributor

@jasmussen jasmussen left a comment

Choose a reason for hiding this comment

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

Just delightful:

nice

Probably get a confidence boost on the code, but this feels vastly improved. Thank you!

Copy link
Contributor

@talldan talldan 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 working well. I'm unsure of some the specifics around how the useDropZone hook works, I personally always find these things a little hard to understand though!

// If a custom dropZoneRef is passed, use that instead of the element.
// This allows the dropzone to cover an expanded area, rather than
// be restricted to the area of the ref returned by this hook.
const element = dropZoneRef?.current ?? elem;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering how this will work in terms of the cleanup of the hook.

Because it's a ref effect, I think the callback will typically only trigger when elem is unmounted, not when dropZoneRef.current is unmounted.

Copy link
Contributor Author

@andrewserong andrewserong May 23, 2023

Choose a reason for hiding this comment

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

Good question! I think this is working pretty well so far. To confirm I logged out element within the callback, and it appears to be the right element:

image

As far as I can tell the behaviour is something like the following:

  • We pass in a ref to useDropZone, but useDropZone also returns a ref. That ref is still used in the list view, to attach to the TreeGrid component.
  • When TreeGrid unmounts, that results in the cleanup callback being called.
  • Because the cleanup callback was instantiated with a reference to element being the one passed in by dropZoneRef the cleanup callback cleans up the passed in element.
  • Also, because we have dropZoneRef?.current in the dependencies array of useRefEffect when the passed in ref changes, the cleanup appears to correctly fire, too. From checking the docs, this appears to be consistent with how useEffect works in that the cleanup fires not only when the component unmounts, but whenever any of the dependencies change. The doc comment for useRefEffect appears to confirm this here, too:
    /**
    * Effect-like ref callback. Just like with `useEffect`, this allows you to
    * return a cleanup function to be run if the ref changes or one of the
    * dependencies changes. The ref is provided as an argument to the callback
    * functions. The main difference between this and `useEffect` is that
    * the `useEffect` callback is not called when the ref changes, but this is.
    * Pass the returned ref callback as the component's ref and merge multiple refs
    * with `useMergeRefs`.
    *
    * It's worth noting that if the dependencies array is empty, there's not
    * strictly a need to clean up event handlers for example, because the node is
    * to be removed. It *is* necessary if you add dependencies because the ref
    * callback will be called multiple times for the same node.
    *
    * @param callback Callback with ref as argument.
    * @param dependencies Dependencies of the callback.
    *
    * @return Ref callback.
    */

So, all up, I don't think there are any stray event listeners not being removed, as far as I can tell.

Do let me know if you think I've missed anything here, though!

Copy link
Contributor

@talldan talldan May 23, 2023

Choose a reason for hiding this comment

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

When TreeGrid unmounts, that results in the cleanup callback being called.

Sorry if I'm making this more complicated. Given this is being introduced as a generic stable API, I'm mainly thinking that there could be different ways it's used (or misused):

  • The dropZoneRef could reference a completely separate part of the DOM that isn't mounted/unmounted at the same time as the effect's component.
  • The dropZoneRef could reference a parent of the effect's component that isn't mounted/unmounted at the same time.

I don't know if there are tests that can be added to assert these different cases work as expected.

It also might be worth expanding upon the docs for the prop to ensure that the right usage of this API is promoted. There's an example of this for Popover's anchor prop that recommends particular usage - https://github.com/WordPress/gutenberg/blob/trunk/packages/components/src/popover/README.md#anchor-element--virtualelement--null.

Also, because we have dropZoneRef?.current in the dependencies array of useRefEffect when the passed in ref changes, the cleanup appears to correctly fire, too

This is the part that often trips me up. With dropZoneRef being a ref type, it won't trigger a re-render when it changes. I've sometimes opted to store an element using useState for that reason (which is also what Popover recommends).

Copy link
Contributor Author

@andrewserong andrewserong May 23, 2023

Choose a reason for hiding this comment

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

Sorry if I'm making this more complicated.

No apology necessary! I'm happy to go as slowly as needed with this PR — I always like to be a bit more cautious when making changes to lower-level packages such as compose, and it's important we get it right and don't introduce any issues 👍

I don't know if there are tests that can be added to assert these different cases work as expected.

Good example use cases, it's worth digging in, I'll do a little more exploration to see if it's possible to come up with additional test cases. I think expanding the test cases there is probably a good path toward building confidence around the API change.

It also might be worth expanding upon the docs for the prop to ensure that the right usage of this API is promoted. There's an example of this for Popover's anchor prop that recommends particular usage

Good idea, for some reason useDropzone isn't documented in the compose package's readme, but I'll have a go at writing an entry for it.

This is the part that often trips me up. With dropZoneRef being a ref type, it won't trigger a re-render when it changes. I've sometimes opted to store an element using useState for that reason (which is also what Popover recommends).

Ah, good point, because the ref reference itself isn't changing, only current 🤔. In practice, I haven't yet run into any issues in this PR so far. In terms of using useState, do you mean we'd do that internally within useDropZone, or are you imagining that the consumer would use useState, and we'd pass the element directly to useDropZone instead of a ref?

Edit: I think you probably mean the latter — and I can see that the url popover for example, uses the state approach here:

— happy to swap it over to that pattern here 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Edit: I think you probably mean the latter — and I can see that the url popover for example, uses the state approach here

Yep, exactly that 👍

Copy link
Contributor Author

@andrewserong andrewserong May 23, 2023

Choose a reason for hiding this comment

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

Update: I've done the following:

  • Swapped out dropZoneRef for a dropZoneElement and updated usage to use state for storing the element before passing it along to the ListView (and then on to useDropZone)
  • Added a README file for useDropZone — because the hook is still currently exported as experimental, I couldn't add directly to the compose package readme. I see a couple of other experimental hooks also include their own README files in the compose package, so this seemed like a decent place to store the documentation for now, while the hook is still "experimental". Happy for any feedback there, I found it a bit challenging coming up with straightforward wording 😅

I haven't looked into exploring adding other tests just yet, but will dig in tomorrow.

Thanks again for the feedback!

Copy link
Contributor

Choose a reason for hiding this comment

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

because the hook is still currently exported as experimental, I couldn't add directly to the compose package readme.

Thanks, didn't realise it was experimental. It must have been that way for ages!

My hunch is that using state to store the element will probably solve the issues, hopefully that's the case.

packages/compose/src/hooks/use-drop-zone/index.js Outdated Show resolved Hide resolved
@andrewserong andrewserong changed the title List View: Allow dragging outside the immediate area by passing down a dropZoneRef List View: Allow dragging outside the immediate area by passing down a dropZoneElement May 23, 2023
Copy link
Contributor

@apeatling apeatling left a comment

Choose a reason for hiding this comment

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

Working great now, a big usability improvement!

2023-05-23 11 31 16

@andrewserong
Copy link
Contributor Author

andrewserong commented May 24, 2023

Thanks for the re-reviews!

@talldan and @kevin940726 — unfortunately I haven't had much luck writing additional tests for this, as I can't seem to get the event handlers to fire within an individual test (I've tried a user.pointer approach, a fireEvent.mouseDown / fireEvent.mouseMove approach, and firing dispatchEvent directly on the expected elements).

At this stage, do you think adding more tests is a blocker to landing this PR? Happy to keep looking into it, but I'm currently a bit stumped as to how to reliably write tests for this hook where the drag events are fired 🤔

@talldan
Copy link
Contributor

talldan commented May 24, 2023

At this stage, do you think adding more tests is a blocker to landing this PR?

I don't really know a lot about the testing situation, so I'm not very useful in offering suggestions!

I think it's good to merge given the docs now recommend using the hook in the same way List View uses it (and that's working well).

@andrewserong
Copy link
Contributor Author

I think it's good to merge given the docs now recommend using the hook in the same way List View uses it (and that's working well).

Thanks Dan! I've just committed your Readme suggestion, and once the GH actions pass, I'll merge this in.

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 [Feature] List View Menu item in the top toolbar to select blocks from a list of links. Needs User Documentation Needs new user documentation [Package] Compose /packages/compose [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants