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

List View: Add multi-select support for shift + Home and End keys #39272

Conversation

andrewserong
Copy link
Contributor

Description

Following on from #38314, this PR adds in support for shift-selecting multiple blocks within the list view via the Home and End keys. The Tree Grid component already supports navigating to the beginning and end of the block list via these keys — this PR is a fairly simple update that rolls out adding in the onFocusRow callback for those key press events, too, and accepting those events as valid key presses for multiple block selection in useBlockSelection.

The end result is that it should now be a little easier to select from a particular block within the list view, to the end or beginning of a post.

Testing Instructions

  1. Add a range of blocks to a post. Open up the list view, and tab to focus on a block within the list.
  2. Use Shift + Home or Shift + End keys to select a range of blocks.
  3. Also use Shift + Up or Shift + Down keys to adjust the selection.
  4. Check that this doesn't introduce any regressions.

Check that the added tests pass in CI (or you can use the following to run locally):

npm run test-unit packages/components/src/tree-grid/test/index.js

Screenshots

In the following screengrab, the Home and End keys allow selection to the beginning or end of the list while the shift key is selected. The up and down arrows then still enable altering that selection.

list-view-home-and-end-keys

Types of changes

Enhancement.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).
  • I've updated related schemas if appropriate.

@andrewserong andrewserong added [Type] Enhancement A suggestion for improvement. [Feature] UI Components Impacts or related to the UI component system [Feature] Block Multi Selection The ability to select and manipulate multiple blocks [Package] Components /packages/components [Feature] List View Menu item in the top toolbar to select blocks from a list of links. labels Mar 8, 2022
@andrewserong andrewserong self-assigned this Mar 8, 2022
@andrewserong andrewserong marked this pull request as ready for review March 8, 2022 01:20
@github-actions
Copy link

github-actions bot commented Mar 8, 2022

Size Change: +4.04 kB (0%)

Total Size: 1.21 MB

Filename Size Change
build/block-editor/index.min.js 146 kB +906 B (+1%)
build/block-editor/style-rtl.css 15.1 kB +118 B (+1%)
build/block-editor/style.css 15.1 kB +114 B (+1%)
build/block-library/blocks/pullquote/style-rtl.css 370 B -19 B (-5%)
build/block-library/blocks/pullquote/style.css 370 B -18 B (-5%)
build/block-library/blocks/separator/editor-rtl.css 140 B +41 B (+41%) 🚨
build/block-library/blocks/separator/editor.css 140 B +41 B (+41%) 🚨
build/block-library/blocks/separator/theme-rtl.css 194 B +22 B (+13%) ⚠️
build/block-library/blocks/separator/theme.css 194 B +22 B (+13%) ⚠️
build/block-library/blocks/site-logo/editor-rtl.css 759 B +15 B (+2%)
build/block-library/blocks/site-logo/editor.css 759 B +15 B (+2%)
build/block-library/editor-rtl.css 10 kB +37 B (0%)
build/block-library/editor.css 10 kB +36 B (0%)
build/block-library/index.min.js 171 kB +2.02 kB (+1%)
build/block-library/style-rtl.css 11.2 kB -9 B (0%)
build/block-library/style.css 11.2 kB -7 B (0%)
build/block-library/theme-rtl.css 689 B +24 B (+4%)
build/block-library/theme.css 694 B +24 B (+4%)
build/components/index.min.js 218 kB +154 B (0%)
build/components/style-rtl.css 15.6 kB +44 B (0%)
build/components/style.css 15.6 kB +52 B (0%)
build/core-data/index.min.js 14.3 kB -8 B (0%)
build/edit-navigation/index.min.js 16.1 kB -50 B (0%)
build/edit-navigation/style-rtl.css 4.04 kB +1 B (0%)
build/edit-navigation/style.css 4.05 kB +1 B (0%)
build/edit-post/index.min.js 29.8 kB +25 B (0%)
build/edit-post/style-rtl.css 7.07 kB +1 B (0%)
build/edit-post/style.css 7.07 kB +2 B (0%)
build/edit-site/index.min.js 45 kB +141 B (0%)
build/edit-site/style-rtl.css 7.58 kB +140 B (+2%)
build/edit-site/style.css 7.56 kB +137 B (+2%)
build/edit-widgets/style-rtl.css 4.4 kB +1 B (0%)
build/edit-widgets/style.css 4.39 kB +1 B (0%)
build/editor/index.min.js 38.4 kB +11 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/admin-manifest/index.min.js 1.24 kB
build/annotations/index.min.js 2.77 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 487 B
build/block-directory/index.min.js 6.49 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-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 150 B
build/block-library/blocks/audio/editor.css 150 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/avatar/editor-rtl.css 59 B
build/block-library/blocks/avatar/editor.css 59 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 445 B
build/block-library/blocks/button/editor.css 445 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 103 B
build/block-library/blocks/code/style.css 103 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-template/style-rtl.css 127 B
build/block-library/blocks/comment-template/style.css 127 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-query-loop/editor-rtl.css 95 B
build/block-library/blocks/comments-query-loop/editor.css 95 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.56 kB
build/block-library/blocks/cover/style.css 1.56 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 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 353 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 961 B
build/block-library/blocks/gallery/editor.css 964 B
build/block-library/blocks/gallery/style-rtl.css 1.51 kB
build/block-library/blocks/gallery/style.css 1.51 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/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 529 B
build/block-library/blocks/image/style.css 535 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 199 B
build/block-library/blocks/latest-posts/editor.css 198 B
build/block-library/blocks/latest-posts/style-rtl.css 447 B
build/block-library/blocks/latest-posts/style.css 446 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 708 B
build/block-library/blocks/navigation-link/editor.css 706 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 375 B
build/block-library/blocks/navigation/editor-rtl.css 2.03 kB
build/block-library/blocks/navigation/editor.css 2.04 kB
build/block-library/blocks/navigation/style-rtl.css 1.89 kB
build/block-library/blocks/navigation/style.css 1.88 kB
build/block-library/blocks/navigation/view.min.js 2.85 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 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 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 446 B
build/block-library/blocks/post-comments-form/style.css 446 B
build/block-library/blocks/post-comments/style-rtl.css 521 B
build/block-library/blocks/post-comments/style.css 521 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 721 B
build/block-library/blocks/post-featured-image/editor.css 721 B
build/block-library/blocks/post-featured-image/style-rtl.css 153 B
build/block-library/blocks/post-featured-image/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 323 B
build/block-library/blocks/post-template/style.css 323 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 80 B
build/block-library/blocks/post-title/style.css 80 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/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-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 201 B
build/block-library/blocks/quote/style.css 201 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 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/style-rtl.css 233 B
build/block-library/blocks/separator/style.css 233 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/style-rtl.css 181 B
build/block-library/blocks/site-logo/style.css 181 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 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.37 kB
build/block-library/blocks/social-links/style.css 1.36 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 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 226 B
build/block-library/blocks/tag-cloud/style.css 227 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 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 934 B
build/block-library/common.css 932 B
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 46.8 kB
build/compose/index.min.js 11.2 kB
build/customize-widgets/index.min.js 11.2 kB
build/customize-widgets/style-rtl.css 1.39 kB
build/customize-widgets/style.css 1.39 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.19 kB
build/date/index.min.js 31.9 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.53 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/edit-widgets/index.min.js 16.5 kB
build/editor/style-rtl.css 3.71 kB
build/editor/style.css 3.71 kB
build/element/index.min.js 4.29 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 6.62 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.83 kB
build/keycodes/index.min.js 1.41 kB
build/list-reusable-blocks/index.min.js 1.75 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.94 kB
build/notices/index.min.js 957 B
build/nux/index.min.js 2.12 kB
build/nux/style-rtl.css 751 B
build/nux/style.css 749 B
build/plugins/index.min.js 1.98 kB
build/preferences/index.min.js 1.2 kB
build/primitives/index.min.js 949 B
build/priority-queue/index.min.js 611 B
build/react-i18n/index.min.js 704 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.69 kB
build/reusable-blocks/index.min.js 2.24 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 11.1 kB
build/server-side-render/index.min.js 1.61 kB
build/shortcode/index.min.js 1.52 kB
build/token-list/index.min.js 668 B
build/url/index.min.js 1.99 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 280 B
build/widgets/index.min.js 7.21 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.07 kB

compressed-size-action

Copy link
Contributor

@alexstine alexstine left a comment

Choose a reason for hiding this comment

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

@andrewserong The change is almost perfect for me. The only issue is if I press Ctrl+End to select all blocks from my current position, it announces the number selected plus the last selected block. This really isn't helpful in this context. Can you ditch the last block name if selection is > than 1 based on the select Home/End keys event?

Copy link
Contributor

@talldan talldan left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for working on another good improvement to List View.

From what I can tell, the issue @alexstine mentioned was solved by that last commit, but would be good to get a thumbs up from Alex before merging.

@andrewserong
Copy link
Contributor Author

Thanks for the quick review @alexstine! I've pushed an update that skips announcing the deselected blocks when the new selection is generated via the Home/End keys and the selection is greater than 1. Is that what you had in mind? It's sounding better to me now using the macOS voice over feature, but I'm happy to keep tweaking if this change didn't quite address the issue 🙂

@alexstine
Copy link
Contributor

@andrewserong Seems that the problem got worse. 👎 Here is what the screen reader announces.

List View toggle button not pressed
pressed
Block library region
Block navigation structure table
Image not selected row 1 column 1
Image link Block 1 of 5, Level 1
5 blocks selected.
Image (selected block)
Image (selected block) not selected row 5 column 1
Image (selected block) link Block 5 of 5, Level 1

Here all the extra selected blocks? Just the total would be enough.

  1. I pulled latest changes.
  2. Ran npm run build with no errors.
  3. Opened my test site in private browsing.
  4. Selected the List View button.
  5. When focus was placed on the first block, I held Shift and pressed End once.

Hope this helps.

Thanks.

@ciampo
Copy link
Contributor

ciampo commented Mar 8, 2022

I don't have much to add here, but just wanted to thank everyone involved (especially @alexstine — your feedback is always very useful, thank you!)

@andrewserong
Copy link
Contributor Author

Thanks @alexstine, that feedback is very helpful! I've been testing with the voice over function in MacOS where the additional announcements of "Image (selected block)" aren't happening. I wonder if it's to do with that component, which is currently focused, being updated when the block selection changes. I'll see if I can install a Windows VM to try out NVDA or another screen reader to see if I can replicate what you've found in testing.

I'll follow up!

@andrewserong
Copy link
Contributor Author

Alrighty, I'm wrapping up for the day, but I've set up a local environment running Windows 11 and NVDA and can reproduce the problem exactly as Alex described. As a side effect of this, I now have a much better testing environment! I'll do some exploration over the rest of the week to see what we can do to try to fix this up 👍

@andrewserong andrewserong force-pushed the update/list-view-to-support-home-and-end-keys-for-multi-select branch from 6a53419 to 3d07283 Compare March 10, 2022 05:48
@andrewserong
Copy link
Contributor Author

Alrighty, I think I've worked out why there are additional announcements of the block that the user started on, and the destination block (I just don't have a fix for it yet 😅). In block-select-button.js the "(selected block)" text within the VisuallyHidden element updates when the selection changes, and given that the button is focused when that change happens, the currently focused button is announced again. The same appears to happen at the destination, the text has changed within the component so it is announced another time.

I'm not quite sure what the best workaround is for this, since we're relying on state changes for the screen reader to announce these components rather than a call to speak. I might not get a chance to continue investigating this week, but happy to continue investigating next week.

Thanks for rolling out the changes to TreeGrid and its tests from this PR in #39302 @alexstine!

@ramonjd
Copy link
Member

ramonjd commented Mar 14, 2022

I don't have a screen reader set up yet, but the interactions are working well for me. SHIFT + UP/LEFT or DOWN/RIGHT all select up and downwards from any position in a leaf node.

The only thing I'm not sure about – and it might be just because I'm using a mac keyboard – is that I can't trigger home or end (I assume it's meant to select the entire block?)

The first few seconds of the screen case is me trying the documented fn + LEFT/RIGHT for HOME/END

2022-03-14 15 28 38

Any tips?

Non-blocking. It's a helpful interaction to have SHIFT alone.

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 taking this on! The multi-selection behaviour with Shift+Home/End is working fine with the keyboard on all browsers except for Safari. (@ramonjd if you were testing on Safari, that wonky behaviour with Fn + Arrow Left/Right seems to be browser-specific; it's working fine on Firefox and Chrome)

The last selected item being announced by screen readers on multi-selection is also reproducible on trunk when selecting multiple items with Shift+Arrow keys, so I don't think it should be a blocker for this PR. We can investigate it separately.

) {
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

In testing on both Windows with NVDA+Firefox and macOS with VoiceOver+Firefox, this change doesn't seem to make any difference. The last selected block of the multi-selection is always announced, whether the multi-selection happens with Home/End keys or just Shift+Arrow Up/Down. And if for @alexstine the change seemed to make things worse, I think it's safe to remove it altogether.

Copy link
Contributor

Choose a reason for hiding this comment

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

This change is good when selecting with Arrows but when using Home/End, it should only announce the number of selected/deselected. Why? Let's look at this practically.

  • I press Shift+Down Arrow to select a block.
  • I hear the total number of blocks selected plus the block I just selected.
  • If I press End, it will select say 5 blocks but then I only hear the last block get announced.

See how this can get confusing?

When having these Home/End selections, it should just announce the total as in reality you selected multiple blocks at once vs. one block at a time.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see what you mean. When pressing End, the last block in the selection gets focused; that must be why it's being announced. I wonder if we can instead keep focus on the first block in the selection - and if there won't be any negative side-effects to that 😅

Copy link
Contributor Author

@andrewserong andrewserong Mar 18, 2022

Choose a reason for hiding this comment

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

Thanks for taking a closer look here! I was wondering if it's possible for us to conditionally add aria-hidden set to true in the block select button component for just the case of having switched focus while holding shift plus Home / End, to prevent the block from being announced. I might have a play.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think focus should always follow the selection. Otherwise when you press up or down again it becomes disorienting.

Looking at how Finder works, it's similar to what Alex describes (though you have to use shift+option+arrow key instead of home or end to select to the start or end). It'll only announce '6 rows selected' and it won't announce the file that is focused (even though focus does move).

Is there any way to suppress the innate announcement that screenreaders make when focus moves?

Copy link
Contributor

Choose a reason for hiding this comment

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

I was also wondering if there's any advantage in using roles like aria-multiselectable:
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-multiselectable

It didn't seem to do anything when I tested adding it, but maybe it needs to be used in combination with aria-selected.

The docs seem to imply that's ok with a tree, but don't say if that extends to a treegrid.

@andrewserong andrewserong force-pushed the update/list-view-to-support-home-and-end-keys-for-multi-select branch from d850880 to 2692f44 Compare March 18, 2022 05:11
@andrewserong
Copy link
Contributor Author

andrewserong commented Mar 18, 2022

I tentatively think I might have come up with a fix for the announcement issue in 2692f44. Thanks again for the feedback and discussion, folks! I've rebased to resolve some conflicts with trunk.

In that change, I've added some state to the parent list view to keep track of whether or not we should prevent announcing the label of the block selection button. When we shift select with Home or End, we set preventAnnouncement to true and pass this all the way down to the block selection button. There, we pass this value to aria-hidden to prevent announcing the label for the button.

Then, when we move focus or select any other row, the aria-hidden flag is switched off. I've added a small delay, so that it isn't switched off prematurely when moving out of focusing on a particular button.

This appears to be testing pretty well for me so far in NVDA on Windows 11 running in a VM on a Mac. But I'd love a confidence check on the approach if you get a chance to take this for another spin @alexstine. No rush at all, though, as I'm finishing up for the week.

Also, very happy to throw out that approach if folks think there's a better way to do it, or if this approach feels too hacky!

@tellthemachines
Copy link
Contributor

Tested this again on Safari+VoiceOver (the home key combo is now working fine on Safari, not sure what happened earlier) and on Firefox+NVDA. In both the currently focused block is read out after "x blocks selected".

As Dan mentioned the multiselectable above, I decided to try it out in and put together #39600 as an experiment (I really just wanted a PR up so I could test it on Windows with Gutenberg.run 😅). It doesn't seem to change much in Safari+VO though.

Not quite sure what else we can try here.

@andrewserong
Copy link
Contributor Author

Thanks again for all the feedback and testing @tellthemachines, @alexstine, and @talldan!

I did some more investigation, thanks for the link to the alternate PR @tellthemachines, that sparked some ideas 😀

Just a heads-up, there's been a rebase recently, so you may need to remove your local copy of this branch before re-testing, in case that's caused any issues.

I think the root of our challenges here is that the set of roles that we're working with in the tree grid is similar to that of working within a grid of tabular data (e.g. the row role or the gridcell role. Rather than wrestle too much with the browser here, I've had a go at reverting the preventAnnouncement approach, and instead see how far we can get by focusing on the row and cell behaviour of the tree grid.

In the latest update in 159b2a2, I've done a few things:

  • Removed the (selected block) text at the button level, as this causes the block to be re-rendered when the text updates, which then triggers additional announcements when we select or deselect the block. Instead, like in @tellthemachines' PR, we move to using the aria-selected attribute on the cell and row. The missing piece appeared to be removing the dynamic changes and description at the button level.
  • I've moved the description and labels up to the table cell, so that the focused block isn't announced twice. With the cell and row approach to the tree grid, the browser's default behaviour is to announce the label of the cell that is focused as well as the link contained within it. This appears to be the source of the multiple announcements of the focused block.
  • So, with the label and description attached to the grid cell, I've then set the button itself to aria-hidden so that we only get a single announcement of each block.

This appears to be testing much better from my perspective using NVDA in Windows 11, where navigating between blocks now only reads that block out once. Shift-selecting all the blocks now no-longer reads out the block you started on a second time (without us having to add the hacky preventAnnouncement approach).

There is the remaining issue that we cannot appear to prevent the destination block from being announced after the selection. This appears to be browser default behaviour of navigating around cell-like elements, so it's a tricky one! I'm wondering if it's enough of an improvement that the block is only announced once instead of twice?

With the current state of the PR, the output from NVDA now sounds like the following in my testing:

Block navigation structure  table
Quote  not selected  Block 13 of 13, Level 1
Heading  not selected  Block 1 of 13, Level 1  row 1
Heading  not selected  Block 2 of 13, Level 1  row 2
12 blocks selected.  
Quote  selected  Block 13 of 13, Level 1  row 13

Please let me know if you think this direction seems viable — my hunch is that focusing on having the announcements at the cell or row level will help keep the behaviour contained and focused, but again, happy to throw any of this out if it doesn't seem suitable!

Thanks again for all the help and patience as we explore the different options 🙇

@alexstine
Copy link
Contributor

@andrewserong It is better, there is no doubt about it. This is the problem I am seeing now. It might honestly be out of scope for this PR.

List View  toggle button  not pressed
pressed
Block library  region
Block navigation structure  table
Paragraph  not selected  Block 1 of 9, Level 1  row 1  column 1
9 blocks selected. 
Column  not selected  Block 2 of 2, Level 2  row 13  column 1
8 blocks deselected. 
Paragraph  selected  Block 1 of 9, Level 1  row 1  column 1
Paragraph  not selected  Block 2 of 9, Level 1  row 2  column 1
Paragraph  not selected  Block 3 of 9, Level 1  row 3  column 1
Paragraph  not selected  Block 4 of 9, Level 1  row 4  column 1
Paragraph  not selected  Block 5 of 9, Level 1  row 5  column 1
Paragraph  not selected  Block 6 of 9, Level 1  row 6  column 1
Paragraph  not selected  Block 7 of 9, Level 1  row 7  column 1
Group  not selected  expanded  Block 8 of 9, Level 1  row 8  column 1
Paragraph  not selected  Block 1 of 1, Level 2  row 9  column 1
Columns  not selected  expanded  Block 9 of 9, Level 1  row 10  column 1
Column  not selected  expanded  Block 1 of 2, Level 2  row 11  column 1
Paragraph  not selected  Block 1 of 1, Level 3  row 12  column 1
Column  not selected  Block 2 of 2, Level 2  row 13  column 1

Column not selected Block 2 of 2, Level 2 row 13 column 1

In another PR, we've got to fix the label on this. This has confused me so bad, I don't even know what to make of that. We need to use simpler language somehow instead of expecting users to actually know what this means.

8 blocks deselected.

Why can I not deselect all blocks? Is it because the paragraph block is selected in the editor but not the selection as far as copy/paste? This confuses me why it says selecting 9 blocks but deselecting 8.

Thanks and great work on this!

@andrewserong
Copy link
Contributor Author

Thanks for confirming, Alex! Since this approach seems to improve things, I'll proceed now with updating the e2e tests to get them passing (they're currently expecting the selected block string at the button link level).

In another PR, we've got to fix the label on this.

Agreed. At least we've got some more information now on how to change things, so the hard part will be just deciding what we want it to say 🙂

Why can I not deselect all blocks?

Oh, that's a good point, sorry I meant to follow-up on your comment there yesterday. I think the problem is that in comparable interfaces (such as a spreadsheet or file system) there is always at least one item currently selected, whereas in this interface there is such a thing as a focused but not selected item, which means we've got some more complexity to deal with. It's hard to know if when a user goes back to the original item with the shift key selected, whether or not they would like that item to remain selected. At the moment the logic assumes that the shift key means the original item is always going to be selected. Perhaps it'll be easier in a separate PR to look at the desired behaviour for de-selecting items, and explore which options might make sense? I'd be happy to look into that in a follow-up if it isn't a blocker for this PR.

@alexstine
Copy link
Contributor

@andrewserong Follow-up PR is certainly okay. Super excited with the progress here.

Let's keep these improvements coming. 👍 Thanks!

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 your continued work on this! The latest batch of changes is testing much better than previously; I just left a couple of comments below.

Regarding the inability to fully deselect list items, I think that should be addressed separately because it's an existing issue, not introduced by this PR.

@alexstine, is the Block 2 of 2, Level 2 row 13 column 1 part too verbose? Perhaps we don't need to indicate whereabouts on the tree every time we move focus around. I think that would also be a good candidate for a follow-up though. It'd be good to get this in, as it's already better than what's currently on trunk!

@alexstine
Copy link
Contributor

@tellthemachines I totally agree.

@alexstine, is the Block 2 of 2, Level 2 row 13 column 1 part too verbose? Perhaps we don't need to indicate whereabouts on the tree every time we move focus around. I think that would also be a good candidate for a follow-up though. It'd be good to get this in, as it's already better than what's currently on trunk!

Copy link
Contributor

@alexstine alexstine left a comment

Choose a reason for hiding this comment

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

An interesting discovery I did not see since I was so busy checking selection.

@andrewserong
Copy link
Contributor Author

Alrighty, I've updated this PR with the following:

  • Updated e2e tests to look for the element with aria-selected now that the selected text has been moved up to the cell.
  • Added the word link to the label used at the cell level
  • Removed the code to skip saying deselected

Please let me know if I've missed anything, or if it needs further tweaking!

Copy link
Contributor

@alexstine alexstine 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 your work on this @andrewserong !

@andrewserong
Copy link
Contributor Author

Thanks for reviewing again @alexstine! I've added back in the code to skip announcing the deselect, and removed the isExpanded at the button level.

I'll merge this in after lunch, once the tests pass!

@alexstine
Copy link
Contributor

@andrewserong Sounds good. Then we can move on to more fun with this selection stuff. Maybe it would be a good idea to start a tracking issue if one doesn't already exist. Still a couple weird things to discuss. If you want to draft it, I can start adding some things to check unless you remember my spread out notes.

@andrewserong
Copy link
Contributor Author

Sure thing, I'll open up a tracking issue a little later on today, and will ping you on it!

@andrewserong andrewserong merged commit 7d6ba76 into trunk Mar 23, 2022
@andrewserong andrewserong deleted the update/list-view-to-support-home-and-end-keys-for-multi-select branch March 23, 2022 02:33
@github-actions github-actions bot added this to the Gutenberg 12.9 milestone Mar 23, 2022
@andrewserong
Copy link
Contributor Author

I've opened up a follow-up issue to track some of the suggestions and ideas raised in the reviews here. Let me know, or add to that issue if I missed anything!

@mtias
Copy link
Member

mtias commented Mar 25, 2022

Thank you all for the great work here!

@mtias mtias added the [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). label Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block Multi Selection The ability to select and manipulate multiple blocks [Feature] List View Menu item in the top toolbar to select blocks from a list of links. [Feature] UI Components Impacts or related to the UI component system [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants