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 & Popover component - Prevent sticky position from causing permanently obscured areas of the selected block. #33981

Merged
merged 19 commits into from
Aug 25, 2021

Conversation

Addison-Stavlo
Copy link
Contributor

@Addison-Stavlo Addison-Stavlo commented Aug 10, 2021

Description

Attempts to resolve #29464 by moving the popover beneath the block if there is no room in the editor canvas to ever allow non-sticky above block positioning for said block.

Currently (on trunk), if a block is at the top of the editor canvas the block toolbar can never be above the block and is always set to the top sticky position. This can cause many conflicts with trying to perform standard actions such as interacting with block content, child blocks, placeholder interfaces, etc. by creating a permanently obscured area of the block whenever it is selected.

In this PR, if the sticky position is enabled we check to see if there is enough room above the block for the popover to ever be at its default non-sticky position. If there is, we default to current standard behavior. If there is not, we place the popover beneath the block to eliminate permanently obscured areas of the block caused by the popover toolbar at the top sticky position.

How has this been tested?

Verify toolbar does not overlap block when possible:

  • Load the site editor, select the block at the top of the screen (probably your 'Header' block).
  • Verify that the position of the popover is at the bottom of the block and not on top of the block itself.

  • Similarly, select another block further down in the editor. Verify the toolbar is above the block as per the current expectation.

  • Test the above in the template editor as well.

  • Smoke test the post editor, there should be no changes to behavior.

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.
  • I've tested my changes with keyboard and screen readers.
  • 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 (please manually search all *.native.js files for terms that need renaming or removal).

@github-actions
Copy link

github-actions bot commented Aug 10, 2021

Size Change: +60 B (0%)

Total Size: 1.04 MB

Filename Size Change
build/block-editor/index.min.js 118 kB +22 B (0%)
build/components/index.min.js 209 kB +38 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/api-fetch/index.min.js 2.19 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.2 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/style-rtl.css 13.8 kB
build/block-editor/style.css 13.8 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 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 474 B
build/block-library/blocks/button/editor.css 474 B
build/block-library/blocks/button/style-rtl.css 605 B
build/block-library/blocks/button/style.css 604 B
build/block-library/blocks/buttons/editor-rtl.css 315 B
build/block-library/blocks/buttons/editor.css 315 B
build/block-library/blocks/buttons/style-rtl.css 370 B
build/block-library/blocks/buttons/style.css 370 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 194 B
build/block-library/blocks/columns/editor.css 193 B
build/block-library/blocks/columns/style-rtl.css 474 B
build/block-library/blocks/columns/style.css 475 B
build/block-library/blocks/cover/editor-rtl.css 666 B
build/block-library/blocks/cover/editor.css 670 B
build/block-library/blocks/cover/style-rtl.css 1.23 kB
build/block-library/blocks/cover/style.css 1.23 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 400 B
build/block-library/blocks/embed/style.css 400 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 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/gallery/editor-rtl.css 879 B
build/block-library/blocks/gallery/editor.css 876 B
build/block-library/blocks/gallery/style-rtl.css 1.7 kB
build/block-library/blocks/gallery/style.css 1.7 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 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 70 B
build/block-library/blocks/group/theme.css 70 B
build/block-library/blocks/heading/editor-rtl.css 152 B
build/block-library/blocks/heading/editor.css 152 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 283 B
build/block-library/blocks/html/editor.css 284 B
build/block-library/blocks/image/editor-rtl.css 728 B
build/block-library/blocks/image/editor.css 728 B
build/block-library/blocks/image/style-rtl.css 482 B
build/block-library/blocks/image/style.css 487 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 63 B
build/block-library/blocks/list/style.css 63 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 488 B
build/block-library/blocks/media-text/style.css 485 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 474 B
build/block-library/blocks/navigation-link/editor.css 474 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation/editor-rtl.css 1.69 kB
build/block-library/blocks/navigation/editor.css 1.69 kB
build/block-library/blocks/navigation/style-rtl.css 1.68 kB
build/block-library/blocks/navigation/style.css 1.67 kB
build/block-library/blocks/navigation/view.min.js 2.52 kB
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 310 B
build/block-library/blocks/page-list/editor.css 310 B
build/block-library/blocks/page-list/style-rtl.css 242 B
build/block-library/blocks/page-list/style.css 242 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 248 B
build/block-library/blocks/paragraph/style.css 248 B
build/block-library/blocks/post-author/editor-rtl.css 210 B
build/block-library/blocks/post-author/editor.css 210 B
build/block-library/blocks/post-author/style-rtl.css 182 B
build/block-library/blocks/post-author/style.css 181 B
build/block-library/blocks/post-comments-form/style-rtl.css 140 B
build/block-library/blocks/post-comments-form/style.css 140 B
build/block-library/blocks/post-comments/style-rtl.css 360 B
build/block-library/blocks/post-comments/style.css 359 B
build/block-library/blocks/post-content/editor-rtl.css 138 B
build/block-library/blocks/post-content/editor.css 138 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 398 B
build/block-library/blocks/post-featured-image/editor.css 398 B
build/block-library/blocks/post-featured-image/style-rtl.css 143 B
build/block-library/blocks/post-featured-image/style.css 143 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 378 B
build/block-library/blocks/post-template/style.css 379 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 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 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 361 B
build/block-library/blocks/pullquote/style.css 360 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 270 B
build/block-library/blocks/query-pagination/editor.css 262 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B
build/block-library/blocks/query-pagination/style.css 168 B
build/block-library/blocks/query-title/editor-rtl.css 85 B
build/block-library/blocks/query-title/editor.css 85 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 169 B
build/block-library/blocks/quote/style.css 169 B
build/block-library/blocks/quote/theme-rtl.css 220 B
build/block-library/blocks/quote/theme.css 222 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 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 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 374 B
build/block-library/blocks/search/style.css 375 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 462 B
build/block-library/blocks/site-logo/editor.css 464 B
build/block-library/blocks/site-logo/style-rtl.css 153 B
build/block-library/blocks/site-logo/style.css 153 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 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 165 B
build/block-library/blocks/social-link/editor.css 165 B
build/block-library/blocks/social-links/editor-rtl.css 812 B
build/block-library/blocks/social-links/editor.css 811 B
build/block-library/blocks/social-links/style-rtl.css 1.33 kB
build/block-library/blocks/social-links/style.css 1.33 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 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 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 636 B
build/block-library/blocks/template-part/editor.css 635 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/term-description/editor-rtl.css 90 B
build/block-library/blocks/term-description/editor.css 90 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 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/common-rtl.css 1.29 kB
build/block-library/common.css 1.29 kB
build/block-library/editor-rtl.css 9.95 kB
build/block-library/editor.css 9.93 kB
build/block-library/index.min.js 150 kB
build/block-library/reset-rtl.css 527 B
build/block-library/reset.css 527 B
build/block-library/style-rtl.css 11 kB
build/block-library/style.css 11 kB
build/block-library/theme-rtl.css 658 B
build/block-library/theme.css 663 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/blocks/index.min.js 47 kB
build/components/style-rtl.css 15.7 kB
build/components/style.css 15.8 kB
build/compose/index.min.js 10.2 kB
build/core-data/index.min.js 12.4 kB
build/customize-widgets/index.min.js 11.1 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.53 kB
build/edit-navigation/index.min.js 13.6 kB
build/edit-navigation/style-rtl.css 3.15 kB
build/edit-navigation/style.css 3.14 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 28.8 kB
build/edit-post/style-rtl.css 7.2 kB
build/edit-post/style.css 7.2 kB
build/edit-site/index.min.js 26.2 kB
build/edit-site/style-rtl.css 5.07 kB
build/edit-site/style.css 5.07 kB
build/edit-widgets/index.min.js 16 kB
build/edit-widgets/style-rtl.css 4.06 kB
build/edit-widgets/style.css 4.06 kB
build/editor/index.min.js 37.7 kB
build/editor/style-rtl.css 3.74 kB
build/editor/style.css 3.73 kB
build/element/index.min.js 3.17 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 5.36 kB
build/format-library/style-rtl.css 668 B
build/format-library/style.css 669 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.59 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.49 kB
build/keycodes/index.min.js 1.25 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.88 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.28 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.6 kB
build/server-side-render/index.min.js 1.32 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.72 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 6.27 kB
build/widgets/style-rtl.css 1.05 kB
build/widgets/style.css 1.05 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@Addison-Stavlo Addison-Stavlo changed the title WIP - investigating solutions for block toolbar on first block of site editor. Popover component - When sticky element, prefer bottom positioning if available. Aug 11, 2021
@Addison-Stavlo Addison-Stavlo self-assigned this Aug 11, 2021
@Addison-Stavlo Addison-Stavlo marked this pull request as ready for review August 11, 2021 15:54
@jasmussen
Copy link
Contributor

Nice 🔥 — this is working really well for the header in the site editor, and I feel validates the initial idea:

site editor

The behavior change does surface a side effect that might not be ideal: the toolbar changes position even if it started at the top, which feels jumpy in the post editor:

post editor

For comparison, before it was sticky:

before

Can we tweak the heuristic so that the block toolbar only ever shows up below the block if that's where it started? I.e. once you select the block, its permanent position thereafter is chosen:

  • If there's space for the toolbar to start above the block, that's where it stays and remains sticky on scroll
  • If there isn't space for the toolbar above, then it starts below the block and stays there

What do you think?

Nice work.

@Addison-Stavlo
Copy link
Contributor Author

Addison-Stavlo commented Aug 12, 2021

Thanks for taking a look @jasmussen !

The behavior change does surface a side effect that might not be ideal: the toolbar changes position even if it started at the top, which feels jumpy in the post editor:

A little jumpy, yes. But I actually really like this behavior. The idea is that the toolbar does not impair any view or interaction with the corresponding block unless there is no other option and it is completely necessary to do so. To me, a small jump of the popover is much more preferable than having something stuck in the way of the item I am trying to edit.

While jumpiness of items in the editor has been a concern, I think the jumpiness of a popover seems minor and much more forgivable than the sort of jumpiness we have seen in the past that actually causes a shift in the layout of blocks in the editor canvas itself.

Can we tweak the heuristic so that the block toolbar only ever shows up below the block if that's where it started? I.e. once you select the block, its permanent position thereafter is chosen:
If there's space for the toolbar to start above the block, that's where it stays and remains sticky on scroll
If there isn't space for the toolbar above, then it starts below the block and stays there
What do you think?

Besides impairing the block when unnecessary, I think this idea has a handful of challenges technically and im not really sure how we would go about doing so. Right now, the popover component has no awareness of the previous states of the editor, and makes its calculations based off the current point in time. This makes sense for a general component. I can't currently think of a good way to add this sort of awareness and control without conflating concerns across package boundaries, inflating data stores, and still requiring a lot more complex logic hammered out around all possible edge cases. Although, maybe there is a much easier way to go about this that I am missing.

Right now the approach is reflexive to the current state of the editor at any given point in time. As a result the logic is very simple, well contained, simple to maintain, and has a much lower probability to introduce any bugs.

If we were to move away from the reflexive approach and towards the more controlled approach based off previous editor states I think the scope of this will inflate very quickly, have much more complicated logic that is more difficult to maintain, require specific handling for every edge case, and have a much higher probability of unexpected bugs.

@jasmussen
Copy link
Contributor

Good thoughts. I agree that if at all possible we should avoid obscuring content, and it's why the Top Toolbar option remains. In this case however, moving the block toolbar below a short paragraph just obscures the next paragraph instead of the preceeding one.

The behavior is definitely valid for the popover component in cases where it means opening dropdown menus and the like. In the case of the block toolbar, my understanding is that it leveraging the popover is mostly a matter of extracting it from the DOM (to enable things like the iframe and such). I understand that writing a unique behavior just for this part of the interface is less optimal than a generic solution that works for the component as a whole, but being such a primary interface for the editor, I think it's important that we find a way forward that avoids the jump when it isn't necessary.

Is there any path forward that isn't too complicated that would allow us to keep the sticky/scrolling behavior for a toolbar that starts above the block? Could it be a prop to toggle the behavior? For what it's worth, @ellatrix has had a desire to move additional block UI from the editing canvas into popovers, including for example the in-canvas inserter. Such a change would very probably leverage the same behavior.

@Addison-Stavlo
Copy link
Contributor Author

Is there any path forward that isn't too complicated that would allow us to keep the sticky/scrolling behavior for a toolbar that starts above the block? Could it be a prop to toggle the behavior?

Possibly! I need more time to think about it and investigate. Often the simple solutions don't emerge until I have spent too much time thinking about the overly complicated ones. 😆 Il keep digging.

In this case however, moving the block toolbar below a short paragraph just obscures the next paragraph instead of the preceding one.

Yes, but its better to obscure the block you aren't currently editing than the block that you are trying to edit. Obviously I really prefer the jumpiness of popover when scrolling offscreen to obscuring the selected block, but Im happy to continue to investigate your proposed behavior as well.

The behavior is definitely valid for the popover component in cases where it means opening dropdown menus and the like.

This behavior is actually only applied when the __unstableStickyBoundaryElement prop is given to the popover, which seems to only happen from the block-popover's implementation.

@annezazu annezazu added [Package] Interface /packages/interface [Type] Bug An existing feature does not function as intended General Interface Parts of the UI which don't fall neatly under other labels. labels Aug 12, 2021
@Addison-Stavlo
Copy link
Contributor Author

@jasmussen - I think thats a bit closer to what you were suggesting.

Theres still some jumpyness to take care of at the bottom of the editor, when the toolbar starts below the block and you scroll down so it moves off the page. But if we leverage another stickyPosition at the bottom of the editor we could make it sticky there until it gets to a point where it makes sense resetting to the top position. 🤔

@Addison-Stavlo
Copy link
Contributor Author

Addison-Stavlo commented Aug 13, 2021

Updated with a bottom sticky position, so I think this has gotten rid of all the jumpiness.

When the block popover mounts if it is initially in a state that would put it in sticky position it is moved underneath the block instead, otherwise it just retains the previous existing behavior. It remains in this bottom location until we scroll down far enough that the toolbar moves underneath the page, at this point it stays at the new bottom sticky position. If we continue to scroll such that the block moves off the screen, the popover is then reset to have the default behavior (top of block positioning):

sticky-bottom-no-jumpy

Theres 1 more edge case that I am noticing at the moment. If a block is tall enough that neither its top or bottom boundaries are in the editor, selecting the block defaults the toolbar to the bottom sticky position instead of the top. I assume we want this to be at the top sticky position since that is the current behavior, but I could see some merits to it being at the bottom in this circumstance as well (edit - I think thats probably just because I was looking at it in a very very short browser window, Il get this edge case fixed early next week).

Anyways, let me know how the current state of the PR feels to you. And if you happen to stumble across any other edge cases 😆 .

@jasmussen
Copy link
Contributor

Thanks so much for sticking on this. I still think it's a powerful feature. Here's what I see:

hey

This is working much better than before, especially for basic writing flows.

However I think we might still want to go with the behavior where if it starts above the block, always keep it there, if it starts below the block, allow it to flip above the block if space becomes available. The reason is sort of shown in the GIF itself — you might select a block where it starts above, then scroll, deselect and select again. Suddenly the block toolbar is below the block, even if you scroll up, which makes it appear as if it belongs to the block below.

That makes it feel important to have "above the block" be the canonical and default place for the toolbar, and then have the other cases be edgecases that revert back to that as soon as possible.

What do you think?

@jasmussen
Copy link
Contributor

Nice one, this is what I see:

this

I think this is pretty good and definitely close. I would appreciate more opinions, though.

If I was to change a single thing, it would probably be related to keeping the toolbar above the block as much as we possibly can. In this case, the behavior is now right for the viewport, in that if there isn't space to see the toolbar perfectly above the block where you scrolled to, it will be below the block. But if we could change that so it's relative to the document itself, I think it might be even better, so:

  • If there isn't room for the block toolbar because we are at the very beginning of the document, show it below with the current heuristic.
  • If we've scrolled down the page a bunch, and there's space in the content above the block — even if it will get sticky-pushed-down, we still show it above the block.

What do you think?

@Addison-Stavlo
Copy link
Contributor Author

What do you think?

I think that makes sense, it will keep things very consistent yet solve the problem for blocks that don't have any room above them regardless of scroll position. 👍

@Addison-Stavlo
Copy link
Contributor Author

Addison-Stavlo commented Aug 18, 2021

@jasmussen how does this feel currently? I think its close to what you were describing.

While this behavior is probably on the more simple end of our iterations, its the only one so far that has required updates to other packages as well due to needing to access the content wrapper for the editor canvas. Here we set up a new section in the block-editor store for the canvas wrapper element. It is set when the iframe component initializes the class on the content wrapper, then selected from the store when we pass props from block-popover to the actual popover component which then uses it for evaluation.

Back to discussing edge case about the exceedingly tall block as the first item in the editor: At this point if there isn't visual room below the block it defaults to normal behavior (sets the toolbar in the top sticky position) and has some jumpiness when you scroll as the popover shifts to the bottom of the block once there is room. This doesn't seem correct as 1 - it has the unnecessary jumpiness and 2 - the top section of the block is always obscured when it is visible and the block is selected.

Im thinking for this edge case what might make sense is adding that bottom sticky position back in, then the popover will be sticky at the bottom position until there is visually room beneath the block. This would both get rid of the jumpiness as well as allow every section of the block to be un-obscurable. Its a bit different than our default behavior to have it sticky at the bottom of the editor, but it seems like it might make sense to solve the problems in that case. Thoughts?

@jasmussen
Copy link
Contributor

Awesome, this is what I see:

fse

posts

To me, this threads the needle and fixes the original issue. I know it's somewhat conservative, but it seems safer to start that way and then expand as we go.

At this point if there isn't visual room below the block it defaults to normal behavior (sets the toolbar in the top sticky position) and has some jumpiness when you scroll as the popover shifts to the bottom of the block once there is room

Indeed. I wasn't immediately able to reproduce, even if I tried with a very tall group. Can you provide a GIF of what you're seeing? It's hard to know exactly what feels the most right there. Instinctively I'd lean conservative and suggest that if there isn't a good obvious place below the block (like when selecting the header in the FSE example above), then we should always defer to the default behavior. But I might be missing a beat.

Thanks so much for working on this 👌

@Addison-Stavlo
Copy link
Contributor Author

Addison-Stavlo commented Aug 18, 2021

Can you provide a GIF of what you're seeing?

Of course!

tall-block-behavior

  • Here we select the ridiculously tall header, since there is no room beneath the block the toolbar goes to the normal top sticky position.
  • Once we scroll down and there is room beneath the block, the toolbar jumps to that bottom position. At this point the bottom position feels useless, as the only sections of the block it serves to un-obscure are sections that could be un-obscured by scrolling anyways. But even if we keep it at top-sticky instead we would have an issue: a permanently obscured zone.

The concern I have here is that the top section of the block (what is underneath the block toolbar when we are scrolled all the way to the top), is always obscured when it is in view. This could prevent users from being able to interact with a child block in that location or other interfaces that may exist with really no way to get around it. If we added a bottom-of-editor sticky position that would only be seen in this odd edge case, then all sections of the block will be free and unobscured at some point in the available scrolling positions.

@jasmussen
Copy link
Contributor

Oh that's a good one, thank you for the GIF that was very helpful. So basically, if the topmost block is taller than the viewport, we get this. I feel like we might want to go for the simplest solution here just so the benefits of this PR can land for what's probably the majority of cases, and depending on how often we encounter that case we can revisit.

I understand the complexity this adds to the positioning behavior already, so I'm definitely tempted to not want to add further to it. But if a "bottom sticky" feature as you describe can be built without adding too much complexity, and leverage that behavior only for this case, when the block is at the top of the document but also taller than the viewport, then it seems like it could work well.

@Addison-Stavlo
Copy link
Contributor Author

Addison-Stavlo commented Aug 19, 2021

if a "bottom sticky" feature as you describe can be built without adding too much complexity, and leverage that behavior only for this case, when the block is at the top of the document but also taller than the viewport, then it seems like it could work well.

Its definitely an addition that doesnt require much complexity. About a +2 -1 loc change that makes some of the placement logic a little more simple too. 03404b1

That situation would look like this now:

bottom-sticky-again

So if there is no room above the block in the canvas (regardless of scroll - so basically just the top block), we just return the minimum (higher in editor) position between the bottom of the block and bottom sticky position. Thus the bottom sticky position should only be seen if both the block is at the very top of the editor canvas and is taller than the viewport.

@jasmussen
Copy link
Contributor

Just from a glance, this looks to me like it could work, nice. Seems like this one mostly needs a code review, and then it'd be nice to try it! 👍 👍

@Addison-Stavlo Addison-Stavlo changed the title Popover component - When sticky element, prefer bottom positioning if available. Block Toolbar & Popover component - Prevent sticky position from causing permanently obscured areas of the selected block. Aug 19, 2021
@Addison-Stavlo
Copy link
Contributor Author

Seems like this one mostly needs a code review, and then it'd be nice to try it!

Awesome, agreed! Updated PR description and this should be ready for review.

Copy link
Contributor

@Copons Copons left a comment

Choose a reason for hiding this comment

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

Thanks @Addison-Stavlo, this works great! ❤️

I've left a few comments, almost all minor.
My major concern is storing the iframe ref in the Redux store. I guess it's not a big deal per se, but I don't recall other similar examples, and I wonder if there are alternative ways to achieve the same thing. 🤔

packages/block-editor/src/components/iframe/index.js Outdated Show resolved Hide resolved
packages/block-editor/src/store/reducer.js Outdated Show resolved Hide resolved
packages/components/src/popover/utils.js Show resolved Hide resolved
Copy link
Contributor

@Copons Copons left a comment

Choose a reason for hiding this comment

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

GO! GO! GO! ✨

@Addison-Stavlo Addison-Stavlo merged commit 60d907b into trunk Aug 25, 2021
@Addison-Stavlo Addison-Stavlo deleted the try/fix-block-toolbar-over-block-content branch August 25, 2021 12:55
@github-actions github-actions bot added this to the Gutenberg 11.5 milestone Aug 25, 2021
@creativecoder
Copy link
Contributor

Nice work @Addison-Stavlo ! I really appreciate the attention to detail here in refining the toolbar placement ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
General Interface Parts of the UI which don't fall neatly under other labels. [Package] Interface /packages/interface [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Contextual block toolbar: Move below the block when bumping against the top edge
5 participants