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

Constrained tabbing: fix unstable behavior in firefox #42653

Merged
merged 5 commits into from
Nov 24, 2022

Conversation

t-hamano
Copy link
Contributor

@t-hamano t-hamano commented Jul 23, 2022

Fix #42652, #45903
Follow up on #34836

What?

This PR fixes a problem with "constrained tabbing" sometimes losing focus in Firefox.

"Constrained tabbing" means that the tab moving is constrained to the content of the wrapper element such as modal component.

As reported in #42652, I confirmed that in Firefox, the focus is sometimes lost from the modal when the following operation is performed:

  • When tab key is pressed on the last focusable element (the first element should be focused)
  • When tab + shift key is pressed on the first focusable element (the last element should be focused)

Why?

I learned that the constrained tabbing useConstrainedTabbing hook.

For example, when the tab key is pressed on the last focused element, the following logic is used to move focus to the first element:

  • Searches for the next element to focus from all tabbable elements
  • Add a trap element to the wrapper element if the element is not contained in a wrapper element
  • Focus on trap elements
  • Browser default behavior moves focus to the next element after the trap element (i.e., the first element in the wrapper)
  • Delete the trap element after the focus has successfully moved

However, in Firefox, I found that the trap element is sometimes deleted while the focus remains on the trap element.

timeoutId = setTimeout( () => {
	// Sometimes the TRAP element still has focus.
	console.log( document.activeElement );
	node.removeChild( trap );
} );

In other words, I believe that the focus is lost by deleting the trap element that remains in focus, and the browser is moving focus without considering the wrapper element.

How?

I haven't been able to find valid documentation, but I think we need to wait for the browser to properly move focus to the next element before removing the trap element.

So I added a small delay to the setTimeout function that removes the trap element.

Testing Instructions

  • Open a modal window such as "Welcome Guide" or "Preferences".
  • Confirm that the focus isn't lost from within the modal when you press 'tab' or 'tab+shift' key.
  • Or, hold down the tab key to move the focus fast.

Screenshot

1d56267affde3a5df8713d9aaa28a5f2.mp4

@t-hamano t-hamano added the [Type] Code Quality Issues or PRs that relate to code quality label Jul 23, 2022
@github-actions
Copy link

github-actions bot commented Jul 23, 2022

Size Change: +13.4 kB (+1%)

Total Size: 1.31 MB

Filename Size Change
build/block-directory/style-rtl.css 1.02 kB +26 B (+3%)
build/block-directory/style.css 1.02 kB +26 B (+3%)
build/block-editor/default-editor-styles-rtl.css 401 B +23 B (+6%) 🔍
build/block-editor/default-editor-styles.css 401 B +23 B (+6%) 🔍
build/block-editor/index.min.js 176 kB +689 B (0%)
build/block-editor/style-rtl.css 16.2 kB +255 B (+2%)
build/block-editor/style.css 16.2 kB +251 B (+2%)
build/block-library/blocks/archives/editor-rtl.css 107 B +46 B (+75%) 🆘
build/block-library/blocks/archives/editor.css 106 B +46 B (+77%) 🆘
build/block-library/blocks/archives/style-rtl.css 129 B +39 B (+43%) 🚨
build/block-library/blocks/archives/style.css 129 B +39 B (+43%) 🚨
build/block-library/blocks/audio/editor-rtl.css 185 B +35 B (+23%) 🚨
build/block-library/blocks/audio/editor.css 185 B +35 B (+23%) 🚨
build/block-library/blocks/audio/style-rtl.css 158 B +36 B (+30%) 🚨
build/block-library/blocks/audio/style.css 158 B +36 B (+30%) 🚨
build/block-library/blocks/audio/theme-rtl.css 160 B +34 B (+27%) 🚨
build/block-library/blocks/audio/theme.css 160 B +34 B (+27%) 🚨
build/block-library/blocks/avatar/editor-rtl.css 154 B +38 B (+33%) 🚨
build/block-library/blocks/avatar/editor.css 154 B +38 B (+33%) 🚨
build/block-library/blocks/avatar/style-rtl.css 126 B +42 B (+50%) 🆘
build/block-library/blocks/avatar/style.css 126 B +42 B (+50%) 🆘
build/block-library/blocks/block/editor-rtl.css 338 B +177 B (+110%) 🆘
build/block-library/blocks/block/editor.css 338 B +177 B (+110%) 🆘
build/block-library/blocks/button/editor-rtl.css 514 B +32 B (+7%) 🔍
build/block-library/blocks/button/editor.css 514 B +32 B (+7%) 🔍
build/block-library/blocks/button/style-rtl.css 564 B +32 B (+6%) 🔍
build/block-library/blocks/button/style.css 564 B +32 B (+6%) 🔍
build/block-library/blocks/buttons/editor-rtl.css 373 B +36 B (+11%) ⚠️
build/block-library/blocks/buttons/editor.css 373 B +36 B (+11%) ⚠️
build/block-library/blocks/buttons/style-rtl.css 368 B +36 B (+11%) ⚠️
build/block-library/blocks/buttons/style.css 368 B +36 B (+11%) ⚠️
build/block-library/blocks/calendar/style-rtl.css 270 B +31 B (+13%) ⚠️
build/block-library/blocks/calendar/style.css 270 B +31 B (+13%) ⚠️
build/block-library/blocks/categories/editor-rtl.css 125 B +41 B (+49%) 🚨
build/block-library/blocks/categories/editor.css 124 B +41 B (+49%) 🚨
build/block-library/blocks/categories/style-rtl.css 138 B +38 B (+38%) 🚨
build/block-library/blocks/categories/style.css 138 B +38 B (+38%) 🚨
build/block-library/blocks/code/editor-rtl.css 102 B +49 B (+92%) 🆘
build/block-library/blocks/code/editor.css 102 B +49 B (+92%) 🆘
build/block-library/blocks/code/style-rtl.css 159 B +38 B (+31%) 🚨
build/block-library/blocks/code/style.css 159 B +38 B (+31%) 🚨
build/block-library/blocks/code/theme-rtl.css 160 B +36 B (+29%) 🚨
build/block-library/blocks/code/theme.css 160 B +36 B (+29%) 🚨
build/block-library/blocks/columns/editor-rtl.css 147 B +39 B (+36%) 🚨
build/block-library/blocks/columns/editor.css 147 B +39 B (+36%) 🚨
build/block-library/blocks/columns/style-rtl.css 442 B +36 B (+9%) 🔍
build/block-library/blocks/columns/style.css 442 B +36 B (+9%) 🔍
build/block-library/blocks/comment-author-avatar/editor-rtl.css 163 B +38 B (+30%) 🚨
build/block-library/blocks/comment-author-avatar/editor.css 163 B +38 B (+30%) 🚨
build/block-library/blocks/comment-content/style-rtl.css 134 B +42 B (+46%) 🚨
build/block-library/blocks/comment-content/style.css 134 B +42 B (+46%) 🚨
build/block-library/blocks/comment-template/style-rtl.css 237 B +38 B (+19%) ⚠️
build/block-library/blocks/comment-template/style.css 236 B +38 B (+19%) ⚠️
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 159 B +36 B (+29%) 🚨
build/block-library/blocks/comments-pagination-numbers/editor.css 157 B +36 B (+30%) 🚨
build/block-library/blocks/comments-pagination/editor-rtl.css 258 B +36 B (+16%) ⚠️
build/block-library/blocks/comments-pagination/editor.css 249 B +40 B (+19%) ⚠️
build/block-library/blocks/comments-pagination/style-rtl.css 272 B +37 B (+16%) ⚠️
build/block-library/blocks/comments-pagination/style.css 268 B +37 B (+16%) ⚠️
build/block-library/blocks/comments-title/editor-rtl.css 118 B +43 B (+57%) 🆘
build/block-library/blocks/comments-title/editor.css 118 B +43 B (+57%) 🆘
build/block-library/blocks/comments/editor-rtl.css 875 B +35 B (+4%)
build/block-library/blocks/comments/editor.css 874 B +35 B (+4%)
build/block-library/blocks/comments/style-rtl.css 672 B +35 B (+5%) 🔍
build/block-library/blocks/comments/style.css 671 B +35 B (+6%) 🔍
build/block-library/blocks/cover/editor-rtl.css 646 B +34 B (+6%) 🔍
build/block-library/blocks/cover/editor.css 647 B +34 B (+6%) 🔍
build/block-library/blocks/cover/style-rtl.css 1.6 kB +36 B (+2%)
build/block-library/blocks/cover/style.css 1.59 kB +37 B (+2%)
build/block-library/blocks/embed/editor-rtl.css 327 B +34 B (+12%) ⚠️
build/block-library/blocks/embed/editor.css 327 B +34 B (+12%) ⚠️
build/block-library/blocks/embed/style-rtl.css 446 B +36 B (+9%) 🔍
build/block-library/blocks/embed/style.css 446 B +36 B (+9%) 🔍
build/block-library/blocks/embed/theme-rtl.css 160 B +34 B (+27%) 🚨
build/block-library/blocks/embed/theme.css 160 B +34 B (+27%) 🚨
build/block-library/blocks/file/editor-rtl.css 335 B +35 B (+12%) ⚠️
build/block-library/blocks/file/editor.css 335 B +35 B (+12%) ⚠️
build/block-library/blocks/file/style-rtl.css 288 B +35 B (+14%) ⚠️
build/block-library/blocks/file/style.css 288 B +34 B (+13%) ⚠️
build/block-library/blocks/freeform/editor-rtl.css 2.47 kB +32 B (+1%)
build/block-library/blocks/freeform/editor.css 2.47 kB +30 B (+1%)
build/block-library/blocks/gallery/editor-rtl.css 978 B +30 B (+3%)
build/block-library/blocks/gallery/editor.css 981 B +31 B (+3%)
build/block-library/blocks/gallery/style-rtl.css 1.56 kB +33 B (+2%)
build/block-library/blocks/gallery/style.css 1.56 kB +33 B (+2%)
build/block-library/blocks/gallery/theme-rtl.css 144 B +36 B (+33%) 🚨
build/block-library/blocks/gallery/theme.css 144 B +36 B (+33%) 🚨
build/block-library/blocks/group/editor-rtl.css 687 B +33 B (+5%) 🔍
build/block-library/blocks/group/editor.css 687 B +33 B (+5%) 🔍
build/block-library/blocks/group/style-rtl.css 105 B +48 B (+84%) 🆘
build/block-library/blocks/group/style.css 105 B +48 B (+84%) 🆘
build/block-library/blocks/group/theme-rtl.css 125 B +47 B (+60%) 🆘
build/block-library/blocks/group/theme.css 125 B +47 B (+60%) 🆘
build/block-library/blocks/heading/style-rtl.css 128 B +52 B (+68%) 🆘
build/block-library/blocks/heading/style.css 128 B +52 B (+68%) 🆘
build/block-library/blocks/html/editor-rtl.css 360 B +33 B (+10%) ⚠️
build/block-library/blocks/html/editor.css 362 B +33 B (+10%) ⚠️
build/block-library/blocks/image/editor-rtl.css 912 B +32 B (+4%)
build/block-library/blocks/image/editor.css 912 B +32 B (+4%)
build/block-library/blocks/image/style-rtl.css 662 B +35 B (+6%) 🔍
build/block-library/blocks/image/style.css 666 B +36 B (+6%) 🔍
build/block-library/blocks/image/theme-rtl.css 159 B +33 B (+26%) 🚨
build/block-library/blocks/image/theme.css 159 B +33 B (+26%) 🚨
build/block-library/blocks/latest-comments/style-rtl.css 333 B +35 B (+12%) ⚠️
build/block-library/blocks/latest-comments/style.css 333 B +35 B (+12%) ⚠️
build/block-library/blocks/latest-posts/editor-rtl.css 250 B +37 B (+17%) ⚠️
build/block-library/blocks/latest-posts/editor.css 249 B +37 B (+17%) ⚠️
build/block-library/blocks/latest-posts/style-rtl.css 514 B +36 B (+8%) 🔍
build/block-library/blocks/latest-posts/style.css 514 B +36 B (+8%) 🔍
build/block-library/blocks/list/style-rtl.css 135 B +47 B (+53%) 🆘
build/block-library/blocks/list/style.css 135 B +47 B (+53%) 🆘
build/block-library/blocks/media-text/editor-rtl.css 300 B +34 B (+13%) ⚠️
build/block-library/blocks/media-text/editor.css 298 B +35 B (+13%) ⚠️
build/block-library/blocks/media-text/style-rtl.css 540 B +33 B (+7%) 🔍
build/block-library/blocks/media-text/style.css 539 B +34 B (+7%) 🔍
build/block-library/blocks/more/editor-rtl.css 465 B +34 B (+8%) 🔍
build/block-library/blocks/more/editor.css 465 B +34 B (+8%) 🔍
build/block-library/blocks/navigation-link/editor-rtl.css 742 B +30 B (+4%)
build/block-library/blocks/navigation-link/editor.css 741 B +30 B (+4%)
build/block-library/blocks/navigation-link/style-rtl.css 153 B +38 B (+33%) 🚨
build/block-library/blocks/navigation-link/style.css 153 B +38 B (+33%) 🚨
build/block-library/blocks/navigation-submenu/editor-rtl.css 329 B +33 B (+11%) ⚠️
build/block-library/blocks/navigation-submenu/editor.css 329 B +34 B (+12%) ⚠️
build/block-library/blocks/navigation/editor-rtl.css 2.18 kB +33 B (+2%)
build/block-library/blocks/navigation/editor.css 2.19 kB +33 B (+2%)
build/block-library/blocks/navigation/style-rtl.css 2.25 kB +39 B (+2%)
build/block-library/blocks/navigation/style.css 2.24 kB +35 B (+2%)
build/block-library/blocks/nextpage/editor-rtl.css 428 B +33 B (+8%) 🔍
build/block-library/blocks/nextpage/editor.css 428 B +33 B (+8%) 🔍
build/block-library/blocks/page-list/editor-rtl.css 397 B +34 B (+9%) 🔍
build/block-library/blocks/page-list/editor.css 398 B +35 B (+10%) ⚠️
build/block-library/blocks/page-list/style-rtl.css 212 B +37 B (+21%) 🚨
build/block-library/blocks/page-list/style.css 212 B +37 B (+21%) 🚨
build/block-library/blocks/paragraph/editor-rtl.css 214 B +40 B (+23%) 🚨
build/block-library/blocks/paragraph/editor.css 214 B +40 B (+23%) 🚨
build/block-library/blocks/paragraph/style-rtl.css 321 B +42 B (+15%) ⚠️
build/block-library/blocks/paragraph/style.css 321 B +40 B (+14%) ⚠️
build/block-library/blocks/post-author/style-rtl.css 212 B +37 B (+21%) 🚨
build/block-library/blocks/post-author/style.css 212 B +36 B (+20%) 🚨
build/block-library/blocks/post-comments-form/editor-rtl.css 137 B +41 B (+43%) 🚨
build/block-library/blocks/post-comments-form/editor.css 137 B +41 B (+43%) 🚨
build/block-library/blocks/post-comments-form/style-rtl.css 536 B +35 B (+7%) 🔍
build/block-library/blocks/post-comments-form/style.css 537 B +36 B (+7%) 🔍
build/block-library/blocks/post-date/style-rtl.css 107 B +46 B (+75%) 🆘
build/block-library/blocks/post-date/style.css 107 B +46 B (+75%) 🆘
build/block-library/blocks/post-excerpt/editor-rtl.css 119 B +46 B (+63%) 🆘
build/block-library/blocks/post-excerpt/editor.css 119 B +46 B (+63%) 🆘
build/block-library/blocks/post-excerpt/style-rtl.css 116 B +47 B (+68%) 🆘
build/block-library/blocks/post-excerpt/style.css 116 B +47 B (+68%) 🆘
build/block-library/blocks/post-featured-image/editor-rtl.css 620 B +34 B (+6%) 🔍
build/block-library/blocks/post-featured-image/editor.css 618 B +34 B (+6%) 🔍
build/block-library/blocks/post-featured-image/style-rtl.css 346 B +31 B (+10%) ⚠️
build/block-library/blocks/post-featured-image/style.css 346 B +31 B (+10%) ⚠️
build/block-library/blocks/post-navigation-link/style-rtl.css 190 B +37 B (+24%) 🚨
build/block-library/blocks/post-navigation-link/style.css 189 B +36 B (+24%) 🚨
build/block-library/blocks/post-template/editor-rtl.css 140 B +41 B (+41%) 🚨
build/block-library/blocks/post-template/editor.css 139 B +41 B (+42%) 🚨
build/block-library/blocks/post-template/style-rtl.css 317 B +35 B (+12%) ⚠️
build/block-library/blocks/post-template/style.css 317 B +35 B (+12%) ⚠️
build/block-library/blocks/post-terms/style-rtl.css 136 B +40 B (+42%) 🚨
build/block-library/blocks/post-terms/style.css 136 B +40 B (+42%) 🚨
build/block-library/blocks/post-title/style-rtl.css 138 B +38 B (+38%) 🚨
build/block-library/blocks/post-title/style.css 138 B +38 B (+38%) 🚨
build/block-library/blocks/preformatted/style-rtl.css 139 B +36 B (+35%) 🚨
build/block-library/blocks/preformatted/style.css 139 B +36 B (+35%) 🚨
build/block-library/blocks/pullquote/editor-rtl.css 170 B +35 B (+26%) 🚨
build/block-library/blocks/pullquote/editor.css 170 B +35 B (+26%) 🚨
build/block-library/blocks/pullquote/style-rtl.css 357 B +31 B (+10%) ⚠️
build/block-library/blocks/pullquote/style.css 357 B +32 B (+10%) ⚠️
build/block-library/blocks/pullquote/theme-rtl.css 201 B +34 B (+20%) 🚨
build/block-library/blocks/pullquote/theme.css 201 B +34 B (+20%) 🚨
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 158 B +36 B (+30%) 🚨
build/block-library/blocks/query-pagination-numbers/editor.css 156 B +35 B (+29%) 🚨
build/block-library/blocks/query-pagination/editor-rtl.css 258 B +37 B (+17%) ⚠️
build/block-library/blocks/query-pagination/editor.css 247 B +36 B (+17%) ⚠️
build/block-library/blocks/query-pagination/style-rtl.css 326 B +38 B (+13%) ⚠️
build/block-library/blocks/query-pagination/style.css 322 B +38 B (+13%) ⚠️
build/block-library/blocks/query-title/style-rtl.css 108 B +45 B (+71%) 🆘
build/block-library/blocks/query-title/style.css 108 B +45 B (+71%) 🆘
build/block-library/blocks/query/editor-rtl.css 475 B +35 B (+8%) 🔍
build/block-library/blocks/query/editor.css 477 B +37 B (+8%) 🔍
build/block-library/blocks/quote/style-rtl.css 253 B +40 B (+19%) ⚠️
build/block-library/blocks/quote/style.css 253 B +40 B (+19%) ⚠️
build/block-library/blocks/quote/theme-rtl.css 255 B +32 B (+14%) ⚠️
build/block-library/blocks/quote/theme.css 259 B +33 B (+15%) ⚠️
build/block-library/blocks/read-more/style-rtl.css 168 B +36 B (+27%) 🚨
build/block-library/blocks/read-more/style.css 168 B +36 B (+27%) 🚨
build/block-library/blocks/rss/editor-rtl.css 239 B +37 B (+18%) ⚠️
build/block-library/blocks/rss/editor.css 240 B +36 B (+18%) ⚠️
build/block-library/blocks/rss/style-rtl.css 323 B +34 B (+12%) ⚠️
build/block-library/blocks/rss/style.css 323 B +35 B (+12%) ⚠️
build/block-library/blocks/search/editor-rtl.css 205 B +40 B (+24%) 🚨
build/block-library/blocks/search/editor.css 205 B +40 B (+24%) 🚨
build/block-library/blocks/search/style-rtl.css 441 B +32 B (+8%) 🔍
build/block-library/blocks/search/style.css 439 B +33 B (+8%) 🔍
build/block-library/blocks/search/theme-rtl.css 149 B +35 B (+31%) 🚨
build/block-library/blocks/search/theme.css 149 B +35 B (+31%) 🚨
build/block-library/blocks/separator/editor-rtl.css 184 B +38 B (+26%) 🚨
build/block-library/blocks/separator/editor.css 184 B +38 B (+26%) 🚨
build/block-library/blocks/separator/style-rtl.css 269 B +35 B (+15%) ⚠️
build/block-library/blocks/separator/style.css 269 B +35 B (+15%) ⚠️
build/block-library/blocks/separator/theme-rtl.css 229 B +35 B (+18%) ⚠️
build/block-library/blocks/separator/theme.css 229 B +35 B (+18%) ⚠️
build/block-library/blocks/shortcode/editor-rtl.css 498 B +34 B (+7%) 🔍
build/block-library/blocks/shortcode/editor.css 498 B +34 B (+7%) 🔍
build/block-library/blocks/site-logo/editor-rtl.css 522 B +32 B (+7%) 🔍
build/block-library/blocks/site-logo/editor.css 522 B +32 B (+7%) 🔍
build/block-library/blocks/site-logo/style-rtl.css 238 B +35 B (+17%) ⚠️
build/block-library/blocks/site-logo/style.css 238 B +35 B (+17%) ⚠️
build/block-library/blocks/site-tagline/editor-rtl.css 129 B +43 B (+50%) 🆘
build/block-library/blocks/site-tagline/editor.css 129 B +43 B (+50%) 🆘
build/block-library/blocks/site-title/editor-rtl.css 155 B +39 B (+34%) 🚨
build/block-library/blocks/site-title/editor.css 155 B +39 B (+34%) 🚨
build/block-library/blocks/site-title/style-rtl.css 101 B +44 B (+77%) 🆘
build/block-library/blocks/site-title/style.css 101 B +44 B (+77%) 🆘
build/block-library/blocks/social-link/editor-rtl.css 219 B +35 B (+19%) ⚠️
build/block-library/blocks/social-link/editor.css 219 B +35 B (+19%) ⚠️
build/block-library/blocks/social-links/editor-rtl.css 709 B +35 B (+5%) 🔍
build/block-library/blocks/social-links/editor.css 708 B +35 B (+5%) 🔍
build/block-library/blocks/social-links/style-rtl.css 1.43 kB +36 B (+3%)
build/block-library/blocks/social-links/style.css 1.43 kB +36 B (+3%)
build/block-library/blocks/spacer/editor-rtl.css 360 B +38 B (+12%) ⚠️
build/block-library/blocks/spacer/editor.css 360 B +38 B (+12%) ⚠️
build/block-library/blocks/spacer/style-rtl.css 96 B +48 B (+100%) 🆘
build/block-library/blocks/spacer/style.css 96 B +48 B (+100%) 🆘
build/block-library/blocks/table/editor-rtl.css 537 B +32 B (+6%) 🔍
build/block-library/blocks/table/editor.css 537 B +32 B (+6%) 🔍
build/block-library/blocks/table/style-rtl.css 664 B +33 B (+5%) 🔍
build/block-library/blocks/table/style.css 663 B +32 B (+5%) 🔍
build/block-library/blocks/table/theme-rtl.css 207 B +35 B (+20%) 🚨
build/block-library/blocks/table/theme.css 207 B +35 B (+20%) 🚨
build/block-library/blocks/tag-cloud/style-rtl.css 287 B +36 B (+14%) ⚠️
build/block-library/blocks/tag-cloud/style.css 288 B +35 B (+14%) ⚠️
build/block-library/blocks/template-part/editor-rtl.css 436 B +201 B (+86%) 🆘
build/block-library/blocks/template-part/editor.css 436 B +201 B (+86%) 🆘
build/block-library/blocks/template-part/theme-rtl.css 139 B +38 B (+38%) 🚨
build/block-library/blocks/template-part/theme.css 139 B +38 B (+38%) 🚨
build/block-library/blocks/text-columns/editor-rtl.css 135 B +40 B (+42%) 🚨
build/block-library/blocks/text-columns/editor.css 135 B +40 B (+42%) 🚨
build/block-library/blocks/text-columns/style-rtl.css 198 B +32 B (+19%) ⚠️
build/block-library/blocks/text-columns/style.css 198 B +32 B (+19%) ⚠️
build/block-library/blocks/verse/style-rtl.css 130 B +43 B (+49%) 🚨
build/block-library/blocks/verse/style.css 130 B +43 B (+49%) 🚨
build/block-library/blocks/video/editor-rtl.css 720 B +29 B (+4%)
build/block-library/blocks/video/editor.css 723 B +29 B (+4%)
build/block-library/blocks/video/style-rtl.css 212 B +38 B (+22%) 🚨
build/block-library/blocks/video/style.css 212 B +38 B (+22%) 🚨
build/block-library/blocks/video/theme-rtl.css 160 B +34 B (+27%) 🚨
build/block-library/blocks/video/theme.css 160 B +34 B (+27%) 🚨
build/block-library/classic-rtl.css 193 B +31 B (+19%) ⚠️
build/block-library/classic.css 193 B +31 B (+19%) ⚠️
build/block-library/common-rtl.css 1.05 kB +27 B (+3%)
build/block-library/common.css 1.04 kB +26 B (+3%)
build/block-library/editor-elements-rtl.css 126 B +51 B (+68%) 🆘
build/block-library/editor-elements.css 126 B +51 B (+68%) 🆘
build/block-library/editor-rtl.css 11.7 kB +258 B (+2%)
build/block-library/editor.css 11.7 kB +259 B (+2%)
build/block-library/elements-rtl.css 105 B +51 B (+94%) 🆘
build/block-library/elements.css 105 B +51 B (+94%) 🆘
build/block-library/index.min.js 194 kB +449 B (0%)
build/block-library/reset-rtl.css 514 B +36 B (+8%) 🔍
build/block-library/reset.css 514 B +36 B (+8%) 🔍
build/block-library/style-rtl.css 12.4 kB +36 B (0%)
build/block-library/style.css 12.4 kB +36 B (0%)
build/block-library/theme-rtl.css 735 B +31 B (+4%)
build/block-library/theme.css 740 B +32 B (+5%) 🔍
build/blocks/index.min.js 49.9 kB -3 B (0%)
build/components/index.min.js 203 kB +178 B (0%)
build/components/style-rtl.css 11.5 kB +25 B (0%)
build/components/style.css 11.6 kB +25 B (0%)
build/compose/index.min.js 12.2 kB +1 B (0%)
build/customize-widgets/style-rtl.css 1.41 kB +26 B (+2%)
build/customize-widgets/style.css 1.41 kB +27 B (+2%)
build/edit-navigation/style-rtl.css 4.08 kB +26 B (+1%)
build/edit-navigation/style.css 4.09 kB +24 B (+1%)
build/edit-post/classic-rtl.css 569 B +23 B (+4%)
build/edit-post/classic.css 570 B +23 B (+4%)
build/edit-post/style-rtl.css 7.42 kB +24 B (0%)
build/edit-post/style.css 7.41 kB +25 B (0%)
build/edit-site/index.min.js 61 kB +55 B (0%)
build/edit-site/style-rtl.css 8.48 kB +82 B (+1%)
build/edit-site/style.css 8.46 kB +94 B (+1%)
build/edit-widgets/style-rtl.css 4.44 kB +27 B (+1%)
build/edit-widgets/style.css 4.44 kB +25 B (+1%)
build/editor/index.min.js 43.7 kB +17 B (0%)
build/editor/style-rtl.css 3.63 kB +28 B (+1%)
build/editor/style.css 3.62 kB +28 B (+1%)
build/format-library/style-rtl.css 596 B +25 B (+4%)
build/format-library/style.css 596 B +25 B (+4%)
build/list-reusable-blocks/style-rtl.css 858 B +23 B (+3%)
build/list-reusable-blocks/style.css 857 B +22 B (+3%)
build/nux/style-rtl.css 759 B +27 B (+4%)
build/nux/style.css 755 B +27 B (+4%)
build/reusable-blocks/style-rtl.css 281 B +25 B (+10%) ⚠️
build/reusable-blocks/style.css 281 B +25 B (+10%) ⚠️
build/widgets/style-rtl.css 1.21 kB +25 B (+2%)
build/widgets/style.css 1.21 kB +24 B (+2%)
ℹ️ 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-library/blocks/file/view.min.js 346 B
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 443 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 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-navigation/index.min.js 16.2 kB
build/edit-post/index.min.js 34.4 kB
build/edit-widgets/index.min.js 16.7 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/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/keycodes/index.min.js 1.83 kB
build/list-reusable-blocks/index.min.js 2.13 kB
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/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/rich-text/index.min.js 10.7 kB
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/wordcount/index.min.js 1.06 kB

compressed-size-action

@t-hamano t-hamano requested a review from ellatrix July 23, 2022 07:44
@t-hamano t-hamano marked this pull request as ready for review July 23, 2022 07:44
@t-hamano t-hamano requested a review from ajitbohra as a code owner July 23, 2022 07:44
@t-hamano t-hamano added the Browser Issues Issues or PRs that are related to browser specific problems label Jul 23, 2022
@t-hamano t-hamano self-assigned this Aug 9, 2022
@alexstine alexstine self-requested a review August 27, 2022 17:51
@@ -64,7 +64,7 @@ function useConstrainedTabbing() {
node[ domAction ]( trap );
trap.focus();
// Remove after the browser moves focus to the next element.
timeoutId = setTimeout( () => node.removeChild( trap ) );
timeoutId = setTimeout( () => node.removeChild( trap ), 10 );
Copy link
Member

Choose a reason for hiding this comment

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

What if we add an event listener to the trap and remove the element only when focus was moved out of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have made the following changes and have confirmed that it works as expected:

// Remove itself when the trap loses focus.
trap.addEventListener( 'blur', () => node.removeChild( trap ) );

trap.focus();

I couldn't figure out how to remove the event listener when the element itself is deleted, but is it also need to remove the event when the element is deleted?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not an expert but I think the element itself and the event listener are retained in memory because there's still a reference to it. To test: dump the trap element to the console after it's removed from the DOM, see that it's still in memory::

			trap.addEventListener( 'blur', () => {
				node.removeChild( trap );
				console.log( trap );
			} );

Since a new trap element and event listener will be created at each Tab key press on the last and first tabbable elements, I suspect this could lead to some memory leak. Again, I'm not an expert but I think that declaring the trap element with let and then assigning it to null after it's removed could be an option e.g. trap = null;.
Would appreciate feedback from someone with better knowledge than me.

Copy link
Contributor

@stokesman stokesman Nov 21, 2022

Choose a reason for hiding this comment

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

I couldn't figure out how to remove the event listener when the element itself is deleted, but is it also need to remove the event when the element is deleted?

It's my understanding that the listener does not need to be removed as long as there is no persisting reference to the element. It looks like in this case it'd be fine because each time the onKeyDown handler creates trap, the only closure around it is the blur listener itself. However, to be sure about it you could use the once option when adding the listener:

// Remove itself when the trap loses focus.
trap.addEventListener( 'blur', () => trap.remove(), { once: true } );

That example also switches to remove instead of removeChild for saving a few bits. Since IE11 doesn't need supported that should be safe.

Also I couldn't quickly find an outside source to back up my statements but there is this bit from the the jsdoc of useRefEffect:

* It's worth noting that if the dependencies array is empty, there's not
* strictly a need to clean up event handlers for example, because the node is
* to be removed. It *is* necessary if you add dependencies because the ref
* callback will be called multiple times for the same node.

Which agrees and indicates that this hook itself could drop the cleanup function here:
return () => {
node.removeEventListener( 'keydown', onKeyDown );
clearTimeout( timeoutId );
};
}, [] );

trap.focus();
// Remove after the browser moves focus to the next element.
timeoutId = setTimeout( () => node.removeChild( trap ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this timeout is not used any longer, the variable declaration at line 36 and the clearTimeout at line 75 should be removed as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed by 11a1cfa

@afercia
Copy link
Contributor

afercia commented Nov 21, 2022

Once this gets reviewed, it would be great to add some E2E tests with Playwright and run them on both Chrome and Firefox. Such an important usability and accessibility feature should never break and there should be tests in place to make sure it doesn't.

Kind reminder that this is a regression present since WordPress 5.9 - Gutenberg 11.8, which is almost one year ago.
/Cc @ellatrix @youknowriad @alexstine

@alexstine
Copy link
Contributor

Agreed. 👍

@alexstine alexstine added the [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). label Nov 21, 2022
Copy link
Contributor

@stokesman stokesman left a comment

Choose a reason for hiding this comment

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

I tested and verified I can reproduce the issue on trunk and I cannot on this branch.

Once Andrea’s comment is addressed this LGTM.

I'll approve anyway because I'm confident no corners will be cut. Awesome work spotting this issue and figuring out the fix @t-hamano 🏅.

@afercia
Copy link
Contributor

afercia commented Nov 23, 2022

Note: I'm working on a separate PR to move the existing a11y tests (which do have some tests for constrained tabbing) to Playwright so that we can run them with Firefox too. I'll also try to add some new tests.

@t-hamano
Copy link
Contributor Author

Thank you for the review, @afercia, @stokesman, @alexstine!
I have removed the unnecessary variables and clearTimeout indicated in this comment.

@stokesman
Should I add { once:true } as suggested in this comment just in case? As far as I have tested, it seems to work well in both cases.

@afercia afercia added [Type] Bug An existing feature does not function as intended [Type] Regression Related to a regression in the latest release [Package] Compose /packages/compose [a11y] Keyboard & Focus and removed Browser Issues Issues or PRs that are related to browser specific problems labels Nov 24, 2022
@stokesman
Copy link
Contributor

Should I add { once:true } as suggested in this comment just in case? As far as I have tested, it seems to work well in both cases.

I don't think it’s needed. I largely bought it up to promote awareness of it in case it comes in handy elsewhere.

@t-hamano t-hamano merged commit 0b9bf24 into trunk Nov 24, 2022
@t-hamano t-hamano deleted the fix/tabbing-on-firefox branch November 24, 2022 16:22
@github-actions github-actions bot added this to the Gutenberg 14.7 milestone Nov 24, 2022
@youknowriad
Copy link
Contributor

Thanks for the fix. Highly appreciated :)

@afercia
Copy link
Contributor

afercia commented Nov 25, 2022

🎉 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Package] Compose /packages/compose [Type] Bug An existing feature does not function as intended [Type] Code Quality Issues or PRs that relate to code quality [Type] Regression Related to a regression in the latest release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Components: focus is lost from Modal on keyboard operation in Firefox
6 participants