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

Fix Navigation accessibility issues #36292

Merged
merged 7 commits into from
Nov 10, 2021
Merged

Conversation

tellthemachines
Copy link
Contributor

Description

Fixes issue mentioned in This comment. When display: contents is used on an element, all its semantics are lost, so screen readers won't read out the content correctly.

I removed all instances of display: contents and instead added an optional setCascadingProperties flag to the layout config which, when enabled, outputs the flex config as custom properties, so they can be used by descendant elements.

In the process of fixing this, I also noticed there is an aria-hidden on wp-block-navigation__responsive-container that's hiding the whole nav contents from screen readers. I removed it altogether, because nav content is already hidden from screen readers with display: none when responsive menu is enabled and in closed mode.

How has this been tested?

  1. Add a Navigation block with a few links in it.
  2. Customise its layout, save and view the front end.
  3. Check that everything displays correctly.
  4. With a screen reader, check that the list semantics in the Navigation are read out correctly.

Screenshots

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.
  • [ x] 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).

@tellthemachines tellthemachines changed the title Fix/display contents issue Fix Navigation accessibility issues Nov 8, 2021
@tellthemachines tellthemachines added [Block] Navigation Affects the Navigation Block [Type] Bug An existing feature does not function as intended Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Nov 8, 2021
@github-actions
Copy link

github-actions bot commented Nov 8, 2021

Size Change: +302 B (0%)

Total Size: 1.09 MB

Filename Size Change
build/block-editor/index.min.js 137 kB +65 B (0%)
build/block-library/blocks/navigation-submenu/style-rtl.css 205 B +10 B (+5%) 🔍
build/block-library/blocks/navigation-submenu/style.css 203 B +8 B (+4%)
build/block-library/blocks/navigation/style-rtl.css 1.53 kB +29 B (+2%)
build/block-library/blocks/navigation/style.css 1.51 kB +25 B (+2%)
build/block-library/blocks/page-list/style-rtl.css 172 B +55 B (+47%) 🚨
build/block-library/blocks/page-list/style.css 172 B +55 B (+47%) 🚨
build/block-library/index.min.js 161 kB +14 B (0%)
build/block-library/style-rtl.css 10.3 kB +21 B (0%)
build/block-library/style.css 10.3 kB +20 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.17 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/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/style-rtl.css 14.4 kB
build/block-editor/style.css 14.4 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 470 B
build/block-library/blocks/button/editor.css 470 B
build/block-library/blocks/button/style-rtl.css 560 B
build/block-library/blocks/button/style.css 560 B
build/block-library/blocks/buttons/editor-rtl.css 292 B
build/block-library/blocks/buttons/editor.css 292 B
build/block-library/blocks/buttons/style-rtl.css 275 B
build/block-library/blocks/buttons/style.css 275 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 206 B
build/block-library/blocks/columns/editor.css 205 B
build/block-library/blocks/columns/style-rtl.css 503 B
build/block-library/blocks/columns/style.css 502 B
build/block-library/blocks/cover/editor-rtl.css 546 B
build/block-library/blocks/cover/editor.css 547 B
build/block-library/blocks/cover/style-rtl.css 1.17 kB
build/block-library/blocks/cover/style.css 1.17 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 417 B
build/block-library/blocks/embed/style.css 417 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 977 B
build/block-library/blocks/gallery/editor.css 982 B
build/block-library/blocks/gallery/style-rtl.css 1.6 kB
build/block-library/blocks/gallery/style.css 1.59 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 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 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 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 731 B
build/block-library/blocks/image/editor.css 730 B
build/block-library/blocks/image/style-rtl.css 507 B
build/block-library/blocks/image/style.css 511 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 94 B
build/block-library/blocks/list/style.css 94 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 493 B
build/block-library/blocks/media-text/style.css 490 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 642 B
build/block-library/blocks/navigation-link/editor.css 642 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-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/editor-rtl.css 1.93 kB
build/block-library/blocks/navigation/editor.css 1.93 kB
build/block-library/blocks/navigation/view.min.js 2.74 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 377 B
build/block-library/blocks/page-list/editor.css 377 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 273 B
build/block-library/blocks/paragraph/style.css 273 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/style-rtl.css 347 B
build/block-library/blocks/post-comments-form/style.css 347 B
build/block-library/blocks/post-comments/style-rtl.css 492 B
build/block-library/blocks/post-comments/style.css 493 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 396 B
build/block-library/blocks/post-featured-image/editor.css 397 B
build/block-library/blocks/post-featured-image/style-rtl.css 156 B
build/block-library/blocks/post-featured-image/style.css 156 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 391 B
build/block-library/blocks/post-template/style.css 392 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 378 B
build/block-library/blocks/pullquote/style.css 378 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 262 B
build/block-library/blocks/query-pagination/editor.css 255 B
build/block-library/blocks/query-pagination/style-rtl.css 234 B
build/block-library/blocks/query-pagination/style.css 231 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 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 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 397 B
build/block-library/blocks/search/style.css 398 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 245 B
build/block-library/blocks/separator/style.css 245 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 770 B
build/block-library/blocks/site-logo/editor.css 770 B
build/block-library/blocks/site-logo/style-rtl.css 165 B
build/block-library/blocks/site-logo/style.css 165 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 177 B
build/block-library/blocks/social-link/editor.css 177 B
build/block-library/blocks/social-links/editor-rtl.css 824 B
build/block-library/blocks/social-links/editor.css 823 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB
build/block-library/blocks/social-links/style.css 1.32 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 560 B
build/block-library/blocks/template-part/editor.css 559 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 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 815 B
build/block-library/common.css 812 B
build/block-library/editor-rtl.css 9.88 kB
build/block-library/editor.css 9.88 kB
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-library/theme-rtl.css 668 B
build/block-library/theme.css 673 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 46 kB
build/components/index.min.js 213 kB
build/components/style-rtl.css 15.3 kB
build/components/style.css 15.3 kB
build/compose/index.min.js 10.9 kB
build/core-data/index.min.js 12.8 kB
build/customize-widgets/index.min.js 11.2 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.16 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.44 kB
build/edit-navigation/index.min.js 15.9 kB
build/edit-navigation/style-rtl.css 3.76 kB
build/edit-navigation/style.css 3.76 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 29.4 kB
build/edit-post/style-rtl.css 7.12 kB
build/edit-post/style.css 7.12 kB
build/edit-site/index.min.js 28 kB
build/edit-site/style-rtl.css 5.32 kB
build/edit-site/style.css 5.32 kB
build/edit-widgets/index.min.js 16.4 kB
build/edit-widgets/style-rtl.css 4.17 kB
build/edit-widgets/style.css 4.18 kB
build/editor/index.min.js 37.5 kB
build/editor/style-rtl.css 3.78 kB
build/editor/style.css 3.77 kB
build/element/index.min.js 3.21 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 6.49 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.72 kB
build/keycodes/index.min.js 1.3 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.91 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.19 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.8 kB
build/server-side-render/index.min.js 1.52 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.82 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@jasmussen
Copy link
Contributor

Nice, very fast work. I see this generally working as intended.

One small issue for this PR. Beause the modal overlay menu is always vertical (at least until a future where its contents can be edited in isolation), it should always be top-aligned. And so when the flex-direction changes from the horizontal navigation menu to the vertical navigation menu, so does the workings of align-items and justify-content. At the moment when the navigation is justified right (or presumably anything other than left), the overlay menu is bottom aligned:

navigation

By the way, the CSS variables here we can probably leverage to fix the issue with menu opening direction — i.e. opening the menu down and left when the navigation is justified right. Does this make sense?

@jasmussen
Copy link
Contributor

By the way, the CSS variables here we can probably leverage to fix the issue with menu opening direction — i.e. opening the menu down and left when the navigation is justified right. Does this make sense?

No, it did not make sense. My idea was to use use one of the new justification CSS variables to set the right: 0; which is needed for the dropdown container to be right aligned, and set that based on the var() fallback variable. Basically use it as a true/false. It's not going to work for us.

Outside of restoring the is-justified-* classnames, I'm going to quickly explore whether we can flex the submenus somehow. I don't think we can, I still think we need the position: absolute;, but just to be sure I'll give that some thought.

display: flex;
flex-wrap: var(--layout-wrap, wrap);
flex-direction: var(--layout-direction, initial);
justify-content: var(--layout-justify, initial);
Copy link
Contributor

Choose a reason for hiding this comment

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

In a quick test, the following seems to have fixed it for me:

Suggested change
justify-content: var(--layout-justify, initial);
justify-content: flex-start;

Can you think of any reason this shouldn't work?

Copy link
Contributor

Choose a reason for hiding this comment

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

This fixes left, center, right:
Screenshot 2021-11-08 at 08 58 16

Screenshot 2021-11-08 at 08 58 27

Screenshot 2021-11-08 at 08 59 56

Screenshot 2021-11-08 at 08 58 38

Screenshot 2021-11-08 at 09 00 11

Screenshot 2021-11-08 at 08 58 51

Space between gets weird, I'll look at what I can do there:
Screenshot 2021-11-08 at 09 00 38

@jasmussen
Copy link
Contributor

Alright I took the liberty of committing a better fix than the one I suggested in #36292 (comment). It works for me, for both vertical and horizontal menus:
nav

Copy link
Contributor

@jasmussen jasmussen left a comment

Choose a reason for hiding this comment

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

This is a good step on the path, incredibly fast work, thank you.

The PHP linter appears to be wanting single quotes, but it seems an easy fix and then we can land this.

@jasmussen
Copy link
Contributor

I'm looking at some issues in a separate PR, and realized that when a text label is long enough to wrap, the button element will keep it centered:

Screenshot 2021-11-08 at 11 53 18

So I moved the text-alignment rule to the submenu block directly.

@tellthemachines
Copy link
Contributor Author

Thanks for the review and improvements @jasmussen !

No, it did not make sense. My idea was to use use one of the new justification CSS variables to set the right: 0; which is needed for the dropdown container to be right aligned, and set that based on the var() fallback variable. Basically use it as a true/false. It's not going to work for us.

We could do something like this, but we'd need to set a new custom property conditionally if layout is (or isn't) right aligned. Something like:

--layout-aligned-right: true;

I'm not sure about this approach because it adds logic to the layout calculations that is super specific to the nav use case. The other custom properties can potentially be useful for any block with complex markup, but submenu alignment is unlikely to occur elsewhere. How likely is it that we'd need to hook arbitrary styles to a specific alignment in other blocks?

The JS approach you hint at in #36241 would be the best if we can get it right (which won't be easy, based on all the issues we've had with the Popover component 😅 ) but perhaps in the meantime the most harmless patch would be to add a bit of custom logic to the Navigation edit that checks the layout value and adds a justified-right classname whenever it's right aligned. I'll look into that as a follow-up.

Outside of restoring the is-justified-* classnames, I'm going to quickly explore whether we can flex the submenus somehow. I don't think we can, I still think we need the position: absolute;, but just to be sure I'll give that some thought.

With flex we'd still need a classname or something to tell us the direction though, wouldn't we? I'm assuming you were thinking of something like flex-direction: row-reverse for right alignment?

@jasmussen
Copy link
Contributor

but perhaps in the meantime the most harmless patch would be to add a bit of custom logic to the Navigation edit that checks the layout value and adds a justified-right classname whenever it's right aligned. I'll look into that as a follow-up.

Yep, the idea of a invalid custom property with a number fallback was out there. I just wanted to share since I mentioned having an idea, and every once in a while it inspires better ideas. I do agree that we probably need the justification classes in the interim.

One thought, though: if we are starting to think about #36241 as a longer term solution, it seems like that approach would also need classes, right? Something like a programmatically added class to the submenu container a la open-leftwards, even on subsequent submenu containers down the hierarchy, should they bump against the edge again. If that's the case, then we could embrace those classes now, and just apply them to the top level submenu container based on justification, and then in the future apply them to all submenu containers based on viewport. Let me know if that made sense.

With flex we'd still need a classname or something to tell us the direction though, wouldn't we? I'm assuming you were thinking of something like flex-direction: row-reverse for right alignment?

Yes, I wasn't able to remove the use of position-absolute, and unless we specifically set the right: 0; left: auto; max-width: n; then the container won't expand in the right direction.

In any case, this is a good first step, thank you again.

@tellthemachines
Copy link
Contributor Author

if we are starting to think about #36241 as a longer term solution, it seems like that approach would also need classes, right?

Not necessarily. If it works like the Popover component, it'll read the position of the parent element in the viewport and then position itself accordingly. All the positioning is done with JS, so the classes aren't needed.

@tellthemachines tellthemachines deleted the fix/display-contents-issue branch November 10, 2021 04:19
@github-actions github-actions bot added this to the Gutenberg 12.0 milestone Nov 10, 2021
@noisysocks noisysocks 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 Nov 10, 2021
noisysocks pushed a commit that referenced this pull request Nov 10, 2021
* Fix display contents accessibility issue in Navigation

* Remove aria-hidden from navigation wrapper.

* Fix content justification in overlay nav.

* Fix for alignment inside overlay menu.

* Move text align rule.

* Revert "Fix content justification in overlay nav."

This reverts commit 5170bb5bb3b9ead314a1ecec68768f2fe2511804.

* Fix php lint errors.

Co-authored-by: jasmussen <[email protected]>
@andrewserong andrewserong mentioned this pull request Nov 10, 2021
28 tasks
andrewserong pushed a commit that referenced this pull request Nov 10, 2021
* Fix display contents accessibility issue in Navigation

* Remove aria-hidden from navigation wrapper.

* Fix content justification in overlay nav.

* Fix for alignment inside overlay menu.

* Move text align rule.

* Revert "Fix content justification in overlay nav."

This reverts commit 5170bb5bb3b9ead314a1ecec68768f2fe2511804.

* Fix php lint errors.

Co-authored-by: jasmussen <[email protected]>
@andrewserong
Copy link
Contributor

Cherry picked into the Gutenberg 11.9 release in: 0ee7f3b

@jasmussen
Copy link
Contributor

jasmussen commented Nov 10, 2021

Not necessarily. If it works like the Popover component, it'll read the position of the parent element in the viewport and then position itself accordingly. All the positioning is done with JS, so the classes aren't needed.

Sounds good. I was thinking classes because the properties to set could, maybe beneficially, be inherited. Imagine this deliberately insane menu:

Group 4

6 gray boxes, 6 submenu containers, pseudo code:

  • Imagine the first one with .opens-right. That assigns it left: 0; right: auto;.
  • The nested submenu, by virtue of being a child (.opens-right .submenu-container) is given left: 100%; right: auto;, which indents it the width of its parent.
  • The 3rd box, nested submenu number 2 is detected to be close to the right screen edge, and is assigned .opens-left. By virtue of being a nested child of .opens-right it inherits the left: 100%; right: auto;, but children from here on out, boxes 4 and 4 now inherit differently: left: auto; right: 100%;

And so on. The idea being that we can avoid some potentially gnarly inline px values that need to be updated onresize with some relatively simple inheritance values.

It might be overthinking it, it might be better as you suggest, but I thought I'd mention it as a potentially basic way to only assign classes based on whether the screen edge is about to be hit.

Edit: Oh and thanks for landing this one! 👏

@@ -103,14 +103,26 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
*/
if ( ! empty( $layout['justifyContent'] ) && array_key_exists( $layout['justifyContent'], $justify_content_options ) ) {
$style .= "justify-content: {$justify_content_options[ $layout['justifyContent'] ]};";
// --justification-setting allows children to inherit the value regardless or row or column direction.
$style .= "--justification-setting: {$justify_content_options[ $layout['justifyContent'] ]};";
if ( ! empty( $layout['setCascadingProperties'] ) && $layout['setCascadingProperties'] ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

My first reaction here is that I don't like this to be honest, it breaks the "layout" abstraction to solve a specific use-case.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

It feels to me like we're tweaking the layout abstraction here to suit the navigation block while we should be thinking about abstraction in a more generic way. Maybe this indicates that the navigation block shouldn't be using the default "flex layout" or implementing its own custom layout?

Or maybe it indicates that we need iterations on the layout like this PR tries to do but I'm not understanding what this is trying to do at the abstraction level.

I guess what I'm trying to say is that when applying a layout to a block, that block shouldn't need to define styles that override the structural styles, these styles are provided by the layout, meaning there's no need for awareness of these CSS variables inside the block or for its children ideally.

@youknowriad
Copy link
Contributor

Can we do something about this ? I'm really concerned about leaking this into 5.9.

Also, there's a related notice maybe on trunk (just opening an simple post on the frontend)

Screen Shot 2021-12-06 at 9 15 37 AM

@youknowriad
Copy link
Contributor

Actually, the notice is related to another layout change in #36681

@matiasbenedetto
Copy link
Contributor

matiasbenedetto commented Dec 6, 2021

#37113 is a potential fix for the issue mentioned by @youknowriad.

@tellthemachines
Copy link
Contributor Author

Can we do something about this ? I'm really concerned about leaking this into 5.9.

Migrating Navigation block to flex layout was flagged as a high priority item in the Navigation tracking issue: #35521

Unless we come up with a better way of making layout work on blocks with complex HTML, the only alternative I see is to roll back layout for the Navigation block altogether.

It feels to me like we're tweaking the layout abstraction here to suit the navigation block while we should be thinking about abstraction in a more generic way. Maybe this indicates that the navigation block shouldn't be using the default "flex layout" or implementing its own custom layout?

Layout as it was initially didn't work for the Navigation block because it has multiple containers inside it that each need to have flex styles applied to them, and those styles are required to change when justification or orientation is changed. setCascadingProperties is a flag that adds all the necessary CSS properties to set the current justification/orientation as custom properties, so they can work across however many layers of markup the block has.

This was the best solution I could find to the problem of using layout in blocks with complex markup structures. We may not have any other core blocks with this problem (I can't think of any offhand) but there are likely to be 3rd party blocks that will benefit from this. It's generic enough that any container block that is more than a single wrapper around its inner blocks can leverage it, and having setCascadingProperties default to false means the custom properties are only added if we explicitly enable them.

(If layout worked with classnames, as the previous justification controls did, this solution wouldn't be necessary. It's essentially a workaround for the shortcomings of auto-generated styles, allowing us to leverage the cascade through custom properties instead of classnames.)

Having said that, layout may not be the best solution for Navigation. We've had to add back a couple of the legacy classnames due to issues with submenu layout and child blocks inheriting orientation: #36340. We've also had feedback from extenders that the classnames were useful for other purposes: #36525

The major upside of using layout is being able to set both orientation and justification as layout properties, where before orientation was a block variation. Layout makes it easier to try out different settings, with the controls all in the same place. I can't see any other way of achieving that short of introducing yet another custom control, which should be avoided.

I guess what I'm trying to say is that when applying a layout to a block, that block shouldn't need to define styles that override the structural styles, these styles are provided by the layout, meaning there's no need for awareness of these CSS variables inside the block or for its children ideally.

This isn't an override, more an extension. The styles defined by layout aren't being replaced, but in order for the layout to be applied correctly to the block markup, they are being provided as custom properties so the inner wrappers of the block can use them.

I see the intention of not wanting the block's internals or its children to be aware of the layout styles, but that will only work for blocks that are composed of a single HTML element wrapping their inner blocks. That may be the case for most core blocks, because we keep core blocks pared down to the essentials, but for any slightly more elaborate markup layout will fail. (Say for whatever reason the block has a header, and the layout styles are only meant to apply to its inner content area. Or that it has two content areas, and layout needs to apply to both their inner contents. In any of these scenarios, we need the flex styles to cascade.)

When (if) we have better accessibility support for display:contents, we might be able to use that instead, but that won't be for the foreseeable future.

It's not clear to me what the best solution is. Any feedback appreciated!

@youknowriad
Copy link
Contributor

Thanks for the explantation, It's a hard problem indeed and I don't see a perfect solution.

The styles defined by layout aren't being replaced, but in order for the layout to be applied correctly to the block markup, they are being provided as custom properties so the inner wrappers of the block can use them.I

$style .= "--layout-justification-setting: {$justify_content_options[ $layout['justifyContent'] ]};";
$style .= '--layout-direction: row;';
$style .= "--layout-wrap: $flex_wrap;";
$style .= "--layout-justify: {$justify_content_options[ $layout['justifyContent'] ]};";
$style .= '--layout-align: center;';

The layout properties used here are justifyContent, flexWrap and orientation, the generated CSS variables are 5 not 3. We're basically generating implementation details as CSS variables which is concerning for me.

The other concern for me is that this is an adhoc fix. Why limit the generation of these variables to only the "flex" layout and only these specific variables, why not everything. From a block and API point of view, the logic is not clear. Basically, we just exposed what we needed to fix the navigation issue.

The last concern for me is that exposing APIs should be done very carefully.

I see the intention of not wanting the block's internals or its children to be aware of the layout styles, but that will only work for blocks that are composed of a single HTML element wrapping their inner blocks. That may be the case for most core blocks, because we keep core blocks pared down to the essentials, but for any slightly more elaborate markup layout will fail.

I'm not sure I agree with this, I think it's something that works for most blocks, I think elaborate blocks should probably rely on inner blocks.. That said, I agree that it's just guesses at the moment and that's why we need to be careful with exposing APIs at the moment. For me, if we're not able to provide an good abstraction that the block author shouldn't have to know about internals (implementation details), we shouldn't build this abstraction entirely as it's just makes creating blocks harder.


When (if) we have better accessibility support for display:contents, we might be able to use that instead, but that won't be for the foreseeable future.

Do we have any idea about the current support? Can we consider this as an incentive or progressive enhancement? Should we rollback the layout support for now in the navigation block?

@tellthemachines
Copy link
Contributor Author

The layout properties used here are justifyContent, flexWrap and orientation, the generated CSS variables are 5 not 3.

We have to generate both --layout-justify and --layout-align for the justification property, because we use one or the other depending on what the orientation is. --layout-justification-setting is the only variable specific to the navigation case, because it's used to inherit justification in the responsive menu, where orientation is always vertical regardless of the value of layout orientation. (Arguably it could be useful in other situations where the mobile layout is different from the desktop one, but there's no evidence for that so far.)

We're basically generating implementation details as CSS variables which is concerning for me.

Apart from --layout-justification-setting, I wouldn't see these as implementation details, because they follow the flexbox model, which is pretty much our only implementation option here. The layout type is even called "flex"; it's unlikely we'll refactor it to use floats anytime soon 😅 .

We could hypothetically remove --layout-justification-setting, but we'd have to generate all the legacy justification classnames inside the Nav block so we could hook the responsive menu styles to them. I guess we could go further and generate orientation classnames too, and that would provide us with a way of using layout for Navigation without needing those custom properties output, but it will bloat the CSS for the block and its children quite a bit.

Why limit the generation of these variables to only the "flex" layout and only these specific variables, why not everything

This isn't needed for the "flow" layout, because there are no justification/orientation options, so it only makes sense to generate them for "flex". If we add a "grid" layout at some point, it might be useful to have these too, at least until subgrid gains wider support. The specific variables are all the ones needed to inherit the flex layout properties at a child element level; unless I'm missing something there are no other values provided by that layout type.

I think elaborate blocks should probably rely on inner blocks.. That said, I agree that it's just guesses at the moment and that's why we need to be careful with exposing APIs at the moment

I'd love to have more info on this too. From looking at block plugins out in the wild, there are all sorts of custom layout alignment/orientation options, so it seems there's a need for a solid core API. But I'm worried that layout without the custom properties, or some other solution that allows for styles to cascade, is too inflexible to be of use except in the most basic cases.

For me, if we're not able to provide an good abstraction that the block author shouldn't have to know about internals (implementation details), we shouldn't build this abstraction entirely as it's just makes creating blocks harder.

I think block authors will always have to know something about the implementation. For instance, if layout styles are only applied to the block wrapper and don't cascade, the block author needs to know this. Layout will never just magically work on a block regardless of its markup; it assumes a very specific markup structure. Likewise, authors need to know that the styles are generated, and no classnames are provided that they can hook custom styles to.

Providing a bunch of ready-made controls that output some CSS or some classnames is already a huge help to block authors, who would otherwise have to build their own controls. But I think some flexibility that allows space for custom styles and markup will be needed if we want this API to be adopted by extenders.

Do we have any idea about the current support? Can we consider this as an incentive or progressive enhancement?

Safari and iOS Safari are our blockers here. Sadly there's no sign of the bug being fixed just yet, and because Safari is the browser most used with VoiceOver we can't use display: contents with any semantic markup until it's fixed. There's no chance of progressive enhancement because the bug makes the Navigation inaccessible.

Should we rollback the layout support for now in the navigation block?

I'm super reluctant to do this, because it would mean reverting to the horizontal/vertical block variations, which is a much worse experience in my opinion.

If we really don't want the custom properties in layout, we could try generating classnames inside the Nav block as I suggested above. The downside is it's another API that we're putting out there, and #36525 suggests theme authors will leverage these classnames, so it'll be hard to remove them down the line. But at least the classnames would be specific to the Nav block, unlike the custom properties API.

@youknowriad
Copy link
Contributor

Apart from --layout-justification-setting, I wouldn't see these as implementation details, because they follow the flexbox model, which is pretty much our only implementation option here.

I think that's the wrong way to look at the layout abstraction, "flex" is an implementation detail of the "Flex layout" even if they share the name. We're not abstracting the DOM positioning tools but more UI layouts people want to achieve. http://every-layout.dev is a good inspiration and mental modal for this.

This isn't needed for the "flow" layout, because there are no justification/orientation options, so it only makes sense to generate them for "flex".

I don't like when we make API decisions for specific use-cases. Basically you're saying that no block will ever need the "widths" for the flow layout elsewhere. While I think that's the ideal situation, I can say the same for flex. Ideally, flex layouts blocks shouldn't need to know about the layout properties directly. If we say that it's needed for flex layout, I don't see why it should be limited to only a handful of specific properties and not be done consistently for all properties of all layouts.

I think block authors will always have to know something about the implementation. For instance, if layout styles are only applied to the block wrapper and don't cascade, the block author needs to know this. Layout will never just magically work on a block regardless of its markup; it assumes a very specific markup structure. Likewise, authors need to know that the styles are generated, and no classnames are provided that they can hook custom styles to.

If you really think that for your block, I'd say don't use the layout abstraction and if it proves to be the case for all blocks, we should remove the abstraction because it becomes just a burden and we just add specific block supports like other block supports.

But what I'm getting here is that you seem to want the "UI" of the layout but without its style (or very few styles), I think maybe the best compromise we can make here (which would also align with other block supports) is to add the __experimentalSkipSerialization support to the "layout" block support. Meaning the UI will be added for the block, the attribute will be kept updated properly using user input, but no style will be generated, the responsibility to generate the styles for the attribute fallbacks to the block itself. That's how we solve the "special cases" for other block supports and I think that's how we should solve them for layout. What do you think about this solution?

@youknowriad
Copy link
Contributor

I've been thinking more here, if you still want the "style generation" from the layout attribute, we can still keep the added code from this PR but move it to a filter (similar to the layout filter itself) that is specific to the navigation block that way we don't impact the abstraction yet until we know more about the use-cases for other blocks...

@tellthemachines
Copy link
Contributor Author

if you still want the "style generation" from the layout attribute, we can still keep the added code from this PR but move it to a filter (similar to the layout filter itself)

Yes, we still need the exact styles generated by layout, we just need to be able to apply them to a different wrapper than they are by default.

I'm not sure I follow the solution though. Would this be another filter applied to render_block or would we be adding the ability to apply filters to layout itself? Also would the filter work on both the editor and front-end, or would we have to duplicate it in JS and PHP?

@youknowriad
Copy link
Contributor

I'm not sure I follow the solution though. Would this be another filter applied to render_block or would we be adding the ability to apply filters to layout itself? Also would the filter work on both the editor and front-end, or would we have to duplicate it in JS and PHP?

yes we need a custom filter that is specific to the navigation block in both editor and frontend (layout filters are also duplicated in both editor and frontend)

@tellthemachines
Copy link
Contributor Author

@youknowriad check out #37438; will that work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants