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

DataViews: navigate through list items via arrow keys #57895

Closed

Conversation

oandregal
Copy link
Member

@oandregal oandregal commented Jan 16, 2024

Part of #55083

Work In Progress.

What?

Implements arrow key navigation for the list layout. The list of items behaves like a single stop.

Why?

This provides a better keyboard navigation and follows accessibility best practices.

How?

Substitutes the unordered <ul> list by a <TreeGrid>.

Testing Instructions

  • Enable the "new admin views" experiment in "Gutenberg > Experiments".
  • Go to "Site Editor > Pages".
  • Navigate with the keyboard through the list of items in the content frame.

@oandregal oandregal self-assigned this Jan 16, 2024
@oandregal oandregal added [Type] Experimental Experimental feature or API. [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond labels Jan 16, 2024
Copy link

github-actions bot commented Jan 16, 2024

Size Change: +262 B (0%)

Total Size: 1.7 MB

Filename Size Change
build/block-editor/index.min.js 247 kB +5 B (0%)
build/block-library/index.min.js 215 kB +203 B (0%)
build/data/index.min.js 8.96 kB +23 B (0%)
build/dom/index.min.js 4.7 kB +12 B (0%)
build/edit-site/index.min.js 195 kB +51 B (0%)
build/edit-site/style-rtl.css 15 kB -35 B (0%)
build/edit-site/style.css 15.1 kB -32 B (0%)
build/patterns/index.min.js 5.4 kB +35 B (+1%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 964 B
build/annotations/index.min.js 2.71 kB
build/api-fetch/index.min.js 2.33 kB
build/autop/index.min.js 2.11 kB
build/blob/index.min.js 590 B
build/block-directory/index.min.js 7.25 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.31 kB
build/block-editor/content.css 4.31 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/style-rtl.css 15.3 kB
build/block-editor/style.css 15.3 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 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 419 B
build/block-library/blocks/button/editor.css 417 B
build/block-library/blocks/button/style-rtl.css 632 B
build/block-library/blocks/button/style.css 631 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 B
build/block-library/blocks/categories/editor-rtl.css 113 B
build/block-library/blocks/categories/editor.css 112 B
build/block-library/blocks/categories/style-rtl.css 124 B
build/block-library/blocks/categories/style.css 124 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 421 B
build/block-library/blocks/columns/style.css 421 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 647 B
build/block-library/blocks/cover/editor.css 650 B
build/block-library/blocks/cover/style-rtl.css 1.7 kB
build/block-library/blocks/cover/style.css 1.69 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 98 B
build/block-library/blocks/details/style.css 98 B
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 B
build/block-library/blocks/file/editor-rtl.css 316 B
build/block-library/blocks/file/editor.css 316 B
build/block-library/blocks/file/style-rtl.css 280 B
build/block-library/blocks/file/style.css 281 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/footnotes/style-rtl.css 201 B
build/block-library/blocks/footnotes/style.css 199 B
build/block-library/blocks/form-input/editor-rtl.css 229 B
build/block-library/blocks/form-input/editor.css 228 B
build/block-library/blocks/form-input/style-rtl.css 343 B
build/block-library/blocks/form-input/style.css 343 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 343 B
build/block-library/blocks/form-submission-notification/editor.css 342 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 452 B
build/block-library/blocks/freeform/editor-rtl.css 2.61 kB
build/block-library/blocks/freeform/editor.css 2.61 kB
build/block-library/blocks/gallery/editor-rtl.css 957 B
build/block-library/blocks/gallery/editor.css 962 B
build/block-library/blocks/gallery/style-rtl.css 1.75 kB
build/block-library/blocks/gallery/style.css 1.75 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 654 B
build/block-library/blocks/group/editor.css 654 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 189 B
build/block-library/blocks/heading/style.css 189 B
build/block-library/blocks/html/editor-rtl.css 340 B
build/block-library/blocks/html/editor.css 341 B
build/block-library/blocks/image/editor-rtl.css 834 B
build/block-library/blocks/image/editor.css 833 B
build/block-library/blocks/image/style-rtl.css 1.61 kB
build/block-library/blocks/image/style.css 1.6 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/image/view.min.js 2.02 kB
build/block-library/blocks/latest-comments/style-rtl.css 357 B
build/block-library/blocks/latest-comments/style.css 357 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 505 B
build/block-library/blocks/media-text/style.css 503 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 671 B
build/block-library/blocks/navigation-link/editor.css 672 B
build/block-library/blocks/navigation-link/style-rtl.css 103 B
build/block-library/blocks/navigation-link/style.css 103 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/editor-rtl.css 2.26 kB
build/block-library/blocks/navigation/editor.css 2.26 kB
build/block-library/blocks/navigation/style-rtl.css 2.25 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/navigation/view.min.js 1.1 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 401 B
build/block-library/blocks/page-list/editor.css 401 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 235 B
build/block-library/blocks/paragraph/editor.css 235 B
build/block-library/blocks/paragraph/style-rtl.css 335 B
build/block-library/blocks/paragraph/style.css 335 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 508 B
build/block-library/blocks/post-comments-form/style.css 508 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 141 B
build/block-library/blocks/post-excerpt/style.css 141 B
build/block-library/blocks/post-featured-image/editor-rtl.css 666 B
build/block-library/blocks/post-featured-image/editor.css 662 B
build/block-library/blocks/post-featured-image/style-rtl.css 345 B
build/block-library/blocks/post-featured-image/style.css 345 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 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 409 B
build/block-library/blocks/post-template/style.css 408 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 69 B
build/block-library/blocks/post-time-to-read/style.css 69 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 354 B
build/block-library/blocks/pullquote/style.css 354 B
build/block-library/blocks/pullquote/theme-rtl.css 168 B
build/block-library/blocks/pullquote/theme.css 168 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 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 486 B
build/block-library/blocks/query/editor.css 486 B
build/block-library/blocks/query/style-rtl.css 312 B
build/block-library/blocks/query/style.css 308 B
build/block-library/blocks/query/view.min.js 647 B
build/block-library/blocks/quote/style-rtl.css 237 B
build/block-library/blocks/quote/style.css 237 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 140 B
build/block-library/blocks/read-more/style.css 140 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 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 184 B
build/block-library/blocks/search/editor.css 184 B
build/block-library/blocks/search/style-rtl.css 602 B
build/block-library/blocks/search/style.css 602 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/search/view.min.js 475 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/shortcode/editor-rtl.css 329 B
build/block-library/blocks/shortcode/editor.css 329 B
build/block-library/blocks/site-logo/editor-rtl.css 760 B
build/block-library/blocks/site-logo/editor.css 760 B
build/block-library/blocks/site-logo/style-rtl.css 204 B
build/block-library/blocks/site-logo/style.css 204 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 682 B
build/block-library/blocks/social-links/editor.css 681 B
build/block-library/blocks/social-links/style-rtl.css 1.49 kB
build/block-library/blocks/social-links/style.css 1.49 kB
build/block-library/blocks/spacer/editor-rtl.css 359 B
build/block-library/blocks/spacer/editor.css 359 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 395 B
build/block-library/blocks/table/editor.css 395 B
build/block-library/blocks/table/style-rtl.css 646 B
build/block-library/blocks/table/style.css 645 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 403 B
build/block-library/blocks/template-part/editor.css 403 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/term-description/style-rtl.css 111 B
build/block-library/blocks/term-description/style.css 111 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 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 191 B
build/block-library/blocks/video/style.css 191 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 12.3 kB
build/block-library/editor.css 12.3 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/style-rtl.css 14.7 kB
build/block-library/style.css 14.7 kB
build/block-library/theme-rtl.css 700 B
build/block-library/theme.css 705 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.6 kB
build/commands/index.min.js 15.5 kB
build/commands/style-rtl.css 947 B
build/commands/style.css 942 B
build/components/index.min.js 235 kB
build/components/style-rtl.css 12.1 kB
build/components/style.css 12.1 kB
build/compose/index.min.js 12.8 kB
build/core-commands/index.min.js 2.73 kB
build/core-data/index.min.js 72.7 kB
build/customize-widgets/index.min.js 12.1 kB
build/customize-widgets/style-rtl.css 1.36 kB
build/customize-widgets/style.css 1.36 kB
build/data-controls/index.min.js 651 B
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 462 B
build/dom-ready/index.min.js 336 B
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 24.9 kB
build/edit-post/style-rtl.css 5.68 kB
build/edit-post/style.css 5.68 kB
build/edit-widgets/index.min.js 17.4 kB
build/edit-widgets/style-rtl.css 4.44 kB
build/edit-widgets/style.css 4.43 kB
build/editor/index.min.js 61.7 kB
build/editor/style-rtl.css 5.48 kB
build/editor/style.css 5.48 kB
build/element/index.min.js 4.87 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 7.98 kB
build/format-library/style-rtl.css 500 B
build/format-library/style.css 500 B
build/hooks/index.min.js 1.57 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.61 kB
build/interactivity/file.min.js 442 B
build/interactivity/image.min.js 2.15 kB
build/interactivity/index.min.js 12.6 kB
build/interactivity/navigation.min.js 1.23 kB
build/interactivity/query.min.js 791 B
build/interactivity/search.min.js 610 B
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.76 kB
build/keycodes/index.min.js 1.49 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.92 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 964 B
build/nux/index.min.js 2.01 kB
build/nux/style-rtl.css 775 B
build/nux/style.css 771 B
build/patterns/style-rtl.css 564 B
build/patterns/style.css 564 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 2.08 kB
build/preferences/index.min.js 2.52 kB
build/preferences/style-rtl.css 725 B
build/preferences/style.css 728 B
build/primitives/index.min.js 994 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 1.02 kB
build/react-i18n/index.min.js 631 B
build/react-refresh-entry/index.min.js 9.46 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.71 kB
build/reusable-blocks/index.min.js 2.74 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 10.4 kB
build/router/index.min.js 1.79 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 2.06 kB
build/token-list/index.min.js 587 B
build/url/index.min.js 3.83 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 967 B
build/warning/index.min.js 259 B
build/widgets/index.min.js 7.22 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

{ onDetailsChange && (
<Button
className="dataviews-view-list__details-button"
<TreeGridCell>
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm trying to use the TreeGrid component in DataViews. In trunk, using the list layout, the user moves with tabs through the list of items. See:

Gravacao.do.ecra.2024-01-16.as.18.40.58.mov

Note how this div is acting as a button, and it's a tab stop. When migrating to use TreeGrid, this element is skipped: the focus goes to the next TreeGridCell (details button) instead.

Gravacao.do.ecra.2024-01-16.as.18.46.07.mov

Once the focus is in the button, I cannot reach this div through the arrow keys either (right/left):

Gravacao.do.ecra.2024-01-16.as.18.49.44.mov

Copy link
Member Author

Choose a reason for hiding this comment

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

Pinging people I've seen contributed to this and/or may be interested in following-up. @mirka @andrewhayward @ciampo @talldan @tellthemachines @andrewserong

Copy link
Member Author

Choose a reason for hiding this comment

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

I've tried the following: setting the tabIndex to 0 when the focus is outside the list view and let TreeGrid handle it when it's inside. It doesn't work, once the focus is moved via the arrow keys to the next item, the details button becomes focused:

Gravacao.do.ecra.2024-01-16.as.18.54.11.mov
Diff in case anyone wants to try
diff --git a/packages/dataviews/src/view-list.js b/packages/dataviews/src/view-list.js
index ce1f3a2b4f..18949f2bd5 100644
--- a/packages/dataviews/src/view-list.js
+++ b/packages/dataviews/src/view-list.js
@@ -18,6 +18,7 @@ import {
 import { ENTER, SPACE } from '@wordpress/keycodes';
 import { info } from '@wordpress/icons';
 import { __ } from '@wordpress/i18n';
+import { useRef } from '@wordpress/element';
 
 export default function ViewList( {
        view,
@@ -30,6 +31,7 @@ export default function ViewList( {
        selection,
        deferredRendering,
 } ) {
+       const treeGridRef = useRef();
        const shownData = useAsyncList( data, { step: 3 } );
        const usedData = deferredRendering ? shownData : data;
        const mediaField = fields.find(
@@ -69,8 +71,15 @@ export default function ViewList( {
                );
        }
 
+       const isFocusWithin = () => {
+               if ( ! treeGridRef.current ) {
+                       return false;
+               }
+               return treeGridRef.current.contains( document.activeElement );
+       }
+
        return (
-               <TreeGrid className="dataviews-view-list">
+               <TreeGrid ref={ treeGridRef } className="dataviews-view-list">
                        { usedData.map( ( item, index ) => {
                                return (
                                        <TreeGridRow
@@ -95,7 +104,7 @@ export default function ViewList( {
                                                                                onSelectionChange( [ item ] )
                                                                        }
                                                                        { ...otherProps }
-                                                                       tabIndex={ tabIndex }
+                                                                       tabIndex={ isFocusWithin() ? tabIndex : 0 }
                                                                >
                                                                        <HStack spacing={ 3 } justify="start">
                                                                                <div className="dataviews-view-list__media-wrapper">

Copy link
Contributor

@talldan talldan Jan 17, 2024

Choose a reason for hiding this comment

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

I think the issue is that the <div> element isn't detected as a focusable.

TreeGrid uses the dom package's focusable utility internally, and that doesn't seem to be returning the div as one of the focusable elements in the row. This is the relevant code:

function getRowFocusables( rowElement: HTMLElement ) {
const focusablesInRow = focus.focusable.find( rowElement, {
sequential: true,
} );
return focusablesInRow.filter( ( focusable ) => {
return focusable.closest( '[role="row"]' ) === rowElement;
} );
}

The selector list for focusable is here:

function buildSelector( sequential ) {
return [
sequential ? '[tabindex]:not([tabindex^="-"])' : '[tabindex]',
'a[href]',
'button:not([disabled])',
'input:not([type="hidden"]):not([disabled])',
'select:not([disabled])',
'textarea:not([disabled])',
'iframe:not([tabindex^="-"])',
'object',
'embed',
'area[href]',
'[contenteditable]:not([contenteditable=false])',
].join( ',' );
}

Out of interest, why use a div?

setting the tabIndex to 0 when the focus is outside the list view and let TreeGrid handle it when it's inside.

I think this would prevent the roving tab index from working correctly.

Copy link
Contributor

Choose a reason for hiding this comment

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

I put together an example of a fix in #57905 for you, but IMO it might be better to use a <button> if possible.

I'm also wondering about the suitability of treegrid. I think you should only use it if there's some hierarchy/nesting to the list. Perhaps you have that with parent pages?

It can be fun to style as it makes everything a table 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

I put together an example of a fix in #57905 for you

Nice, thanks Dan! Merged it to keep the conversation in one place.

but IMO it might be better to use a if possible.

I can investigate alternatives.

I'm also wondering about the suitability of treegrid. I think you should only use it if there's some hierarchy/nesting to the list. Perhaps you have that with parent pages?

Yeah, exactly.

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 also wondering about the suitability of treegrid. I think you should only use it if there's some hierarchy/nesting to the list. Perhaps you have that with parent pages?

Yeah, exactly.

Would using Composite be a better alternative? (cc @andrewhayward )

@ciampo
Copy link
Contributor

ciampo commented Jan 17, 2024

Also flagging this PR from @andrewhayward #56513 that may try to achieve a similar result for the Table layout, but using the Composite component.

@jameskoster
Copy link
Contributor

Aside from the technical discussion, here are a couple of notes on the UX based on a discussion I had with Andrew about this last week:

  • Navigating through the list should automatically select each item rather than having to press return.
  • In addition to the details button, there should be a way to access the edit button (the frame).
    • If this isn't feasible, perhaps we need to include an 'edit' action next to the details button?

@oandregal
Copy link
Member Author

oandregal commented Jan 17, 2024

I'm no longer convinced this is a good approach. The reason is that consumers of the DataViews package (Pages, Templates, Patterns, any 3rd party) control field rendering: they can render any focusable element within the list item which will break the interactions. This is a test case: render a link for the title field.

After merging Dan's patch, it was working as expected. Then, I updated the Pages so it renders a link for the title using the patch below.

Patch for rendering a link.
diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js
index 5ef05273be..39cec46a0d 100644
--- a/packages/edit-site/src/components/page-pages/index.js
+++ b/packages/edit-site/src/components/page-pages/index.js
@@ -231,7 +231,7 @@ export default function PagePages() {
                                id: 'title',
                                getValue: ( { item } ) => item.title?.rendered,
                                render: ( { item } ) => {
-                                       return [ LAYOUT_TABLE, LAYOUT_GRID ].includes(
+                                       return [ LAYOUT_TABLE, LAYOUT_GRID, LAYOUT_LIST ].includes(
                                                view.type
                                        ) ? (
                                                <Link

This is the result: the roving tabindex no longer works (users can tab, doesn't find the proper nodes, etc.).

Gravacao.do.ecra.2024-01-17.as.11.50.15.mov

@oandregal
Copy link
Member Author

oandregal commented Jan 17, 2024

In addition to the details button, there should be a way to access the edit button (the frame).

@jameskoster You mean this flow?

  • tab to the list of items
  • arrow key to the target item
  • arrow key to the editor + enter to go to the editor

Right now you can reach it after pagination.

@jameskoster
Copy link
Contributor

You mean this flow?

Yes.

Right now you can reach it after pagination.

That's correct, but I don't suppose it's all that intuitive.

@andrewhayward
Copy link
Contributor

#57895 (comment):

Navigating through the list should automatically select each item rather than having to press return.

This is a tricky one. If the relevant content loads asynchronously, it's generally better to leave it as a manual step, otherwise moving around in the list can cause a lot of overhead. Because this is a flexible and multi-use view, we can't say for sure whether the content is going to be async or not (though I'm guessing in most cases it probably will be), so it's probably better to leave it as is, at least to start.

@jameskoster
Copy link
Contributor

Happy to start with that.

@talldan
Copy link
Contributor

talldan commented Jan 18, 2024

The reason is that consumers of the DataViews package (Pages, Templates, Patterns, any 3rd party) control field rendering: they can render any focusable element within the list item which will break the interactions.

Yeah, that's a tricky one, as it requires wrapping every control in a TreeGridCell and ensuring the onFocus and tabIndex props are managed correctly by those controls. The table markup is also hard to work with both in terms of markup and styling—I'm not sure if it would be a good idea to use the treegrid roles on non-table elements.

I think there is some precedence with the block toolbar and the ToolbarItem component. That also required that extenders follow some best practices.

@andrewhayward
Copy link
Contributor

andrewhayward commented Jan 18, 2024

A few high-level thoughts...

I'm also wondering about the suitability of treegrid. I think you should only use it if there's some hierarchy/nesting to the list.

Would using Composite be a better alternative?

As mentioned above, this isn't really a suitable candidate for a treegrid, as there's no particular tree aspect to it; at least, I'm not seeing any hierarchy of information. You'll definitely get better mileage out of the Composite set of components, as @ciampo suggests.

I'm no longer convinced this is a good approach. The reason is that consumers of the DataViews package (Pages, Templates, Patterns, any 3rd party) control field rendering: they can render any focusable element within the list item which will break the interactions.

Regarding the tab flow aspect, without further testing, I would probably expect it to look something like this:

A diagram showing a potential tab flow through a list of navigation controls

  1. Focus starts at the top, and moves through the various controls, including filters and view settings
  2. It then moves to the first (or most recently focused) item in the list
  3. It then cycles through any interactive content within the list item, should it exist, before reaching the 'info' button
  4. It then moves to the preview panel, if it is loaded
  5. Finally, focus moves to any controls at the end of the list, such as pagination

Step 4 might get a bit weird if the preview panel has further interactive content in it, so we might have to adjust this.

For arrow key navigation, I'd go with something like this:

A diagram showing arrow key movement through a list of navigation controls

  1. Focus starts on the first (or most recently focused) list item
  2. Up and Down move between list items
  3. Left and Right move between a list item and its info button
  4. If an info button is focused, Up and Down move between info buttons
  5. Tab would move to the next appropriate step, as above

consumers of the DataViews package ... can render any focusable element within the list item

Of particular note, if list items can contain interactive elements, we won't be able to have the list item itself be a button, or equivalent...

<!-- ⛔️ We can't do this... -->

<ul>
  ...
  <li class="list-item">
    <button>
      <img src="..." class="thumb">
      <div class="primary">Title</div>
      <div class="fields">
        <a href="...">Field</a>
      </div>
    </button>
    <a href="..." class="info"></a>
  </li>
  ...
</ul>

Instead we'll have to move the actual button to the primary field, but maintain the visual and interactive appearance by being clever with either CSS, or event handlers.

<!-- ✅ This is better... -->

<ul>
  ...
  <li class="list-item">
    <img src="..." class="thumb">
    <button class="primary">Title</button>
    <div class="fields">
      <a href="...">Field</a>
    </div>
    <a href="..." class="info"></a>
  </li>
  ...
</ul>

Let me know if there are any specific questions, or if you want any help wrangling that in Composite.

@talldan
Copy link
Contributor

talldan commented Jan 18, 2024

As mentioned above, this isn't really a suitable candidate for a treegrid, as there's no particular tree aspect to it

I took @oandregal's response to mean that there is a tree aspect to it (parent/child pages).

From memory, I think TreeGrid support is still a bit ropey in screenreaders, I'm not sure there's any inbuilt announcements about nesting, so a grid that relays adequate information about nesting might be just as good. 🤷

@oandregal
Copy link
Member Author

The hierarchical relationship exists, but we haven't defined how to visualize it yet. I wanted to try the TreeGrid because I saw it as the tried and tested component for these situations. But, as I mentioned, I no longer believe this is the right approach.

Keep the comments coming, it had been already useful to clarify expectations around interactions.

@andrewhayward
Copy link
Contributor

andrewhayward commented Jan 18, 2024

...we'll have to move the actual button to the primary field, but maintain the visual and interactive appearance...

Just to follow up on this bit quickly, we can achieve the end goal here with the following mark-up (presentational stuff omitted):

HTMLCSS
<div class="wrapper">
  <div class="primary">
    <button>Item Title</button>
  </div>
  <div class="preview">
    🖼️
  </div>
  <div class="fields">
    <a href="...">Author Name</a>
  </div>
  <div class="info">
    <a href="..."></a>
  </div>
</div>
.wrapper {
  position: relative;
  display: grid;
  grid-template: "preview primary info" ...
                 "preview fields  info" ...
                / ...;
}

.primary button::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.primary button:focus-visible {
  outline: none;
}

.primary button:focus-visible::before {
  outline: ...;
}

The tab flow through the above markup, first appearing to capture the entire block, before cycling through the author name and info link

Copy link
Contributor

@andrewhayward andrewhayward left a comment

Choose a reason for hiding this comment

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

Good start – hopefully the feedback is helpful. Thanks for working on this.

@oandregal
Copy link
Member Author

Closing in favor of #59637

@oandregal oandregal closed this Mar 11, 2024
@oandregal oandregal deleted the update/dataviews-list-layout-keyboard-navigation branch March 11, 2024 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond [Type] Experimental Experimental feature or API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants