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

Block toolbar: account for scrollable blocks that affect the position of the block toolbar #66188

Merged
merged 3 commits into from
Oct 21, 2024

Conversation

ramonjd
Copy link
Member

@ramonjd ramonjd commented Oct 17, 2024

Fixes: #66112

What?

The while that gets the rect bounds of the child, including the x and y values, which change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the popover.

Why?

Hard to control what you can't see. This makes the block toolbar positioning more robust for extenders.

How?

Adjust calculated x/y values to account for any scrolling.

Testing Instructions

Navigation block with child extending beyond the nav block's bounds

This will confirm that the original fix from #62711 (comment) still works.

  1. Switch to EmptyTheme and navigate to Appearance > Editor
  2. Click on the canvas and add a navigation block to the header
  3. Move the navigation block to the very first position in the block list to force the toolbar below the block
  4. Add a submenu to the navigation if it doesn't already have one
  5. Ensure that the block toolbar moves down to accomodate the submenu when it is opened i.e. the toolbar shouldn't overlap the navigation or submenu blocks
  6. Confirm the toolbar behaves appropriately when adding new submenu items or scrolling the overall page

Scrollable block toolbars

Follow the nice and detailed instructions on #66112

TL;DR

  1. Edit a post, open dev tools and paste in the snippet from the issue to create some test blocks that scroll
  2. Add the test blocks to a long post with several paragraphs
  3. Select each of the horizontal and vertical scrolling blocks and confirm their toolbar stays in the correct location
  4. Scroll down the page and ensure their toolbars disappear correctly as the block leaves the viewport

Block Popovers and Visualizers

  1. Edit a post and add blocks that have a block popover e.g. Cover block with its resizable popover
  2. Add some blocks that support spacing visualizers e.g. Group block with padding and margin support
  3. Confirm that the visualizers and popovers display appropriately (visualizers have some problems on trunk not matching the controls value immediately so ignore them)A

Screenshots or screencast

2024-10-17.15.38.45.mp4

… y values, which change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the popover.
@ramonjd ramonjd added the [Status] In Progress Tracking issues with work in progress label Oct 17, 2024
Copy link

github-actions bot commented Oct 17, 2024

Size Change: +49 B (0%)

Total Size: 1.77 MB

Filename Size Change
build/block-editor/index.min.js 255 kB +49 B (+0.02%)
ℹ️ View Unchanged
Filename Size
build-module/a11y/index.min.js 482 B
build-module/block-library/file/view.min.js 447 B
build-module/block-library/image/view.min.js 1.78 kB
build-module/block-library/navigation/view.min.js 1.16 kB
build-module/block-library/query/view.min.js 742 B
build-module/block-library/search/view.min.js 616 B
build-module/interactivity-router/index.min.js 3.03 kB
build-module/interactivity/debug.min.js 17.2 kB
build-module/interactivity/index.min.js 13.6 kB
build/a11y/index.min.js 952 B
build/annotations/index.min.js 2.26 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.12 kB
build/blob/index.min.js 579 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1 kB
build/block-directory/style.css 1 kB
build/block-editor/content-rtl.css 4.46 kB
build/block-editor/content.css 4.45 kB
build/block-editor/default-editor-styles-rtl.css 394 B
build/block-editor/default-editor-styles.css 394 B
build/block-editor/style-rtl.css 15.3 kB
build/block-editor/style.css 15.3 kB
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 149 B
build/block-library/blocks/audio/editor.css 151 B
build/block-library/blocks/audio/style-rtl.css 132 B
build/block-library/blocks/audio/style.css 132 B
build/block-library/blocks/audio/theme-rtl.css 134 B
build/block-library/blocks/audio/theme.css 134 B
build/block-library/blocks/avatar/editor-rtl.css 115 B
build/block-library/blocks/avatar/editor.css 115 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/button/editor-rtl.css 265 B
build/block-library/blocks/button/editor.css 265 B
build/block-library/blocks/button/style-rtl.css 538 B
build/block-library/blocks/button/style.css 538 B
build/block-library/blocks/buttons/editor-rtl.css 291 B
build/block-library/blocks/buttons/editor.css 291 B
build/block-library/blocks/buttons/style-rtl.css 345 B
build/block-library/blocks/buttons/style.css 345 B
build/block-library/blocks/calendar/style-rtl.css 240 B
build/block-library/blocks/calendar/style.css 240 B
build/block-library/blocks/categories/editor-rtl.css 132 B
build/block-library/blocks/categories/editor.css 131 B
build/block-library/blocks/categories/style-rtl.css 152 B
build/block-library/blocks/categories/style.css 152 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 139 B
build/block-library/blocks/code/style.css 139 B
build/block-library/blocks/code/theme-rtl.css 122 B
build/block-library/blocks/code/theme.css 122 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 420 B
build/block-library/blocks/columns/style.css 420 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 124 B
build/block-library/blocks/comment-author-avatar/editor.css 124 B
build/block-library/blocks/comment-author-name/style-rtl.css 72 B
build/block-library/blocks/comment-author-name/style.css 72 B
build/block-library/blocks/comment-content/style-rtl.css 120 B
build/block-library/blocks/comment-content/style.css 120 B
build/block-library/blocks/comment-date/style-rtl.css 65 B
build/block-library/blocks/comment-date/style.css 65 B
build/block-library/blocks/comment-edit-link/style-rtl.css 70 B
build/block-library/blocks/comment-edit-link/style.css 70 B
build/block-library/blocks/comment-reply-link/style-rtl.css 71 B
build/block-library/blocks/comment-reply-link/style.css 71 B
build/block-library/blocks/comment-template/style-rtl.css 200 B
build/block-library/blocks/comment-template/style.css 199 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 228 B
build/block-library/blocks/comments-pagination/editor.css 217 B
build/block-library/blocks/comments-pagination/style-rtl.css 234 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 832 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 631 B
build/block-library/blocks/cover/editor-rtl.css 641 B
build/block-library/blocks/cover/editor.css 642 B
build/block-library/blocks/cover/style-rtl.css 1.64 kB
build/block-library/blocks/cover/style.css 1.63 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 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 331 B
build/block-library/blocks/embed/editor.css 331 B
build/block-library/blocks/embed/style-rtl.css 419 B
build/block-library/blocks/embed/style.css 419 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 326 B
build/block-library/blocks/file/style-rtl.css 278 B
build/block-library/blocks/file/style.css 279 B
build/block-library/blocks/footnotes/style-rtl.css 198 B
build/block-library/blocks/footnotes/style.css 197 B
build/block-library/blocks/form-input/editor-rtl.css 229 B
build/block-library/blocks/form-input/editor.css 229 B
build/block-library/blocks/form-input/style-rtl.css 357 B
build/block-library/blocks/form-input/style.css 357 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 344 B
build/block-library/blocks/form-submission-notification/editor.css 341 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 470 B
build/block-library/blocks/freeform/editor-rtl.css 2.6 kB
build/block-library/blocks/freeform/editor.css 2.6 kB
build/block-library/blocks/gallery/editor-rtl.css 946 B
build/block-library/blocks/gallery/editor.css 951 B
build/block-library/blocks/gallery/style-rtl.css 1.83 kB
build/block-library/blocks/gallery/style.css 1.82 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 334 B
build/block-library/blocks/group/editor.css 334 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 B
build/block-library/blocks/group/theme-rtl.css 79 B
build/block-library/blocks/group/theme.css 79 B
build/block-library/blocks/heading/style-rtl.css 188 B
build/block-library/blocks/heading/style.css 188 B
build/block-library/blocks/html/editor-rtl.css 346 B
build/block-library/blocks/html/editor.css 347 B
build/block-library/blocks/image/editor-rtl.css 785 B
build/block-library/blocks/image/editor.css 787 B
build/block-library/blocks/image/style-rtl.css 1.59 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 355 B
build/block-library/blocks/latest-comments/style.css 354 B
build/block-library/blocks/latest-posts/editor-rtl.css 179 B
build/block-library/blocks/latest-posts/editor.css 179 B
build/block-library/blocks/latest-posts/style-rtl.css 509 B
build/block-library/blocks/latest-posts/style.css 510 B
build/block-library/blocks/list/style-rtl.css 107 B
build/block-library/blocks/list/style.css 107 B
build/block-library/blocks/loginout/style-rtl.css 61 B
build/block-library/blocks/loginout/style.css 61 B
build/block-library/blocks/media-text/editor-rtl.css 321 B
build/block-library/blocks/media-text/editor.css 320 B
build/block-library/blocks/media-text/style-rtl.css 558 B
build/block-library/blocks/media-text/style.css 556 B
build/block-library/blocks/more/editor-rtl.css 427 B
build/block-library/blocks/more/editor.css 427 B
build/block-library/blocks/navigation-link/editor-rtl.css 644 B
build/block-library/blocks/navigation-link/editor.css 645 B
build/block-library/blocks/navigation-link/style-rtl.css 192 B
build/block-library/blocks/navigation-link/style.css 191 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 295 B
build/block-library/blocks/navigation-submenu/editor.css 294 B
build/block-library/blocks/navigation/editor-rtl.css 2.2 kB
build/block-library/blocks/navigation/editor.css 2.2 kB
build/block-library/blocks/navigation/style-rtl.css 2.25 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/nextpage/editor-rtl.css 392 B
build/block-library/blocks/nextpage/editor.css 392 B
build/block-library/blocks/page-list/editor-rtl.css 378 B
build/block-library/blocks/page-list/editor.css 378 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 236 B
build/block-library/blocks/paragraph/editor.css 236 B
build/block-library/blocks/paragraph/style-rtl.css 341 B
build/block-library/blocks/paragraph/style.css 340 B
build/block-library/blocks/post-author-biography/style-rtl.css 74 B
build/block-library/blocks/post-author-biography/style.css 74 B
build/block-library/blocks/post-author-name/style-rtl.css 69 B
build/block-library/blocks/post-author-name/style.css 69 B
build/block-library/blocks/post-author/editor-rtl.css 107 B
build/block-library/blocks/post-author/editor.css 107 B
build/block-library/blocks/post-author/style-rtl.css 188 B
build/block-library/blocks/post-author/style.css 189 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-comments-form/style-rtl.css 527 B
build/block-library/blocks/post-comments-form/style.css 528 B
build/block-library/blocks/post-content/style-rtl.css 61 B
build/block-library/blocks/post-content/style.css 61 B
build/block-library/blocks/post-date/style-rtl.css 62 B
build/block-library/blocks/post-date/style.css 62 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 155 B
build/block-library/blocks/post-excerpt/style.css 155 B
build/block-library/blocks/post-featured-image/editor-rtl.css 729 B
build/block-library/blocks/post-featured-image/editor.css 726 B
build/block-library/blocks/post-featured-image/style-rtl.css 347 B
build/block-library/blocks/post-featured-image/style.css 347 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 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 399 B
build/block-library/blocks/post-template/style.css 398 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 70 B
build/block-library/blocks/post-time-to-read/style.css 70 B
build/block-library/blocks/post-title/style-rtl.css 162 B
build/block-library/blocks/post-title/style.css 162 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 134 B
build/block-library/blocks/pullquote/editor.css 134 B
build/block-library/blocks/pullquote/style-rtl.css 342 B
build/block-library/blocks/pullquote/style.css 342 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 121 B
build/block-library/blocks/query-pagination-numbers/editor.css 118 B
build/block-library/blocks/query-pagination/editor-rtl.css 154 B
build/block-library/blocks/query-pagination/editor.css 154 B
build/block-library/blocks/query-pagination/style-rtl.css 237 B
build/block-library/blocks/query-pagination/style.css 237 B
build/block-library/blocks/query-title/style-rtl.css 64 B
build/block-library/blocks/query-title/style.css 64 B
build/block-library/blocks/query/editor-rtl.css 452 B
build/block-library/blocks/query/editor.css 451 B
build/block-library/blocks/quote/style-rtl.css 238 B
build/block-library/blocks/quote/style.css 238 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 236 B
build/block-library/blocks/read-more/style-rtl.css 138 B
build/block-library/blocks/read-more/style.css 138 B
build/block-library/blocks/rss/editor-rtl.css 101 B
build/block-library/blocks/rss/editor.css 101 B
build/block-library/blocks/rss/style-rtl.css 288 B
build/block-library/blocks/rss/style.css 287 B
build/block-library/blocks/search/editor-rtl.css 199 B
build/block-library/blocks/search/editor.css 199 B
build/block-library/blocks/search/style-rtl.css 672 B
build/block-library/blocks/search/style.css 671 B
build/block-library/blocks/search/theme-rtl.css 113 B
build/block-library/blocks/search/theme.css 113 B
build/block-library/blocks/separator/editor-rtl.css 100 B
build/block-library/blocks/separator/editor.css 100 B
build/block-library/blocks/separator/style-rtl.css 248 B
build/block-library/blocks/separator/style.css 248 B
build/block-library/blocks/separator/theme-rtl.css 195 B
build/block-library/blocks/separator/theme.css 195 B
build/block-library/blocks/shortcode/editor-rtl.css 286 B
build/block-library/blocks/shortcode/editor.css 286 B
build/block-library/blocks/site-logo/editor-rtl.css 806 B
build/block-library/blocks/site-logo/editor.css 803 B
build/block-library/blocks/site-logo/style-rtl.css 218 B
build/block-library/blocks/site-logo/style.css 218 B
build/block-library/blocks/site-tagline/editor-rtl.css 87 B
build/block-library/blocks/site-tagline/editor.css 87 B
build/block-library/blocks/site-tagline/style-rtl.css 65 B
build/block-library/blocks/site-tagline/style.css 65 B
build/block-library/blocks/site-title/editor-rtl.css 85 B
build/block-library/blocks/site-title/editor.css 85 B
build/block-library/blocks/site-title/style-rtl.css 143 B
build/block-library/blocks/site-title/style.css 143 B
build/block-library/blocks/social-link/editor-rtl.css 338 B
build/block-library/blocks/social-link/editor.css 338 B
build/block-library/blocks/social-links/editor-rtl.css 729 B
build/block-library/blocks/social-links/editor.css 727 B
build/block-library/blocks/social-links/style-rtl.css 1.51 kB
build/block-library/blocks/social-links/style.css 1.5 kB
build/block-library/blocks/spacer/editor-rtl.css 346 B
build/block-library/blocks/spacer/editor.css 346 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-of-contents/style-rtl.css 83 B
build/block-library/blocks/table-of-contents/style.css 83 B
build/block-library/blocks/table/editor-rtl.css 394 B
build/block-library/blocks/table/editor.css 394 B
build/block-library/blocks/table/style-rtl.css 640 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/editor-rtl.css 144 B
build/block-library/blocks/tag-cloud/editor.css 144 B
build/block-library/blocks/tag-cloud/style-rtl.css 266 B
build/block-library/blocks/tag-cloud/style.css 265 B
build/block-library/blocks/template-part/editor-rtl.css 368 B
build/block-library/blocks/template-part/editor.css 368 B
build/block-library/blocks/template-part/theme-rtl.css 113 B
build/block-library/blocks/template-part/theme.css 113 B
build/block-library/blocks/term-description/style-rtl.css 126 B
build/block-library/blocks/term-description/style.css 126 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 165 B
build/block-library/blocks/text-columns/style.css 165 B
build/block-library/blocks/verse/style-rtl.css 98 B
build/block-library/blocks/verse/style.css 98 B
build/block-library/blocks/video/editor-rtl.css 396 B
build/block-library/blocks/video/editor.css 397 B
build/block-library/blocks/video/style-rtl.css 192 B
build/block-library/blocks/video/style.css 192 B
build/block-library/blocks/video/theme-rtl.css 134 B
build/block-library/blocks/video/theme.css 134 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.08 kB
build/block-library/common.css 1.08 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.7 kB
build/block-library/editor.css 11.7 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 220 kB
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.9 kB
build/block-library/style.css 14.9 kB
build/block-library/theme-rtl.css 708 B
build/block-library/theme.css 712 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 52.5 kB
build/commands/index.min.js 16.1 kB
build/commands/style-rtl.css 955 B
build/commands/style.css 952 B
build/components/index.min.js 227 kB
build/components/style-rtl.css 12.4 kB
build/components/style.css 12.4 kB
build/compose/index.min.js 12.7 kB
build/core-commands/index.min.js 3.11 kB
build/core-data/index.min.js 73.4 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.35 kB
build/customize-widgets/style.css 1.35 kB
build/data-controls/index.min.js 641 B
build/data/index.min.js 8.97 kB
build/date/index.min.js 18 kB
build/deprecated/index.min.js 458 B
build/dom-ready/index.min.js 325 B
build/dom/index.min.js 4.66 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 580 B
build/edit-post/index.min.js 13.7 kB
build/edit-post/style-rtl.css 2.76 kB
build/edit-post/style.css 2.75 kB
build/edit-site/index.min.js 218 kB
build/edit-site/posts-rtl.css 7.32 kB
build/edit-site/posts.css 7.32 kB
build/edit-site/style-rtl.css 12.6 kB
build/edit-site/style.css 12.6 kB
build/edit-widgets/index.min.js 17.7 kB
build/edit-widgets/style-rtl.css 4.19 kB
build/edit-widgets/style.css 4.19 kB
build/editor/index.min.js 103 kB
build/editor/style-rtl.css 9.37 kB
build/editor/style.css 9.38 kB
build/element/index.min.js 4.82 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.04 kB
build/format-library/style-rtl.css 476 B
build/format-library/style.css 476 B
build/hooks/index.min.js 1.65 kB
build/html-entities/index.min.js 445 B
build/i18n/index.min.js 3.58 kB
build/is-shallow-equal/index.min.js 526 B
build/keyboard-shortcuts/index.min.js 1.31 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.13 kB
build/list-reusable-blocks/style-rtl.css 852 B
build/list-reusable-blocks/style.css 852 B
build/media-utils/index.min.js 3.2 kB
build/notices/index.min.js 946 B
build/nux/index.min.js 1.62 kB
build/nux/style-rtl.css 749 B
build/nux/style.css 745 B
build/patterns/index.min.js 7.34 kB
build/patterns/style-rtl.css 687 B
build/patterns/style.css 685 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.9 kB
build/preferences/style-rtl.css 554 B
build/preferences/style.css 554 B
build/primitives/index.min.js 829 B
build/priority-queue/index.min.js 1.54 kB
build/private-apis/index.min.js 960 B
build/react-i18n/index.min.js 630 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.76 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.55 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.1 kB
build/router/index.min.js 1.96 kB
build/server-side-render/index.min.js 1.94 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 2.04 kB
build/token-list/index.min.js 581 B
build/url/index.min.js 3.9 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react-jsx-runtime.min.js 556 B
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 965 B
build/warning/index.min.js 250 B
build/widgets/index.min.js 7.16 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

@aaronrobertshaw aaronrobertshaw added [Type] Bug An existing feature does not function as intended [Package] Block editor /packages/block-editor labels Oct 17, 2024
Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

Thanks for spinning this up @ramonjd 🚀

I've taken the liberty to flesh out the PR description and test instructions with some of the testing I've done using this PR branch. I don't suspect it to be an exhaustive list though but here's to hoping it helps spark further ideas.

In the meantime:

✅ Code changes match the snippet discussed on the original issue
✅ Toolbar remains correctly positioned for both horizontally and vertically scrollable blocks
✅ Block popovers such as spacing visualizers or cover blocks resizable popover appear unaffected
✅ The block toolbar is positioned correctly when toggling display of a nav submenu, adding links to it etc.

The Navigation block appears to be the only core block where a child extends beyond the visual bounds of the block's wrapper. I happy to be corrected here but if it is. This PR works well for me.

Screenshot 2024-10-17 at 3 36 54 pm
Screen.Recording.2024-10-17.at.3.38.18.pm.mp4

In the video above you might notice the block selection outline not adapting to scrollable blocks as well. I don't think that needs to be covered by this PR and is best suited to a seperate follow-up.

I'll hold off on approving this to leave space for new ideas, further testing etc.

@ramonjd ramonjd requested a review from t-hamano October 17, 2024 06:16
@ramonjd
Copy link
Member Author

ramonjd commented Oct 17, 2024

Thanks a lot for the great description and test steps. Helps a lot. So far it's working for me too - waiting for @t-hamano to find the bug :trollface:

@ramonjd ramonjd marked this pull request as ready for review October 17, 2024 22:38
@ramonjd ramonjd removed the [Status] In Progress Tracking issues with work in progress label Oct 17, 2024
@ramonjd ramonjd self-assigned this Oct 17, 2024
Copy link

github-actions bot commented Oct 17, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: kevin940726 <kevin940726@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment on lines 156 to 159
if ( childBounds.height > bounds.height ) {
childBounds.y = bounds.y;
childBounds.height = bounds.height;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately I think the logic is imperfect — while it works for me when the links within a sub menu are the same height as the submenu item itself, if we add a link within the submenu that is taller (i.e. a link to a page that wraps to a second line) then the toolbar will overlap the submenu again:

image

If I'm following the logic correctly, in this case, the individual item within the submenu is taller than bounds.height so we use bounds.height instead, so the bounds doesn't grow to include this item.

Apologies that this isn't a very useful comment — unfortunately I can't think of a neat way to determine if the child item is taller because it's in a popover (and so we want to include it) versus it being because of scroll (in which case we want to exclude it) 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

Having trouble replicating it, but I see what you mean based on the logic you've explained

2024-10-18.14.11.51.mp4

🤔 Do we only care about the parentRect?

Maybe we should rather be checking against that:

Example diff
diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js
index 19dd24ce382..1983d37f723 100644
--- a/packages/block-editor/src/utils/dom.js
+++ b/packages/block-editor/src/utils/dom.js
@@ -140,7 +140,8 @@ export function getVisibleElementBounds( element ) {
 		return new window.DOMRectReadOnly();
 	}
 
-	let bounds = element.getBoundingClientRect();
+	const parentRect = element.getBoundingClientRect();
+	let bounds = parentRect;
 
 	const stack = [ element ];
 	let currentElement;
@@ -150,12 +151,12 @@ export function getVisibleElementBounds( element ) {
 			if ( isElementVisible( child ) ) {
 				const childBounds = child.getBoundingClientRect();
 				// If the child is larger than the parent, adjust the x and y values to account for any scrolling.
-				if ( childBounds.width > bounds.width ) {
-					childBounds.x = bounds.x;
+				if ( childBounds.width > parentRect.width ) {
+					childBounds.x = parentRect.x;
 				}
-				if ( childBounds.height > bounds.height ) {
-					childBounds.y = bounds.y;
-					childBounds.height = bounds.height;
+				if ( childBounds.height > parentRect.height ) {
+					childBounds.y = parentRect.y;
+					childBounds.height = parentRect.height;
 				}
 				bounds = rectUnion( bounds, childBounds );
 				stack.push( child );

Copy link
Contributor

Choose a reason for hiding this comment

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

Having trouble replicating it, but I see what you mean based on the logic you've explained

Now that you mention it, I can only replicate it when the tall menu item is the last in the list. If it isn't, then when the logic gets to the last child, the union will work against that item so the bug isn't apparent. So perhaps this is a bit more edge-casey than I thought! Ideally it'd be good to figure out, though 🤔

🤔 Do we only care about the parentRect?
Maybe we should rather be checking against that:

Comparing explicitly against the parentRect now more closely matches the intent (and the comment), but I can still replicate the issue, so I'm not sure it changes much, unfortunately.

Copy link
Member Author

@ramonjd ramonjd Oct 18, 2024

Choose a reason for hiding this comment

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

I see it now - is it right that it only happens onHover?

Selecting the element, I cannot replicate.

Seems as if the position, onHover, is the previous position. Only onHover where the currently-selected item's toolbar doesn't drop.

2024-10-18.14.46.15.mp4

Interesting!

Copy link
Member Author

Choose a reason for hiding this comment

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

Or rather, I'm seeing it only when selecting a menu item with no submenu and the hovering over a menu item with a submenu.

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 managed to get something working by caching all the x/y values and using the max:

2024-10-18.15.25.44.mp4

It's pretty experimental, but I'll commit for consideration 😄

2024-10-18.15.25.19.mp4

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for digging in further here! That's definitely getting it closer for me. Now it looks like the y position of the toolbar is directly beneath the last item, but not the padding of the sub menu. Much better but still not quite right:

image

But it might just be close enough?

Or rather, I'm seeing it only when selecting a menu item with no submenu and the hovering over a menu item with a submenu.

Ah yep, that seems to be the case for me. That makes it feel even more edge-casey, so I feel like we could be nearly close to something workable.

}
if ( childBounds.height > parentRect.height ) {
childBounds.y = Math.max(
parentRect.y,
Copy link
Member Author

Choose a reason for hiding this comment

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

Now, this all makes me suspect that the original logic might be over-engineered? I'm not sure, so don't quote me.

What do we care about here? Whether any children overflow their parents.

A flat list of element.querySelector(*) might do the same job.

I don't really know to be honest 😆

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a good point, this is pretty complex and I'm finding it hard to reason about making changes that feel stable.

What do we care about here? Whether any children overflow their parents.
A flat list of element.querySelector(*) might do the same job.
I don't really know to be honest 😆

The more I look at the logic the less I feel sure of how it should work, but that's also possibly because of being at the end of the week!

I like your thinking in general about simplification. Overall we're trying to see if any children extend beyond the bounds of the top-level container visually. It'd be great to be able to do that without having to walk the entire DOM hierarchy, which depending on the circumstances could be fairly complex.

A flat list of element.querySelector(*) might do the same job.

I suppose the question then is which is more performant: iterating over currentElement.children and adding to a stack, or using the querySelector. In my mind what we're doing is fairly similar in each case, though element.querySelector(*) might be slightly easier to read as it'd be a forEach instead of a nested for within a while 🤔

For now, I'd probably lean toward seeing if we can keep the current overall shape of the code in place while fixing the bug, but I do agree it's worth revisiting the overall complexity here.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a good point, this is pretty complex and I'm finding it hard to reason about making changes that feel stable.

Ditto.

For now, I'd probably lean toward seeing if we can keep the current overall shape of the code in place while fixing the bug, but I do agree it's worth revisiting the overall complexity here.

In my testing it appears latest update in 4403bb9 has reintroduced the issue where a vertically scrolling block's toolbar isn't hidden until after the height of the scrollable content.

Here's what I'm now seeing
Screen.Recording.2024-10-18.at.4.35.41.pm.mp4

Personally, I'm starting to feel as though we should ensure we have clarity around what we have to achieve, then perhaps start from there, working to the simplest solution rather than persist with the complex approach and hope to work back to a simpler option. In other words, if we're struggling to reason about the changes etc it could be hard to reach the point where we're confident enough that it could be refactored.

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, I'm starting to feel as though we should ensure we have clarity around what we have to achieve, then perhaps start from there, working to the simplest solution rather than persist with the complex approach and hope to work back to a simpler option. In other words, if we're struggling to reason about the changes etc it could be hard to reach the point where we're confident enough that it could be refactored.

Also a very good point! No objections from me if we think we can come up with a simpler solution 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

With the "Friday brain is mush" disclaimer established, take the following with a grain of salt.

Do we need to treat children that are scrollable within the parent differently to one rendered "outside" the parent. The former should be restricted by the parent's bounds, right? The latter shouldn't be?

If that makes any sense, I appreciate that it isn't making things simpler as we'd hoped.

Copy link

Flaky tests detected in 4403bb9.
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/11397547769
📝 Reported issues:

if ( childBounds.width > parentRect.width ) {
childBounds.x = Math.max(
parentRect.x,
xValues.sort().at( -1 ) || 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a thought, but if we stick with the idea of caching values, do we need arrays? Could we set let maxX = 0 and only update maxX if childBounds.x is greater than it?

@aaronrobertshaw
Copy link
Contributor

In case it helps explain my early thought bubble, I've pushed a branch based off trunk that might illustrate it in code.

I'm probably missing something stupid, so I'm not intending that branch to supplant this one. If it does somehow get the job done, we can easily bring the change in here or convert that branch to a PR.

Using the alternative approach that checks if a child is within a scrollable parent this is what I get:

Navigation Submenu Test
Screen.Recording.2024-10-18.at.5.33.19.pm.mp4
Scrollable Blocks Test
Screen.Recording.2024-10-18.at.5.32.37.pm.mp4

It should be noted that this is a naive implementation, it doesn't take into account descendants of children that could be positioned in a way that would always make them visible despite being within the overall scrollable block. That's an edge case that's so contrived it could be addressed when/if it ever becomes an issue.

@t-hamano
Copy link
Contributor

Sorry for the late reply. I realized that this is a much more difficult problem than I had imagined 😅

I also wondered if there was a better approach. One approach I came up with is the following logic. I was inspired by the isScrollable function proposed by @aaronrobertshaw:

  • Check if the current element is scrollable horizontally or vertically
  • If the current element is scrollable horizontally, update the child's width and x position with that of the current element
  • If the current element is scrollable horizontally, update the child's height and y position with that of the current element

The code that actually tried this approach is below. The diff below is for the trunk branch, not for this PR:

Diff
diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js
index 9c2e813ef7..bd91fbc04e 100644
--- a/packages/block-editor/src/utils/dom.js
+++ b/packages/block-editor/src/utils/dom.js
@@ -74,6 +74,29 @@ export function rectUnion( rect1, rect2 ) {
        return new window.DOMRectReadOnly( left, top, right - left, bottom - top );
 }
 
+/**
+ * Checks if the element is horizontally scrollable.
+ *
+ * @param {Element} element Element.
+ * @return {boolean} True if the element is horizontally scrollable.
+ */
+function isHorizontallyScrollable( element ) {
+       const style = window.getComputedStyle( element );
+       return style.overflowX === 'auto' || style.overflowX === 'scroll';
+}
+
+/**
+ * Checks if the element is vettically scrollable.
+ *
+ * @param {Element} element Element.
+ * @return {boolean} True if the element is vettically scrollable.
+ */
+function isVerticallyScrollable( element ) {
+       const style = window.getComputedStyle( element );
+       console.log( style.overflowY );
+       return style.overflowY === 'auto' || style.overflowY === 'scroll';
+}
+
 /**
  * Returns whether an element is visible.
  *
@@ -149,6 +172,16 @@ export function getVisibleElementBounds( element ) {
                for ( const child of currentElement.children ) {
                        if ( isElementVisible( child ) ) {
                                const childBounds = child.getBoundingClientRect();
+                               const currentElementBounds =
+                                       currentElement.getBoundingClientRect();
+                               if ( isHorizontallyScrollable( currentElement ) ) {
+                                       childBounds.width = currentElement.clientWidth;
+                                       childBounds.x = currentElementBounds.x;
+                               }
+                               if ( isVerticallyScrollable( currentElement ) ) {
+                                       childBounds.height = currentElement.clientHeight;
+                                       childBounds.y = currentElementBounds.y;
+                               }
                                bounds = rectUnion( bounds, childBounds );
                                stack.push( child );
                        }

It seems to work fine as far as I tested it, but I'm probably missing something.

975c472d6a44561327dd23ad69f5f2ad.mp4

@ramonjd
Copy link
Member Author

ramonjd commented Oct 20, 2024

Thanks for helping out with this problem, everyone! ❤️

The isScrollable idea sounds like it's a winner so far 🥇 I'll merge the marriage of @t-hamano's and @aaronrobertshaw's changes into this one so we can continue to test.

@ramonjd
Copy link
Member Author

ramonjd commented Oct 21, 2024

@t-hamano @aaronrobertshaw Good call on the isScrollable checks. 💯

I tried both code snippets independently and they address all use cases as far as I can see.

Also tested both using window.performance and there was no measurable difference between the two (latest Chrome).

So, which do folks think? I think it's now between the fewer calls to DOM API methods.

I think try/improve-block-toolbar-positioning-alternative might elbow in as it makes only one call to getComputedStyle.

We might even get away with using the existing rectUnion(), e.g.,

diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js
index 8a7b21aaa7f..0603e9bbb1d 100644
--- a/packages/block-editor/src/utils/dom.js
+++ b/packages/block-editor/src/utils/dom.js
@@ -118,6 +118,22 @@ function isElementVisible( element ) {
 	return true;
 }
 
+/**
+ * Checks if the element is scrollable.
+ *
+ * @param {Element} element Element.
+ * @return {boolean} True if the element is scrollable.
+ */
+function isScrollable( element ) {
+	const style = window.getComputedStyle( element );
+	return (
+		style.overflowX === 'auto' ||
+		style.overflowX === 'scroll' ||
+		style.overflowY === 'auto' ||
+		style.overflowY === 'scroll'
+	);
+}
+
 /**
  * Returns the rect of the element including all visible nested elements.
  *
@@ -136,41 +152,23 @@ function isElementVisible( element ) {
  */
 export function getVisibleElementBounds( element ) {
 	const viewport = element.ownerDocument.defaultView;
+
 	if ( ! viewport ) {
 		return new window.DOMRectReadOnly();
 	}
 
-	const parentRect = element.getBoundingClientRect();
-	let bounds = parentRect;
-
+	let bounds = element.getBoundingClientRect();
 	const stack = [ element ];
-	const xValues = [];
-	const yValues = [];
 	let currentElement;
 
 	while ( ( currentElement = stack.pop() ) ) {
 		for ( const child of currentElement.children ) {
 			if ( isElementVisible( child ) ) {
-				const childBounds = child.getBoundingClientRect();
-				yValues.push( childBounds.y );
-				xValues.push( childBounds.x );
-				/*
-				 * If the child is larger than the parent, adjust the x and y values to the greatest known
-				 * to account for any scrolling.
-				 */
-				if ( childBounds.width > parentRect.width ) {
-					childBounds.x = Math.max(
-						parentRect.x,
-						xValues.sort().at( -1 ) || 0
-					);
-				}
-				if ( childBounds.height > parentRect.height ) {
-					childBounds.y = Math.max(
-						parentRect.y,
-						yValues.sort().at( -1 ) || 0
-					);
+				let childBounds = child.getBoundingClientRect();
+				// If the parent is scrollable, use parent's scrollable bounds.
+				if ( isScrollable( currentElement ) ) {
+					childBounds = currentElement.getBoundingClientRect();
 				}
-
 				bounds = rectUnion( bounds, childBounds );
 				stack.push( child );
 			}
@@ -187,12 +185,12 @@ export function getVisibleElementBounds( element ) {
 	 */
 	const left = Math.max( bounds.left, 0 );
 	const right = Math.min( bounds.right, viewport.innerWidth );
-
 	bounds = new window.DOMRectReadOnly(
 		left,
 		bounds.top,
 		right - left,
 		bounds.height
 	);
+
 	return bounds;
 }

At least, in testing, it works for me. Tell if I've missed something from your demo @aaronrobertshaw

@aaronrobertshaw
Copy link
Contributor

So, which do folks think? I think it's now between the fewer calls to DOM API methods.

I'm on board with less DOM API method calls if we aren't reinventing the wheel elsewhere. I'm also fine with Aki's version if there is a benefit to splitting the horizontal vs vertical scrollable checks.

We might even get away with using the existing rectUnion(), e.g.,

I've had a weekend to wipe my memory since I rushed that branch through Friday afternoon. I recall trying rectUnion but switching things up when trying to break it with inner children that wouldn't intersect etc. It was something I was planning to test further.

Which I'll do in a review shortly 🙂

Copy link
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

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

Thanks for all the iteration here @ramonjd 👍

I think we've narrowed in on something that works for the known uses cases.

✅ Block toolbar is correctly positioned for top most block
✅ Toolbar position is kept below content that expands outside the parent block e.g. nav submenu
✅ Scrolling content within a block does not affect the toolbar position. Works for horizontal, vertical, and dual scrolling content

Screenshot 2024-10-21 at 4 40 35 pm
Screen.Recording.2024-10-21.at.4.45.24.pm.mp4

I've tried to break the current approach but it seems pretty solid.

I could only come up with contrived examples like using fixed positioning on inner block content but even then the block toolbar would behave as it does for other scrollable content, which could be the expected behaviour.

Any unforeseen edge cases would probably warrant a deeper investigation. So in that spirit, I think we can move forward with this approach and land the fix as is for 6.7.

@ramonjd ramonjd added the Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Oct 21, 2024
@ramonjd ramonjd merged commit 484c960 into trunk Oct 21, 2024
67 checks passed
@ramonjd ramonjd deleted the try/block-toolbar-positions-overflow branch October 21, 2024 22:24
@github-actions github-actions bot added this to the Gutenberg 19.6 milestone Oct 21, 2024
@github-actions github-actions bot removed the Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Oct 21, 2024
Copy link

I just cherry-picked this PR to the wp/6.7 branch to get it included in the next release: a3c0d3c

@github-actions github-actions bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Oct 21, 2024
gutenbergplugin pushed a commit that referenced this pull request Oct 21, 2024
… of the block toolbar (#66188)

The rect bounds of blocvk child elements, specifically the x and y values, change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the block toolbar popover.

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: kevin940726 <kevin940726@git.wordpress.org>
Comment on lines +167 to +171
let childBounds = child.getBoundingClientRect();
// If the parent is scrollable, use parent's scrollable bounds.
if ( isScrollable( currentElement ) ) {
childBounds = currentElement.getBoundingClientRect();
}
Copy link
Contributor

@stokesman stokesman Oct 29, 2024

Choose a reason for hiding this comment

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

Good work on the solution and nice collaboration here. While I was tinkering around on solutions for #66438, I noticed what seems to be a minor issue here so I’m leaving this late review comment.

I know scrollable elements aren’t expected to be a common case but from what I’ve tested this is wasteful. It loops over all their children yet gets and unions the bounds from the same element each time. I spun up #66546 to address it and included some instructions on testing my claim here. I haven’t requested reviews from anyone yet since I don’t think there’s any urgency to this but I thought it better to mention while still pretty fresh.

karthick-murugan pushed a commit to karthick-murugan/gutenberg that referenced this pull request Nov 13, 2024
… of the block toolbar (WordPress#66188)

The rect bounds of blocvk child elements, specifically the x and y values, change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the block toolbar popover.

Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: kevin940726 <kevin940726@git.wordpress.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backported to WP Core Pull request that has been successfully merged into WP Core [Package] Block editor /packages/block-editor [Type] Bug An existing feature does not function as intended
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[WP 6.7] Scrollable blocks affect the position of the block toolbar
5 participants