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: add actions to list layout #60805

Merged
merged 32 commits into from
May 14, 2024
Merged

Conversation

oandregal
Copy link
Member

@oandregal oandregal commented Apr 17, 2024

Part of #59659 and #55083
Follow-up to #59637
Fixes #61555

What?

This PR adds support for actions in list layout, which is only enabled for Pages and Templates as of now:

Pages Templates
Captura de ecrã 2024-05-10, às 11 49 29 Captura de ecrã 2024-05-10, às 11 49 23

This PR also enables two-dimensional arrow-key navigation:

Gravacao.do.ecra.2024-05-10.as.11.53.21.mov

Why?

We want to make them available. See #59659

How?

  • Pass the existing actions prop that any other layout is using to the list view layout.
  • Add two-dimensional arrow navigation to the list items, so users can use right/left arrow keys to move between the element and its actions.

Testing Instructions

  • Go to a page with list view (Pages or Templates) and verify the actions are present.
  • Navigate via keyboard to verify that it works as expected:
    • The item list is a single tab stop.
    • You can vertically through the list via up/down arrow keys.
    • You can move horizontally within a single item via right/left arrow keys.

@oandregal oandregal self-assigned this Apr 17, 2024
@oandregal oandregal added [Type] Enhancement A suggestion for improvement. [Feature] DataViews Work surrounding upgrading and evolving views in the site editor and beyond labels Apr 17, 2024
Copy link

github-actions bot commented Apr 17, 2024

Size Change: +164 B (+0.01%)

Total Size: 1.75 MB

Filename Size Change
build/block-editor/index.min.js 259 kB -86 B (-0.03%)
build/block-library/blocks/shortcode/editor-rtl.css 286 B -37 B (-11.46%) 👏
build/block-library/blocks/shortcode/editor.css 286 B -37 B (-11.46%) 👏
build/block-library/editor-rtl.css 12.3 kB -14 B (-0.11%)
build/block-library/editor.css 12.2 kB -14 B (-0.11%)
build/block-library/index.min.js 218 kB -22 B (-0.01%)
build/edit-site/index.min.js 220 kB +289 B (+0.13%)
build/edit-site/style-rtl.css 12.9 kB +41 B (+0.32%)
build/edit-site/style.css 12.9 kB +44 B (+0.34%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 955 B
build/annotations/index.min.js 2.27 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.1 kB
build/blob/index.min.js 578 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1.03 kB
build/block-directory/style.css 1.03 kB
build/block-editor/content-rtl.css 4.57 kB
build/block-editor/content.css 4.57 kB
build/block-editor/default-editor-styles-rtl.css 395 B
build/block-editor/default-editor-styles.css 395 B
build/block-editor/style-rtl.css 15.5 kB
build/block-editor/style.css 15.5 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 133 B
build/block-library/blocks/audio/theme.css 133 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 277 B
build/block-library/blocks/block/editor.css 277 B
build/block-library/blocks/button/editor-rtl.css 415 B
build/block-library/blocks/button/editor.css 414 B
build/block-library/blocks/button/style-rtl.css 627 B
build/block-library/blocks/button/style.css 626 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 671 B
build/block-library/blocks/cover/editor.css 674 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 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 312 B
build/block-library/blocks/embed/editor.css 312 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 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 327 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 324 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 227 B
build/block-library/blocks/form-input/editor.css 227 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 340 B
build/block-library/blocks/form-submission-notification/editor.css 340 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 471 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 956 B
build/block-library/blocks/gallery/editor.css 960 B
build/block-library/blocks/gallery/style-rtl.css 1.72 kB
build/block-library/blocks/gallery/style.css 1.72 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 394 B
build/block-library/blocks/group/editor.css 394 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 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 336 B
build/block-library/blocks/html/editor.css 337 B
build/block-library/blocks/image/editor-rtl.css 891 B
build/block-library/blocks/image/editor.css 891 B
build/block-library/blocks/image/style-rtl.css 1.6 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 133 B
build/block-library/blocks/image/theme.css 133 B
build/block-library/blocks/image/view.min.js 1.54 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 306 B
build/block-library/blocks/media-text/editor.css 305 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 668 B
build/block-library/blocks/navigation-link/editor.css 669 B
build/block-library/blocks/navigation-link/style-rtl.css 193 B
build/block-library/blocks/navigation-link/style.css 192 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 296 B
build/block-library/blocks/navigation-submenu/editor.css 295 B
build/block-library/blocks/navigation/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.26 kB
build/block-library/blocks/navigation/style.css 2.25 kB
build/block-library/blocks/navigation/view.min.js 1.03 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/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-content/editor-rtl.css 74 B
build/block-library/blocks/post-content/editor.css 74 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 734 B
build/block-library/blocks/post-featured-image/editor.css 732 B
build/block-library/blocks/post-featured-image/style-rtl.css 342 B
build/block-library/blocks/post-featured-image/style.css 342 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 397 B
build/block-library/blocks/post-template/style.css 396 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 353 B
build/block-library/blocks/pullquote/theme-rtl.css 174 B
build/block-library/blocks/pullquote/theme.css 174 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/view.min.js 958 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 233 B
build/block-library/blocks/quote/theme.css 235 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 156 B
build/block-library/blocks/rss/editor.css 157 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 690 B
build/block-library/blocks/search/style.css 689 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 478 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 239 B
build/block-library/blocks/separator/style.css 239 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 B
build/block-library/blocks/site-logo/editor-rtl.css 805 B
build/block-library/blocks/site-logo/editor.css 805 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 324 B
build/block-library/blocks/social-link/editor.css 324 B
build/block-library/blocks/social-links/editor-rtl.css 676 B
build/block-library/blocks/social-links/editor.css 675 B
build/block-library/blocks/social-links/style-rtl.css 1.48 kB
build/block-library/blocks/social-links/style.css 1.48 kB
build/block-library/blocks/spacer/editor-rtl.css 350 B
build/block-library/blocks/spacer/editor.css 350 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 639 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 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 393 B
build/block-library/blocks/template-part/editor.css 393 B
build/block-library/blocks/template-part/theme-rtl.css 107 B
build/block-library/blocks/template-part/theme.css 107 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 185 B
build/block-library/blocks/video/style.css 185 B
build/block-library/blocks/video/theme-rtl.css 133 B
build/block-library/blocks/video/theme.css 133 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/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.8 kB
build/block-library/style.css 14.8 kB
build/block-library/theme-rtl.css 707 B
build/block-library/theme.css 713 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/blocks/index.min.js 51.7 kB
build/commands/index.min.js 15.1 kB
build/commands/style-rtl.css 953 B
build/commands/style.css 951 B
build/components/index.min.js 222 kB
build/components/style-rtl.css 11.9 kB
build/components/style.css 11.9 kB
build/compose/index.min.js 12.8 kB
build/core-commands/index.min.js 2.81 kB
build/core-data/index.min.js 72.5 kB
build/customize-widgets/index.min.js 10.9 kB
build/customize-widgets/style-rtl.css 1.36 kB
build/customize-widgets/style.css 1.36 kB
build/data-controls/index.min.js 640 B
build/data/index.min.js 9 kB
build/date/index.min.js 17.9 kB
build/deprecated/index.min.js 451 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.65 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 578 B
build/edit-post/index.min.js 14.6 kB
build/edit-post/style-rtl.css 2.68 kB
build/edit-post/style.css 2.68 kB
build/edit-widgets/index.min.js 17.5 kB
build/edit-widgets/style-rtl.css 4.18 kB
build/edit-widgets/style.css 4.18 kB
build/editor/index.min.js 85.3 kB
build/editor/style-rtl.css 8.33 kB
build/editor/style.css 8.33 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.07 kB
build/format-library/style-rtl.css 493 B
build/format-library/style.css 492 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.58 kB
build/interactivity/debug.min.js 16.2 kB
build/interactivity/file.min.js 447 B
build/interactivity/image.min.js 1.67 kB
build/interactivity/index.min.js 13 kB
build/interactivity/navigation.min.js 1.17 kB
build/interactivity/query.min.js 740 B
build/interactivity/router.min.js 2.79 kB
build/interactivity/search.min.js 618 B
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.3 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.11 kB
build/list-reusable-blocks/style-rtl.css 851 B
build/list-reusable-blocks/style.css 851 B
build/media-utils/index.min.js 2.92 kB
build/modules/importmap-polyfill.min.js 12.2 kB
build/notices/index.min.js 948 B
build/nux/index.min.js 1.57 kB
build/nux/style-rtl.css 748 B
build/nux/style.css 744 B
build/patterns/index.min.js 6.45 kB
build/patterns/style-rtl.css 595 B
build/patterns/style.css 595 B
build/plugins/index.min.js 1.8 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/index.min.js 2.85 kB
build/preferences/style-rtl.css 710 B
build/preferences/style.css 712 B
build/primitives/index.min.js 809 B
build/priority-queue/index.min.js 1.52 kB
build/private-apis/index.min.js 1 kB
build/react-i18n/index.min.js 623 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.78 kB
build/redux-routine/index.min.js 2.7 kB
build/reusable-blocks/index.min.js 2.7 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.1 kB
build/router/index.min.js 1.93 kB
build/server-side-render/index.min.js 1.96 kB
build/shortcode/index.min.js 1.39 kB
build/style-engine/index.min.js 2.02 kB
build/token-list/index.min.js 582 B
build/url/index.min.js 3.74 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react.min.js 4.03 kB
build/viewport/index.min.js 957 B
build/warning/index.min.js 249 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.17 kB
build/widgets/style.css 1.17 kB
build/wordcount/index.min.js 1.02 kB

compressed-size-action

@oandregal
Copy link
Member Author

oandregal commented Apr 17, 2024

Keyboard interaction: the actions button should be reachable via the left arrow key, not by tabbing.

#59637 introduced arrow-key navigation for the list items. I don't remember the details, but my expectation was that there was a single tab stop for the list items (the whole item) and the actions button (called details button at the time) was reachable via arrow keys (right/left).

Code changed a bit since and this PR re-introduces the actions button, though it's not working as I expected (note how the tab navigation actually goes into the action button and right-left arrow keys don't work):

Gravacao.do.ecra.2024-04-17.as.11.37.30.mov

Compare with the editor's list view behaviour:

Gravacao.do.ecra.2024-04-17.as.11.43.53.mov

@oandregal oandregal added the [Status] In Progress Tracking issues with work in progress label Apr 29, 2024
@oandregal oandregal force-pushed the add/actions-to-list-layout branch from 684cd5d to 2f42280 Compare April 30, 2024 11:59
@oandregal
Copy link
Member Author

oandregal commented Apr 30, 2024

By adding a second <CompositeItem> within the same <CompositeRow> this PR is trying to add two-dimensional arrow key navigation:

  • top/bottom arrow navigates up/down through the list of items
  • left/right arrow navigates within a single item: item <=> actions button

According to the AriaKit's docs for Composite, two-dimensional navigation works by using the following (we use a store instead of a CompositeProvider):

  <Composite store={store}>
    <CompositeRow>
      <CompositeItem>Item 1.1</CompositeItem>
      <CompositeItem>Item 1.2</CompositeItem>
    </CompositeRow>
    <CompositeRow>
      <CompositeItem>Item 2.1</CompositeItem>
      <CompositeItem>Item 2.2</CompositeItem>
    </CompositeRow>
  </Composite>

That's our basic structure, though we use the render prop to control what's rendered for the CompositeItem:

  <Composite store={store}>
    <CompositeRow>
      <CompositeItem>Item 1.1</CompositeItem>
      <CompositeItem render={<button>Item 1.2</button>} />
    </CompositeRow>
    <CompositeRow>
      <CompositeItem>Item 2.1</CompositeItem>
      <CompositeItem render={<button>Item 2.2</button>} />
    </CompositeRow>
  </Composite>

This is all well, and works as expected (codesandbox demo):

Gravacao.do.ecra.2024-04-30.as.14.10.23.mov

However, this stops working as soon as the DropdownMenu component is used as the render prop. Here's a minimal codesandbox demo.

Pinging some of the @WordPress/gutenberg-components minds for feedback.

@DaniGuardiola
Copy link
Contributor

Hi there @oandregal 👋 😄

I want to help. Two questions:

  1. Did you find a solution or workaround?
  2. Did you report this in the Ariakit repo? If so, can you link it?

cc @mirka as I believe you were looking into this.

I could take a look and try to fix this in Ariakit's side.

@oandregal
Copy link
Member Author

oandregal commented May 6, 2024

Hi @DaniGuardiola thanks for offering help :)

Just this morning was tinkering with the example Lena shared in slack using only Ariaki components, and modified it so it has multiple rows. It demonstrates how Menus don't work well with composite (or there's some config that I'm missing).

I've looked into Ariakit's Github, and didn't find any issue for this. The only issue related to composite is ariakit/ariakit#3170 created by Andrew, but it's a bit different one.

Issue created upstream at ariakit/ariakit#3768

actions,
data,
fields,
Copy link
Member Author

Choose a reason for hiding this comment

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

This is just sorting the props alphabetically.

@@ -175,14 +175,14 @@ function GridItem( {
}

export default function ViewGrid( {
actions,
Copy link
Member Author

Choose a reason for hiding this comment

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

This is just sorting the prop alphabetically.

actions={ actions }
data={ data }
fields={ _fields }
Copy link
Member Author

Choose a reason for hiding this comment

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

Sorts the props alphabetically.

@oandregal oandregal force-pushed the add/actions-to-list-layout branch from 2f42280 to f377520 Compare May 8, 2024 11:52
@oandregal
Copy link
Member Author

oandregal commented May 8, 2024

As per the conversation at ariakit/ariakit#3768 and this example by Dani https://stackblitz.com/edit/vitejs-vite-p27qhy?file=src%2FApp.tsx&terminal=dev there seems to be a way to make two dimensional arrow key navigation work with Ariakit's components.

Specifically, this bit is the key:

          <Ariakit.CompositeRow>
            <Ariakit.CompositeItem render={<button>Button</button>} />
            <Ariakit.MenuProvider>
              {/* here, CompositeItem has precedence and pressing arrow down
              goes downwards in the 2d composite as expected */}
              <Ariakit.CompositeItem
                store={store}
                render={<Ariakit.MenuButton>Menu</Ariakit.MenuButton>}
              />
              <Ariakit.Menu>
                <Ariakit.MenuItem>Hello</Ariakit.MenuItem>
              </Ariakit.Menu>
            </Ariakit.MenuProvider>

            <Ariakit.CompositeItem render={<button>Button</button>} />
          </Ariakit.CompositeRow>
Gravacao.do.ecra.2024-05-08.as.14.11.31.mov

I'm looking into how we can achieve the same with the existing @wordpress/components we have.

@oandregal
Copy link
Member Author

Sharing my ongoing work, as per the slack conversation. In dc0f82d I switched to use the underlying Ariakit components directly, and it's working:

Gravacao.do.ecra.2024-05-08.as.16.26.14.mov

Of course, we want to use the @wordpress/components instead, and I'm still investigating how to do that without breaking the keyboard interactions.

onSelectionChange,
selection,
id: preferredId,
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing it because it's not used.

@oandregal
Copy link
Member Author

Using the Composite* items from @wordpress/components as of e97be2b still works as expected. The last bit is substituting the following by @wordpress/components:

<Ariakit.MenuProvider>
    <CompositeItem
        store={ store }
        render={
            <Ariakit.MenuButton>Menu</Ariakit.MenuButton>
        }
    />
    <Ariakit.Menu>
        <Ariakit.MenuItem>Hello</Ariakit.MenuItem>
    </Ariakit.Menu>
</Ariakit.MenuProvider>

@DaniGuardiola
Copy link
Contributor

DaniGuardiola commented May 8, 2024

I'm not sure why we want to use wordpress components here. Are the styles the exact same? These components are little more than themed and slightly more abstracted Ariakit components, not necessarily meant to be low-level. I think using Ariakit components here directly is fine unless you need to reuse a significant mount of styles from the wordpress component in question.

Edit: I think I misunderstood what's being done here. Is this DataViews component supposed to be composed with other components by its consumer?

@oandregal
Copy link
Member Author

As of f10e368 I've got it working with @wordpress/components:

Gravacao.do.ecra.2024-05-08.as.17.18.50.mov

It's not complete, I need to add support for primary actions, verify everything is working properly, etc. Also see if there's ways to modify ItemActions so I can reuse here — as soon as we start improving the other layouts to add arrow key navigation I presume we'll run into the same issues with this component.

@oandregal
Copy link
Member Author

I'm not sure why we want to use wordpress components here. Are the styles the exact same? These components are little more than themed and slightly more abstracted Ariakit components, not necessarily meant to be low-level. I think using Ariakit components here directly is fine unless you need to reuse a significant mount of styles from the wordpress component in question.

As far as my understanding goes, using Ariakit directly is not allowed — there's even lint rules that prevent you from committing if you do so. I'm not sure why this is. Anyway, I've got this PR working with @wordpress/components :)

@tyxla
Copy link
Member

tyxla commented May 8, 2024

I'm not sure why we want to use wordpress components here. Are the styles the exact same? These components are little more than themed and slightly more abstracted Ariakit components, not necessarily meant to be low-level. I think using Ariakit components here directly is fine unless you need to reuse a significant mount of styles from the wordpress component in question.

As far as my understanding goes, using Ariakit directly is not allowed — there's even lint rules that prevent you from committing if you do so. I'm not sure why this is. Anyway, I've got this PR working with @wordpress/components :)

This is correct and very intentional. The @wordpress/components package uses Ariakit under the hood, but we aim to keep this an implementation detail and not something that the end user has to care about. For various reasons, we want to add custom layers on top of Ariakit, and using Ariakit components directly might prevent the consumers from leveraging the benefits of those layers. Keeping those internals private is also helpful in case we decide to start using a different underlying library for component X.

@oandregal
Copy link
Member Author

Interaction-wise, this is working now with every kind of action (modal & non modal):

Gravacao.do.ecra.2024-05-09.as.11.11.09.mov

I still have to test all action flows and verify that everything works properly. I'm also looking for opportunities to improve the existing code now that it's working, so things can change a bit code-wise.

@youknowriad @jameskoster While I do that, I'd welcome feedback on the following:

What primary actions should we display in Pages & Templates in the list view? The same as in any other view or limit it only to Edit?

Page Primary actions for Table layout Primary actions for Grid layout Primary actions for List layout
Templates Edit - Edit
Pages Edit, View, Trash - Edit

The original issue suggested only Edit #59659 and that sounds good to me, but I wanted to double check. I plan to implement this in consumer-land, not as a new dataviews API: this is, the Pages component will change the primary actions depending on layout.

@@ -401,6 +401,7 @@
li {
margin: 0;
cursor: pointer;
border-top: 1px solid $gray-100;
Copy link
Member Author

Choose a reason for hiding this comment

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

Move the border to the topmost HTML element. The .dataviews-view-list__item only targets the item but not the actions.

@youknowriad
Copy link
Contributor

The original issue suggested only Edit #59659 and that sounds good to me, but I wanted to double check. I plan to implement this in consumer-land, not as a new dataviews API: this is, the Pages component will change the primary actions depending on layout.

Edit as the only primary action makes sense but I actually wonder about adding more things to think about from a consumer's perspective. What if we just say: The list action can only have one primary action and it's always the first action?

primaryField?: NormalizedField;
store: any;
Copy link
Member Author

Choose a reason for hiding this comment

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

Unsure if there's a better way to type this https://ariakit.org/reference/use-composite-store

Copy link
Member

Choose a reason for hiding this comment

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

import type { CompositeStore } from '@ariakit/react'; should do it. We actually export this type from the v2 composite module (and you can see it used here), but I don't think we re-export it from the components package. @mirka any idea if this is intentional? I'd be fine to export the type.

Copy link
Member

Choose a reason for hiding this comment

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

I've been trying to avoid us having to export types from the package, to reduce maintenance cost. The suggested way is to extract the types from the components/hooks that we export.

type CompositeStore = React.ComponentProps< typeof Composite >[ 'store' ];
type CompositeStoreProps = Parameters< typeof useCompositeStore >[ 0 ];

Though, I was looking at this specific case and noticed that the unlock() function for private APIs is typed in a way that doesn't preserve the original types of the locked objects. I'll look into that.

@jameskoster
Copy link
Contributor

What if we just say: The list action can only have one primary action and it's always the first action?

I wouldn't be opposed to that, but I also don't mind keeping all primary actions visible for consistency with table layout, so long as we tweak the visuals a little:

Screenshot 2024-05-09 at 13 27 07
  • Actions are only visible on the selected row, or when a row is focused/hovered.
  • Actions are positioned in the top-right corner to take up less space.

@oandregal oandregal force-pushed the add/actions-to-list-layout branch from 1a5b41d to b003ae4 Compare May 10, 2024 09:51
interface ListViewProps {
view: ViewListType;
fields: NormalizedField[];
actions: Action[];
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the only new prop, the other changes sort the props alphabetically.


interface Action {
callback: ( items: Item[] ) => void;
icon: any;
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 not sure how to provide the type for this. Happy to prepare a follow-up to improve it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I've actually provided types for all the actions in #61400 but unfortunately my PR is blocked because of some unrelated failure. Maybe we should just extract the action types from my PR and land it (without actually typing item-actions.js). I'll try this in its own PR and we can reuse these types here instead.

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 actually tried adding IconType as you do in your PR, but that made this PR fail locally.

@@ -192,6 +369,24 @@ export default function ViewList( props: ListViewProps ) {
defaultActiveId: getItemDomId( selectedItem ),
} );

// Manage focused item, when the active one is removed from the list.
const isActiveIdInList = store.useState(
( state: { items: any[]; activeId: any } ) =>
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 not sure how to provide the type for this. Happy to prepare a follow-up to improve it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure exactly either, I guess this needs usage of ariakit types?

Regardless, it's a bit weird that we have to use all these low level hooks (store and what not). I'm guessing the components API of ariakit is not easily usable for us here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Regardless, it's a bit weird that we have to use all these low level hooks (store and what not). I'm guessing the components API of ariakit is not easily usable for us here?

Yeah. Each has its own reason:

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the details.

we need to handle onkeydown for the "all actions" button to make sure arrow down doesn't open the menu but goes down the list. This is an issue with our Dropdown, as it works fine with Ariakit components.

Maybe I'm not testing properly but for me it was actually opening the menu (and I felt that it was ok :P )

As per #60805 (comment) when deleting an element, we need to take care of updating activeId as ariakit doesn't do it for us.

Couldn't that be considered a bug to be solved in ariakit?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just saw the ariakit issue :)

Copy link
Member Author

Choose a reason for hiding this comment

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

cc @WordPress/gutenberg-components for awareness. This PR implements two-dimensional arrow-key navigation with Ariakit's Composite & our own components. I'm leaving some comments for your awareness, in case we want to smooth it as an API. I plan to do similar work for other dataviews' layout in a few weeks.

I had to use the store's state in this PR, so I needed access to some types. I presume any can be improved by using Ariakit's types directly, but I also want to bring it up as another case where we may want to re-export from our components package.

@oandregal
Copy link
Member Author

All issues and feedback have been addressed, just waiting for an approval :)

@youknowriad
Copy link
Contributor

In terms of behavior this is working great for me. I did notice the double snackbars (inside and outside the preview but these should probably be solved separately)

@@ -142,23 +205,137 @@ function ListItem( {
</HStack>
</CompositeItem>
</div>
{ actions?.length > 0 && (
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand why we can't reuse item-actions here? (Maybe with a new prop that indicates that we should only use one primary action). What's the other differences between this and item actions?

Copy link
Member Author

@oandregal oandregal May 14, 2024

Choose a reason for hiding this comment

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

These are the differences: every button trigger needs to be wrapped by a CompositeItem that receives the composite store, the "all actions" button needs to handle onkeydown event on their own, it only renders 1 primary action.

An alternative to make ItemActions work for this layout would be adding ifs everywhere, though I discarded it because it is too intertwined. When table and grid layout improve the keyboard interactions, ItemActions would actually be more reusable as all the layouts would share the same logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

When table and grid layout improve the keyboard interactions, ItemActions would actually be more reusable as all the layouts would share the same logic.

With the gained ariakit/composite experience, I actually want to tackle that next, though it'll probably land for 6.7.

Copy link
Contributor

Choose a reason for hiding this comment

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

An alternative to make ItemActions work for this layout would be adding ifs everywhere, though I discarded it because it is too intertwined. When table and grid layout improve the keyboard interactions, ItemActions would actually be more reusable as all the layouts would share the same logic.

How can we make sure we actually do that and not end up with two similar components.

Copy link
Member Author

Choose a reason for hiding this comment

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

How can we make sure we actually do that and not end up with two similar components.

We'll have more info about the proper abstractions for the actions component when keyboard interactions are improved for other layouts. The existing proved not enough to use with Composite, for example. Personally, I won't be able to start looking into this until end of May/first of June, the soonest. If we'd rather have a single component that accommodates all the possible use cases in the interim, I'm happy to switch the implementation.

store.move( store.up() );
}
}
}, [ isActiveIdInList ] );
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a very weird effect, why do we have this adhoc logic in our view?

Copy link
Member Author

Choose a reason for hiding this comment

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

It fixes this behavior (see related ariakit issue).

Copy link
Member Author

@oandregal oandregal May 14, 2024

Choose a reason for hiding this comment

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

cc @WordPress/gutenberg-components for awareness. This PR implements two-dimensional arrow-key navigation with Ariakit's Composite & our own components. I'm leaving some comments for your awareness, in case we want to smooth it as an API. I plan to do similar work for other dataviews' layout in a few weeks.

This makes sure the internal ariakit index is updated when an element is updated (see).

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

Good looks generally good but I do believe that we should just reuse item actions. So I'd like to understand more why we can't reuse it?

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

LGTM 👍 but I think we should add e2e tests here to ensure the keyboard navigation and everything don't regress. These things can easily regress.

@oandregal oandregal enabled auto-merge (squash) May 14, 2024 08:21
@oandregal oandregal merged commit 5ea53bb into trunk May 14, 2024
62 of 63 checks passed
@oandregal oandregal deleted the add/actions-to-list-layout branch May 14, 2024 08:54
@github-actions github-actions bot added this to the Gutenberg 18.4 milestone May 14, 2024
@oandregal
Copy link
Member Author

I'm adding e2e tests for this at #61648

@jameskoster
Copy link
Contributor

Nice work on this 🚀

A couple of follow-ups;

  • I think the icons size / position can be adjusted slightly so they take up less space, similar to DataViews: add actions to list layout #60805 (comment)
  • The show/hide mechanic should probably be applied to the wrapper, because currently titles appear truncated unnecessarily early:
Screenshot 2024-05-14 at 11 49 41

Copy link
Contributor

@mcsf mcsf left a comment

Choose a reason for hiding this comment

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

Nice work.

Comment on lines +147 to +148
onMouseEnter={ handleMouseEnter }
onMouseLeave={ handleMouseLeave }
Copy link
Contributor

Choose a reason for hiding this comment

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

Super minor, but with these tiny functions I think it's more readable if it's all inlined (especially since they aren't even using useCallback:

onMouseEnter={ () => setIsHovered( true ) }

Comment on lines +243 to +244
onActionStart={ () => {} }
onActionPerformed={ () => {} }
Copy link
Contributor

Choose a reason for hiding this comment

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

Why pass empty functions at all?

Copy link
Member Author

Choose a reason for hiding this comment

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

Typescript :)

Thanks for bring it up. I added this at some point so Typescript let me focus on behavioral issues rather than ortographical things but forgot to add a TODO marker to come back to it later. Prepared a follow-up to fix this at #61659

@oandregal oandregal mentioned this pull request May 14, 2024
33 tasks
@@ -2,6 +2,9 @@
* External dependencies
*/
import clsx from 'clsx';
// Import CompositeStore type, which is not exported from @wordpress/components.
// eslint-disable-next-line no-restricted-imports
import type { CompositeStore } from '@ariakit/react';
Copy link
Member Author

@oandregal oandregal May 14, 2024

Choose a reason for hiding this comment

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

cc @WordPress/gutenberg-components for awareness. This PR implements two-dimensional arrow-key navigation with Ariakit's Composite & our own components. I'm leaving some comments for your awareness, in case we want to smooth it as an API. I plan to do similar work for other dataviews' layout in a few weeks.

I presume we should re-export the type from our components package?

icon={ moreVertical }
label={ __( 'Actions' ) }
disabled={ ! actions.length }
onKeyDown={ ( event: {
Copy link
Member Author

@oandregal oandregal May 14, 2024

Choose a reason for hiding this comment

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

cc @WordPress/gutenberg-components for awareness. This PR implements two-dimensional arrow-key navigation with Ariakit's Composite & our own components. I'm leaving some comments for your awareness, in case we want to smooth it as an API. I plan to do similar work for other dataviews' layout in a few weeks.

I had to implement the onKeyDown event in the trigger Button to prevent the arrow down from opening the menu. That's not necessarily when using Ariakit directly, see example at ariakit/ariakit#3768

@youknowriad
Copy link
Contributor

Even though the "navigate" metric in the site editor is a bit unstable in our tests, I do think this PR had a small impact on the numbers there. I wonder if you have ideas.

@oandregal
Copy link
Member Author

Even though the "navigate" metric in the site editor is a bit unstable in our tests, I do think this PR had a small impact on the numbers there. I wonder if you have ideas.

Yeah, I agree. I've tried before/after locally and I see a consistent +15ms after this PR. This is what I've looked at (the same as the navigate performance test):

  • set up SCRIPT_DEBUG & WP_DEBUG to false in the env
  • visit the templates page & switched to list layout
  • start performance trace and click on "Single posts" item, so the preview is updated
  • inspect the duration of the click event

Codehealth after this commit reports a higher mean number as well:

Captura de ecrã 2024-05-15, às 12 34 59

I've looked at browser's performance traces and they are very similar (before.json.zip & after.json.zip, for anyone to import into devtools and inspect):

Before After
Captura de ecrã 2024-05-15, às 12 33 19 Captura de ecrã 2024-05-15, às 12 33 05

The major thing I've noticed is the Role component coming from Ariakit's reac-core package (imported from @wordpress/components). While it exists in both traces, it takes +8ms more in the after trace. What's intriguing is that it's not called more times, it just takes more time to do the same number of calls:

Before After
Captura de ecrã 2024-05-15, às 13 07 14 Captura de ecrã 2024-05-15, às 13 06 57

So I guess it's fair to say that the performance hit comes from the internal components/ariakit code, which is in line with what this PR does:

  • adds dropdown from @wordpress/components that also uses ariakit under the hood
  • adds more composite items (primary action + all actions buttons)
  • uses the composite store to do some things

Further debugging would require looking more deeply at how @wordpress/components and Ariakit works, to understand how it can be improved. Hope this serves as a starting point.

@youknowriad
Copy link
Contributor

I suspect it's the fact that we're actually rendering more components (The actions dropdown) and re-rendering them when we select new pages. One thing to check is whether these things re-render too much and if we can limit the re-renderings.

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] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Editor > Pages: It is impossible to access the editor on mobile
7 participants