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

[WIP] Layout: Explore adding in sticky position support within the layout support #44723

Closed
wants to merge 14 commits into from

Conversation

andrewserong
Copy link
Contributor

@andrewserong andrewserong commented Oct 6, 2022

What?

🚧 🚧 🚧 🚧 🚧 WIP: This is nowhere near ready for testing yet 🚧 🚧 🚧 🚧 🚧

This PR is an early exploration into storing position and related data as part of the Layout object, in an effort to come up with a solution for #30121. This expands on ideas earlier explored in #38039.

Related to: #30121

Why?

It'll be useful for many kinds of sites to be able to set one or two group blocks or template areas to be sticky positioned in order to anchor a header or footer to the top or the bottom of the page.

How?

TBC

Note: much of this is hacked together for now — all the changes in 6.1 files should be moved elsewhere prior to stabilising the PR.

To-do

  • Wire up the attributes.layout.position value to style output in both the editor and on the site frontend (e.g. in the layout output in layout.php)
  • Switch layout.position to be an object, as there are likely related values that need to be stored. For example, we need the position type (e.g. sticky) as well as the particular edge it should be close to top, bottom, etc. Also, we might want an offset value if elements are to be set slightly off from being adjacent to the edge of the viewport.
  • Include related rules to offset based on the presence of the logged in admin area.
  • In the output include an inferred z-index value to ensure that the sticky positioned element sits where it should. Edit: at the moment this is hard-coded.
  • In the editor, figure out how we deal with z-index and ensuring that the element can be reached appropriately via List View, clicking on the element, etc, and all inspector / toolbar controls are still behaving as expected
  • Even with a hard-coded z-index value, the block toolbar appears to scroll off the screen when using sticky position
  • Might not be required for an MVP, but me might also want to look into overriding scroll-padding-top when setting a header in the site editor (e.g. this rule)
  • Explore the right place to store the position object in block attributes. Should it live in the layout object, or in the style object? There are trade-offs either way.

Testing Instructions

For testing purposes, for now, let's focus on looking just at the Group block

  1. Open up the block editor, add a group block and put a paragraph inside it, and give the group block a background color
  2. In the inspector controls, set the Area to top/header, and position to Sticky
  3. Scroll down, and the block should stick to the top of the screen
  4. Publish the post or page, and on the site frontend, the block should stick to the top as you scroll, and factor in the height of the logged-in admin bar when it is visible

Screenshots or screencast

WIPs:

Editor Site frontend

@andrewserong andrewserong added [Status] In Progress Tracking issues with work in progress [Type] Experimental Experimental feature or API. [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Feature] Layout Layout block support, its UI controls, and style output. labels Oct 6, 2022
@andrewserong andrewserong self-assigned this Oct 6, 2022
@andrewserong andrewserong changed the title Layout: Explore adding in position support within the layout object [WIP] Layout: Explore adding in position support within the layout object Oct 6, 2022
@andrewserong andrewserong marked this pull request as draft October 6, 2022 05:52
@github-actions
Copy link

github-actions bot commented Oct 6, 2022

Size Change: +15 kB (+1%)

Total Size: 1.3 MB

Filename Size Change
build/block-editor/index.min.js 176 kB +7.4 kB (+4%)
build/block-editor/style-rtl.css 15.9 kB +149 B (+1%)
build/block-editor/style.css 15.9 kB +139 B (+1%)
build/block-library/blocks/group/editor-rtl.css 654 B +260 B (+66%) 🆘
build/block-library/blocks/group/editor.css 654 B +260 B (+66%) 🆘
build/block-library/blocks/latest-comments/style-rtl.css 298 B +14 B (+5%) 🔍
build/block-library/blocks/latest-comments/style.css 298 B +14 B (+5%) 🔍
build/block-library/blocks/latest-posts/style-rtl.css 478 B +15 B (+3%)
build/block-library/blocks/latest-posts/style.css 478 B +16 B (+3%)
build/block-library/blocks/navigation-link/editor-rtl.css 712 B +7 B (+1%)
build/block-library/blocks/navigation-link/editor.css 711 B +8 B (+1%)
build/block-library/blocks/navigation/editor-rtl.css 2.15 kB +116 B (+6%) 🔍
build/block-library/blocks/navigation/editor.css 2.16 kB +116 B (+6%) 🔍
build/block-library/blocks/navigation/style-rtl.css 2.21 kB +19 B (+1%)
build/block-library/blocks/navigation/style.css 2.2 kB +21 B (+1%)
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB +27 B (+1%)
build/block-library/blocks/query-pagination/style-rtl.css 288 B +6 B (+2%)
build/block-library/blocks/query-pagination/style.css 284 B +6 B (+2%)
build/block-library/blocks/query/editor-rtl.css 440 B +1 B (0%)
build/block-library/blocks/query/editor.css 440 B +1 B (0%)
build/block-library/blocks/table/editor-rtl.css 505 B +11 B (+2%)
build/block-library/blocks/table/editor.css 505 B +11 B (+2%)
build/block-library/blocks/table/style-rtl.css 631 B +20 B (+3%)
build/block-library/blocks/table/style.css 631 B +22 B (+4%)
build/block-library/blocks/table/theme-rtl.css 172 B -18 B (-9%)
build/block-library/blocks/table/theme.css 172 B -18 B (-9%)
build/block-library/editor-rtl.css 11.5 kB +253 B (+2%)
build/block-library/editor.css 11.4 kB +247 B (+2%)
build/block-library/index.min.js 194 kB +1.33 kB (+1%)
build/block-library/style-rtl.css 12.4 kB +47 B (0%)
build/block-library/style.css 12.4 kB +42 B (0%)
build/block-library/theme-rtl.css 704 B -15 B (-2%)
build/block-library/theme.css 708 B -14 B (-2%)
build/blocks/index.min.js 49.9 kB +15 B (0%)
build/components/index.min.js 203 kB +154 B (0%)
build/components/style-rtl.css 11.5 kB +220 B (+2%)
build/components/style.css 11.5 kB +220 B (+2%)
build/edit-navigation/index.min.js 16.2 kB +59 B (0%)
build/edit-navigation/style-rtl.css 4.06 kB +64 B (+2%)
build/edit-navigation/style.css 4.06 kB +66 B (+2%)
build/edit-post/index.min.js 34.4 kB +281 B (+1%)
build/edit-post/style-rtl.css 7.39 kB +63 B (+1%)
build/edit-post/style.css 7.38 kB +59 B (+1%)
build/edit-site/index.min.js 61 kB +2.89 kB (+5%) 🔍
build/edit-site/style-rtl.css 8.4 kB +28 B (0%)
build/edit-site/style.css 8.37 kB +17 B (0%)
build/edit-widgets/index.min.js 16.7 kB +64 B (0%)
build/edit-widgets/style-rtl.css 4.41 kB +68 B (+2%)
build/edit-widgets/style.css 4.41 kB +69 B (+2%)
build/editor/index.min.js 43.7 kB +71 B (0%)
build/keycodes/index.min.js 1.83 kB +2 B (0%)
build/rich-text/index.min.js 10.7 kB +49 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.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/index.min.js 7.09 kB
build/block-directory/style-rtl.css 990 B
build/block-directory/style.css 991 B
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 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 84 B
build/block-library/blocks/avatar/style.css 84 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 482 B
build/block-library/blocks/button/editor.css 482 B
build/block-library/blocks/button/style-rtl.css 532 B
build/block-library/blocks/button/style.css 532 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 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 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 406 B
build/block-library/blocks/columns/style.css 406 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 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.55 kB
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/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 346 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 948 B
build/block-library/blocks/gallery/editor.css 950 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/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 327 B
build/block-library/blocks/html/editor.css 329 B
build/block-library/blocks/image/editor-rtl.css 880 B
build/block-library/blocks/image/editor.css 880 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 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-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 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/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/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 363 B
build/block-library/blocks/page-list/editor.css 363 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-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 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 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 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 315 B
build/block-library/blocks/post-featured-image/style.css 315 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 282 B
build/block-library/blocks/post-template/style.css 282 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-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 326 B
build/block-library/blocks/pullquote/style.css 325 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-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 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 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 409 B
build/block-library/blocks/search/style.css 406 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 464 B
build/block-library/blocks/shortcode/editor.css 464 B
build/block-library/blocks/site-logo/editor-rtl.css 490 B
build/block-library/blocks/site-logo/editor.css 490 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 322 B
build/block-library/blocks/spacer/editor.css 322 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 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 235 B
build/block-library/blocks/template-part/editor.css 235 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 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 691 B
build/block-library/blocks/video/editor.css 694 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 162 B
build/block-library/classic.css 162 B
build/block-library/common-rtl.css 1.02 kB
build/block-library/common.css 1.02 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/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/compose/index.min.js 12.2 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 kB
build/data-controls/index.min.js 653 B
build/data/index.min.js 8.08 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.7 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/editor/style-rtl.css 3.6 kB
build/editor/style.css 3.59 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/experiments/index.min.js 868 B
build/format-library/index.min.js 6.95 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.77 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/list-reusable-blocks/index.min.js 2.13 kB
build/list-reusable-blocks/style-rtl.css 835 B
build/list-reusable-blocks/style.css 835 B
build/media-utils/index.min.js 2.93 kB
build/notices/index.min.js 963 B
build/nux/index.min.js 2.06 kB
build/nux/style-rtl.css 732 B
build/nux/style.css 728 B
build/plugins/index.min.js 1.94 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.58 kB
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.21 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/server-side-render/index.min.js 1.77 kB
build/shortcode/index.min.js 1.53 kB
build/style-engine/index.min.js 1.48 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.61 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.08 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.21 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.19 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@andrewserong
Copy link
Contributor Author

I've experimented in b4d0801 with adding position output to the layout support, so that the rules are output as part of those rules (and so we can add additional rules as needed). It seems to be working okay in the editor for now (with a hard-coded magic value for z-index so that it works correctly):

2022-10-12 17 12 58

Will continue hacking on this tomorrow and have a go at adding the server-side output, too.

@andrewserong
Copy link
Contributor Author

andrewserong commented Oct 12, 2022

Another challenge, for both z-index and popovers, is figuring out how to ensure that the toolbar doesn't scroll off the page when a sticky block is selected: 🤔

2022-10-13 10 09 42

@andrewserong andrewserong force-pushed the try/add-sticky-position-as-part-of-layout branch from b4d0801 to 27b2a43 Compare October 13, 2022 05:45
@andrewserong
Copy link
Contributor Author

In 27b2a43, I've added in server-rendering support, which also factors in the admin bar for the top position when using a fixed or sticky position type:

2022-10-13 16 47 11

A couple of further thoughts from that change:

  • For fixed headers, I imagine we'll likely want to eventually add a scroll-padding-top offset (like this rule), but it may not be a blocker for an MVP
  • I'm pleased that server-rendering appears to be working pretty well, but I'm unsure if the layout object is the right place for these values to live — server-rendering seems to be the right way to go, but perhaps position should live in style so that isn't quite so coupled to layout. In terms of block attributes, maybe style.layout.position? E.g. if in the future the layout classes move to the innerBlock wrapper, then the position should still be applied to the outer wrapper — that seems to indicate there'll be at least some difference there
  • Still need to figure out a good default z-index value that plays nicely in the editor (e.g. with the block toolbar), as well as on the site frontend
  • How much should occur in the style engine versus in the block support (the perennial question)
  • This feature requires adding additional position-related CSS properties to the list of allowed CSS properties — this may not be desired. Along with the existing cases for display, we'll either want to pursue whether or not to add these properties as allowed in core, or if we want an escape hatch in the style engine for particular allow-listed CSS properties — ones that we allow in certain circumstances, but not globally. Just a thought.

@andrewserong andrewserong changed the title [WIP] Layout: Explore adding in position support within the layout object [WIP] Layout: Explore adding in sticky position support within the layout support Oct 13, 2022
@andrewserong
Copy link
Contributor Author

I'm wrapping up for the week, and busy with other things next week, so will pick this up again after that. Just jotting down some additional notes, after brainstorming a little with @tellthemachines and @ramonjd.

Tasks to try next:

  • Flatten data structure for position object so that the props resemble the CSS properties more closely, move to style.layout.position possibly, so that either in this PR or in the future, we can hook in the style engine for processing the position from the style object if need be.
  • Add position’s own output / attachment to wrapper element so that the default layout approach can safely move to innerBlocks and not worry about what position is doing. This means that the work in Try adding layout classnames to inner block wrapper #44600 would not have to be concerned with the needs of the position output (which should always be attached to the outer wrapper).
  • Try out the lowest reasonable z-index value — z-index appears to be required because in the block editor, blocks are set to relative via the .block-editor-block-list__block classname (most likely so that toolbars, etc can be neatly overlaid). It'd be good to try to settle on a z-index value that just works, and allows things like the navigation block menu popover to be overlaid.

@javierarce
Copy link
Contributor

Testing this PR I noticed that changing the "Inner blocks use content width" setting resets both the Area and Position settings.

@andrewserong
Copy link
Contributor Author

Testing this PR I noticed that changing the "Inner blocks use content width" setting resets both the Area and Position settings.

Thanks! I'll fix that up.

Copy link
Contributor

@tellthemachines tellthemachines 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 this most interesting experiment!

My first attempt at testing didn't work, and it took me a while to work out that the sticky position only works if the container of the sticky block is bigger than the sticky block itself. This can become a major usability obstacle because the block nesting structure has to be just so for it to work as expected. I'm not sure what the best way to tackle this might be, but some thoughts:

  • add some guiding text when "sticky" is selected as an option, to the effect that the block will only stick to its immediate container;
  • could we only enable this support for blocks that aren't the only child of their container? Or even only for top-level blocks?
  • build some custom sticky functionality with JS instead of the native CSS? 🙈 Clutching at straws here 😅

'declarations' => array(
'position' => $position_type,
$position_side => $offset_value,
'z-index' => '250', // TODO: This hard-coded value should live somewhere else.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we get away with a lower value? In testing it seems to work fine with 2. In the editor the current value is interfering with the toolbars and block appenders so in any case will need a bit of tweaking!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we can definitely play with the value here. I'll have a play with a lower value 👍

packages/block-editor/src/hooks/layout.js Show resolved Hide resolved
isBlock
>
{ POSITION_OPTIONS.map( ( option ) => (
<ToggleGroupControlOption
Copy link
Contributor

Choose a reason for hiding this comment

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

The interaction here feels a bit awkward, I wonder if it could just be a toggle to "stick block to top or bottom" which when toggled on would show the area controls?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, good point! Yes, happy to play with the design. In this PR I was mostly copying what's in the screenshots in #30121, but it's pretty bulky having both an Area and a Position section. It'd be good if we can come up with a way to group them together. I like your idea of a toggle... I wonder how it'd work if and when we have fixed as an option in addition to sticky?

@andrewserong
Copy link
Contributor Author

Thanks for taking this for a spin @tellthemachines!

I'm not sure what the best way to tackle this might be, but some thoughts:

Good thoughts, there! I think it'd be good to see how far we can get with native CSS output rather than adding in JS, and try out some of the suggested ideas about when we do or do not show the controls.

While the current use case is thinking of a global header or footer, another potential one is for headings in a glossary that stick to the top as you scroll down a really long page. Having a block that's intentionally within the post content area of a page template could be useful in that sense, so that it's not globally sticky. However allowing that kind of thing in a user friendly way is probably not simple!

Another thought is that sticky behaves quite differently in CSS to fixed in that it relates to the parent container instead of globally, so I wonder if it'll be useful for users to be able to choose between the two (though exposing fixed would likely create a bunch of additional challenges in the editor UI).

To expand on some of your suggestions, some other potential considerations for the controls:

  • Only allow in the site editor / template editor?
  • Only allow at root level, or first child of a template part?

In terms of usability, there's also the idea that if we refactor the Layout panel to use the ToolsPanel, then we might have these controls be hidden by default. In that case, folks would (hopefully) only be reaching for them when they need them, which might possibly help mitigate the usability issues a bit, though that's probably not safe to rely on 🤔

Thanks again for the thoughts and testing everybody!

@andrewserong andrewserong force-pushed the try/add-sticky-position-as-part-of-layout branch from b5f84d0 to 0b7cbb2 Compare October 24, 2022 06:51
@andrewserong
Copy link
Contributor Author

andrewserong commented Oct 24, 2022

I've pushed a couple of code quality changes in 0b7cbb2. This flattens the data a little, and moves it over to the style object, which is a better home for things that more closely resemble CSS values. The new structure also allows for offset values in the future (say, if someone wants their block to not be directly adjacent to the edge of the viewport). The data is now stored in style.layout in the block's attributes. So in real-world usage, here is a sticky group block set to the top position:

<!-- wp:group {"style":{"layout":{"position":"sticky","top":"0px"}},"backgroundColor":"vivid-red","textColor":"background","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-background-color has-vivid-red-background-color has-text-color has-background"><!-- wp:paragraph -->
<p>A paragraph</p>
<!-- /wp:paragraph --></div>
<!-- /wp:group -->
  • style.layout.position — a string containing the position type, e.g. sticky, fixed
  • style.layout.top — the value for the top position
  • style.layout.right — the value for the right position
  • style.layout.bottom — the value for the bottom position
  • style.layout.left — the value for the left position

This structure also allows us to add other values in the future, if we wish to set them at the block level. E.g. style.layout.zIndex. It also fixes the issue that @javierarce mentioned above, where toggling the 'use content width' toggle cleared out the position values. The position values should now be preserved when adjusting other layout attributes. I've also enabled the top / footer buttons to toggle the values on and off.

Still to do from the earlier to-do list (in addition to exploring the more recent feedback):

  • Add position’s own output / attachment to wrapper element so that the default layout approach can safely move to innerBlocks and not worry about what position is doing. (This needs to be updated in both JS and PHP)
  • Try out the lowest reasonable z-index value, as in the comments above from @tellthemachines

@ramonjd
Copy link
Member

ramonjd commented Oct 28, 2022

This is testing very well manually, thank you @andrewserong !!

I created a new template!

2022-10-28.15.48.01.mp4

Maybe you know about this, but this is what the layout controls look like in Global styles:

Screen Shot 2022-10-28 at 3 46 40 pm

@andrewserong
Copy link
Contributor Author

Thanks for taking this for a spin @ramonjd!

Maybe you know about this, but this is what the layout controls look like in Global styles:

This issue is currently on trunk, too, and a fix is being explored / discussed over in: #45340

@andrewserong andrewserong force-pushed the try/add-sticky-position-as-part-of-layout branch from 1b8e1b5 to a106a00 Compare November 3, 2022 01:08
@andrewserong
Copy link
Contributor Author

Update: I'll be AFK off and on over the next couple of weeks, so just jotting down some notes and thoughts for next things to work on with this PR, for when I come back to it:

  • A blocker for this PR is that we will need to add position support for template parts, as for sticky to work correctly at the site-wide level (for a global header or footer), it needs to be applied to root level blocks. This way you could apply sticky directly to the Header or Footer template parts, instead of setting it on the first Group child of those blocks. However, if you opt-in the template part block to __experimentalLayout, and go to update a template part in the site editor to set the position and then hit save, it does not save the block attributes. I imagine there's some nuance here surrounding what happens that the template part block wrapper level, and what happens within a template part block? This will be something to look into.
  • The block toolbar positioning doesn't play nicely with sticky positioning, in that if you scroll the window, the toolbar moves as if the block is static rather than sticky, so we lose the toolbar.
  • We'll need to decide how things should behave on mobile, or across mobile and desktop. I.e. a site with a large header on desktop that can comfortably be sticky, but on mobile should be static, or a header that should be sticky on mobile but static on desktop.
  • Still need to experiment with a good baseline z-index value and try out the idea of setting quite a low value.
  • The controls are fairly clunky and will be infrequently used, so it might be best to explore switching the LayoutPanel to the ToolsPanel before trying to stabilise this PR (LayoutPanel: Switch to using the ToolsPanel #44560).
  • The controls will need to include being able to select top or bottom at least, as well as normal / sticky.

@jameskoster
Copy link
Contributor

Nice work on this so far. Sticky positioning is working well for root level group blocks on the frontend, but I did notice that the effect isn't present in the editor.

A blocker for this PR is that we will need to add position support for template parts

I'm not convinced we should do this, and would not consider it a blocker to this PR. My general feeling is that position is an abstract concept that can be applied to any block within the context of a document. That is to say: it's the responsibility of a template to define whether its header is sticky or not.

One thing that seems important is for the values in the UI to match the CSS behaviour. IE a "Sticky" block should effectively just have position: sticky applied. This means it won't be possible to fix a footer to the bottom of the viewport until we add fixed positions. I think that is fine. Getting the experience for sticky positioning right is a big task on its own, and we shouldn't get bogged down in creating specific experiences for template parts yet. I think it would be fine to focus purely on adding position: sticky in this PR.

@annezazu
Copy link
Contributor

annezazu commented Nov 7, 2022

Update: I'll be AFK off and on over the next couple of weeks, so just jotting down some notes and thoughts for next things to work on with this PR, for when I come back to it

Just want to check in as I'm doing the weekly update for phase 2 tasks -- do you need any extra help or back up considering the on and off AFK? Would love to make momentum continues.

@andrewserong
Copy link
Contributor Author

andrewserong commented Nov 7, 2022

do you need any extra help or back up considering the on and off AFK?

Thanks for checking in @annezazu — Joen and James have added useful feedback for when I’m back, so I plan to dig into those ideas. There are a few things to figure out with this proposed feature, as I imagine we’re going to encounter quite a few edge cases!

The main thing that I think would help with momentum would be for folks to test out this PR, have a go at setting some Group blocks to “sticky” and report back usability thoughts and feedback, that’ll help give a fuller picture of the edge cases that’ll need to be addressed. A good use case for folks to test is “I want a site with a sticky header, can I achieve this by setting a Group block in the header area in the site editor to use sticky + top position”. If the answer is “no”, then let’s figure out the missing things required to getting it working acceptably.

In terms of help with the code side of things, if anyone is free to jump in and wants to work on the code — feel free to fork this PR or commit directly to it, though I understand it can be tricky to jump into a WIP, so I’ve got some other suggestions below. I’ll comment here again when I’m back, so happy to work with anyone who might’ve picked anything up. However, the most useful things to look at I think would be:

  • If anyone would like to investigate how to make the block toolbar play nicely with sticky/fixed blocks — when you select a sticky block, the block toolbar should be in an easy to reach place and be visible at all times when scrolling in the block editor while the block is selected. I’m not sure what will be involved in fixing this issue, so that would be the most helpful task from my perspective.
  • A dependency for this PR is to switch the LayoutPanel over to use the ToolsPanel so that position controls can be hidden by default. This change will need to land before this PR will become viable. My plan was to pick up this task when I’m back, but I’d be very happy if anyone else wanted to give it a go: LayoutPanel: Switch to using the ToolsPanel #44560

Hope that helps! Let me know if you need any more info here.

@paaljoachim
Copy link
Contributor

Testing
Using the Gutenberg PR build.
Twenty Twenty Three
WordPress 6.1
Site Editor

Before:

Screenshot 2022-11-08 at 10 45 01

After:

Adding sticky to Header.
Clicking top area icon.
Adding a green color to the background.

Screenshot 2022-11-08 at 10 56 13

Sticky did not work in the backend or frontend.

This is what I looked for.
Clicking Position I expected the border around the sticky Group block to change to reflect that I have done something to modify the Group block. Perhaps a dashed border outline to show that the state of the Group block has changed from Normal to Sticky.

@jameskoster
Copy link
Contributor

A good use case for folks to test is “I want a site with a sticky header, can I achieve this by setting a Group block in the header area in the site editor to use sticky + top position”

Could we amend that to simply: "I want to make a Group block stick to the top of the viewport as I scroll past it"? Throwing template parts (particularly footers) into the mix at this stage is making things overly complex. Adding the position: sticky functionality is a nice enhancement on its own (the Table of Contents block will appreciate!) and we need to get that right before moving on to the more intricate use cases.

Joen updated #30121 with the latest mockups.

@andrewserong
Copy link
Contributor Author

Could we amend that to simply: "I want to make a Group block stick to the top of the viewport as I scroll past it"? Throwing template parts (particularly footers) into the mix at this stage is making things overly complex.

Great point @jameskoster. Yes, I think for this PR let's limit the scope to the Group block, whatever we can do to implement this incrementally sounds good 👍.

Joen updated #30121 with the latest mockups.

Awesome, thanks for that. Just left a follow-up comment over there to make sure I understand the goal for the initial implementation 🙂

Sticky did not work in the backend or frontend.

Thanks for testing @paaljoachim! I think in that example it's to do with sticky being applied at a non-root level so the area that it affects isn't site wide. I think for the moment this means that (at least with this PR) we're better off pursuing the suggestion James made to just focus on the Group block at the moment, rather than template parts.

Then, once this PR lands we can look at the flow for switching on position for template parts (or a group block that is a parent of a template part) in a follow up.

@andrewserong
Copy link
Contributor Author

Update: I've updated this PR and simplified the UI controls to match the latest designs in #30121 — toggling between Default and Sticky now also sets top: 0 as well as position: sticky, so it seems to be working pretty well now without a separate Area or Placement control: (Note: it does sort of stick out there at the bottom of the list of controls, but it sorta looks a little odd at the top as well, happy for any feedback there)

image

It does still take up a fair bit of room for a control that will (most likely) be used only in a couple of places, so I've progressed forward with the idea of converting the LayoutPanel over to using the ToolsPanel in a separate PR over in: #45833 — that seems to have been going pretty well, the only major issue so far is that there isn't quite enough room between the Justification and Orientation controls for the gutter. I've added a screenshot in this comment: #45833 (comment)

As for the remaining issues in this PR, next up I'll take a look at:

  • The issue of the block toolbar's positioning when you go to scroll down the page (currently the toolbar scrolls off the screen for sticky blocks)
  • Z-index tweaking


if ( position === 'sticky' || position === 'fixed' ) {
// TODO: Work out where to put the magic z-index value.
output += `z-index: 250`;
Copy link
Member

Choose a reason for hiding this comment

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

Could the z-index be defined in theme.json layout.definitions, e.g., is-layout-sticky similar to is-layout-flow?

🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just jotting down a note here that it might make sense to have some preset-like values for z-index stored in settings.layout.zIndexSticky or if we want support for multiple z-indexes, then perhaps an array of z-indexes for different purposes. That way we could have a core default z-index value for sticky / fixed position, but themes could then override it with their own values if need be.

@jameskoster
Copy link
Contributor

Thanks for updating this, it seems to be working well.

We probably need to do something with the helper text – at the moment it's only describing the sticky option. For now it may even make sense to use a switch here:

Screenshot 2022-11-21 at 11 01 07

I think this may be more intuitive. I acknowledge that it prohibits fixed positions, but I don't think that's a big problem for now, as that use case needs further design consideration. What do you think @jasmussen ?

@jasmussen
Copy link
Contributor

Thanks for the PR, thanks for the ping, taking for a spin and seeing the toggle work really well:

status

This is super nice.

  • I think Jay may be right, that a simple toggle may be better fow now. It has a smaller visual footprint.
  • Unless you're scrolled, there's no visual effect in the canvas. That suggests to me we should a) have it be a non default toolspanel control (✅ I've seen the separate PR) and that we do need the help text.

But perhaps we don't need the "Position" subheading. Just like how there isn't a "content width" subheading for this:

Screenshot 2022-11-21 at 13 29 54

— just the toggle, and maybe it could say "Stick to the top"?

@jasmussen
Copy link
Contributor

So, thinking more about this, and from good advice from a friend, it behooves us to consider an interface that can at least scale to additional properties in the future, and perhaps it would be frustrating to see the toggle replaced with a segmented control at a later time. So I tried one more option:

Sticky toggle

  • It keeps the toggle, with two options, Sticky and Fixed.
  • "Default" is gone, because it would be the same as removing the control from the ToolsPanel.
  • A small control grid appears on "Fixed", similar to that which exists in the Cover block toolbar, which allows a basic 9 grid of positions for the fixed position control.

As far as near term, we could still go with just "Sticky" as a starting point, and have "Default" and "Sticky" options inside the segmented control. Or we could simplify the positional control with something like this:

fixed toggle

But it would still be useful to consider a design that can naturally evolve to the additional controls. Let me know your thoughts! @jameskoster I'd love your thoughts on this. It breaks a few rules 😅 Figma

@andrewserong
Copy link
Contributor Author

Thanks for the extra discussion! Happy to implement whichever of the designs folks think will work for the first iteration of the feature.

I think if we use a single on/off toggle, then I agree that removing the Position label sounds good. If we retain the Default/Sticky options, then keeping the heading seems better to me. I also like the idea of retaining Default in the UI in some way, even if we add Fixed as an extra option in a follow-up — as a user, I'd like to be able to toggle it off immediately without having to dig into the ToolsPanel menu.

I like the idea of the X and Y position offsets, too — that'll allow some pretty cool advanced behaviour further down the track. To begin with, though, I reckon if we can keep it to "switch to sticky sets it to top: 0" that'll help us with keeping things simple. I really love seeing these explorations for where we might take things in follow-ups, though! 😀

@jameskoster
Copy link
Contributor

@jasmussen It all depends on how far we want to take this, which isn't 100% clear to me. Do we want a control(s) that is able to entertain the full gamut of css position (including absolute and relative which both have their place)? Or do we want UIs that are tailored for specific use cases (IE fixed header / footer)? Or do we want both? :)

I'm happy to work on whatever, but it's quite a big task and will be tricky to get right. That's kind of why I suggested the simple toggle to begin with, but maybe it's not useful enough on its own?

@jasmussen
Copy link
Contributor

Do we want a control(s) that is able to entertain the full gamut of css position (including absolute and relative which both have their place)? Or do we want UIs that are tailored for specific use cases (IE fixed header / footer)? Or do we want both? :)

I think the answer is that it isn't entirely clear how far we'd want to go, for example my current instinct is that we should avoid "relative" as an option, and ideally provide an interface that makes you not need to worry about relative at all.

I was also reminded that in one design we have items in all 4 corners, like this:

8Gg-WI59th

How's that accomplished? Is it a two full-width flex-between navigation bars, top and bottom fixed respectively? Or is it 4, each of which is fixed to a corner? And are those positioned using a simple cover-block like matrix, or are those easier to accomplish with x/y coordinates? Or even top/right/bottom/left inputs?

We don't have to accomplish all of this, I still think it's a great idea to start with as little as possible, e.g. sticky as it doesn't require any positioning. But what I realized is that it would probably be a better interface if what we ship today can naturally evolve into what we might ship next year. I.e. if we know we'll need a segmented control in the future, perhaps we shouldn't start with a toggle — even if initially that seemed like a simpler design. What do you think?

@jameskoster
Copy link
Contributor

if we know we'll need a segmented control in the future

My point is simply that I'm not convinced we do know that. But if your conviction is strong then let's stick with it because I haven't explored this issue with a microscope just yet 😁

Otherwise we have two options:

  1. Go with the toggle for now, and revise it later
  2. Postpone implementation while we perform a deeper dive on the design side

I have no strong feelings either way.

@jasmussen
Copy link
Contributor

My point is simply that I'm not convinced we do know that. But if your conviction is strong then let's stick with it because I haven't explored this issue with a microscope just yet 😁

That's the thing, I don't know for sure! But it's the best of the options I came up with, mainly because it's hard to find icons to denote the nuance between "fixed" vs. "sticky". A dropdown as also explored previously is another option:

Screenshot 2022-11-22 at 14 12 47

Mainly my point is, I would think we have reasonable confidence that we do want to add fixed (plus some positioning controls) in the future, and in that case, the toggle wouldn't scale.

@jameskoster
Copy link
Contributor

Okay. The only other problem I see is that the segmented control needs to include at least 2 values, so we'll need to either:

  1. Implement sticky and fixed positioning at the same time.
  2. Include a 'Default' or 'Static' value.

Did you have a preference?

@jasmussen
Copy link
Contributor

Right, that's the challenge of the moment, where "Default" really doesn't make too much sense if the control is a non-default control. But I think we can probably include it regardless, even without Fixed, — just like how you can add the Dropcap control and toggle it off. Then when we get a chance to add Fixed in the future, we can choose whether we want 3 options, or can do without the Default at that point. What do you think?

@jameskoster
Copy link
Contributor

So you mean this?

Screenshot 2022-11-22 at 14 37 34

I guess it's fine, the only part I'm not sure about is the help text. In this context shouldn't the description speak about the control itself, rather than the specific values therein?

@andrewserong
Copy link
Contributor Author

Great questions and discussion, folks! Just my 2 cents, but since it's very easy for controls to become quite complex as we consider more advanced use cases, I think I'd lean toward a simple control to begin with (focusing on the main use case of stick-to-top), accepting that we'll likely wind up exploring a very different control at some point next year when we attempt the more complex use cases.

In this context shouldn't the description speak about the control itself, rather than the specific values therein?

Good question — I suppose we can have the help text be descriptive of the current state, and have it say something different depending on the option currently selected, a bit like we do for the help text next to the "Inner blocks use content width" control?

@jameskoster
Copy link
Contributor

I opened a discussion here to further discuss the design.

@andrewserong
Copy link
Contributor Author

Thanks for all the feedback on this PR, folks! Based on the latest discussions, and since the technical implementation needed to change a bit to decouple from the Layout block support, I've opened up a separate PR for continued exploration over in: #46142 — that PR is now the current one for future work on this feature (with discussion happening over in #46032), so I'll close out this PR now.

@priethor priethor removed the [Status] In Progress Tracking issues with work in progress label Jan 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Feature] Layout Layout block support, its UI controls, and style output. [Type] Experimental Experimental feature or API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants