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

Experiment: Replicate Navigation block using directives (Alpinejs) #44289

Closed

Conversation

SantosGuillamot
Copy link
Contributor

@SantosGuillamot SantosGuillamot commented Sep 20, 2022

What?

This is an experiment to replicate the functionalities of the navigations block but using directives. In this case we are using Alpinejs. This is part of the directives hydration experiment.

Why?

In the directives hydration experiment we have started using directives, and we want to understand which ones would be needed for this use case.

It is worth mentioning that this is just an experiment with learning purposes. We want to understand better the directives that are needed and I am not suggesting we should use AlpineJS instead of micromodal.

How?

I removed the micromodal library and added AlpineJS (with the @alpine/focus plugin) instead. From there, I am just adding the directives needed to replicate the behaviour.

Testing Instructions

Just open a site with the navigation block and check everything is working as expected.

@SantosGuillamot SantosGuillamot added the [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible label Sep 20, 2022
@github-actions
Copy link

github-actions bot commented Sep 20, 2022

Size Change: -2.97 kB (0%)

Total Size: 1.25 MB

Filename Size Change
build/block-directory/index.min.js 7.08 kB +26 B (0%)
build/block-editor/index.min.js 163 kB +371 B (0%)
build/block-editor/style-rtl.css 15.4 kB +1 B (0%)
build/block-editor/style.css 15.4 kB +4 B (0%)
build/block-library/blocks/navigation/view-modal.min.js 0 B -2.78 kB (removed) 🏆
build/block-library/blocks/navigation/view.min.js 0 B -443 B (removed) 🏆
build/block-library/index.min.js 190 kB +112 B (0%)
build/components/index.min.js 198 kB +180 B (0%)
build/customize-widgets/style-rtl.css 1.38 kB +5 B (0%)
build/customize-widgets/style.css 1.38 kB +5 B (0%)
build/edit-post/index.min.js 30.8 kB +26 B (0%)
build/edit-site/index.min.js 57.6 kB -379 B (-1%)
build/editor/index.min.js 41.6 kB -25 B (0%)
build/editor/style-rtl.css 3.62 kB -39 B (-1%)
build/editor/style.css 3.61 kB -41 B (-1%)
build/style-engine/index.min.js 1.45 kB +6 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/style-rtl.css 990 B
build/block-directory/style.css 991 B
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 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 126 B
build/block-library/blocks/audio/theme.css 126 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 84 B
build/block-library/blocks/avatar/style.css 84 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 482 B
build/block-library/blocks/button/editor.css 482 B
build/block-library/blocks/button/style-rtl.css 523 B
build/block-library/blocks/button/style.css 523 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 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 100 B
build/block-library/blocks/categories/style.css 100 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 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-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 187 B
build/block-library/blocks/comment-template/style.css 185 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 834 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 630 B
build/block-library/blocks/cover/editor-rtl.css 605 B
build/block-library/blocks/cover/editor.css 607 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.55 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 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 126 B
build/block-library/blocks/embed/theme.css 126 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 253 B
build/block-library/blocks/file/style.css 254 B
build/block-library/blocks/file/view.min.js 346 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 948 B
build/block-library/blocks/gallery/editor.css 950 B
build/block-library/blocks/gallery/style-rtl.css 1.53 kB
build/block-library/blocks/gallery/style.css 1.53 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 337 B
build/block-library/blocks/group/editor.css 337 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 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 327 B
build/block-library/blocks/html/editor.css 329 B
build/block-library/blocks/image/editor-rtl.css 876 B
build/block-library/blocks/image/editor.css 873 B
build/block-library/blocks/image/style-rtl.css 627 B
build/block-library/blocks/image/style.css 630 B
build/block-library/blocks/image/theme-rtl.css 126 B
build/block-library/blocks/image/theme.css 126 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 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 463 B
build/block-library/blocks/latest-posts/style.css 462 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 507 B
build/block-library/blocks/media-text/style.css 505 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 705 B
build/block-library/blocks/navigation-link/editor.css 703 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 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-submenu/view.min.js 423 B
build/block-library/blocks/navigation/editor-rtl.css 1.99 kB
build/block-library/blocks/navigation/editor.css 2 kB
build/block-library/blocks/navigation/style-rtl.css 2.17 kB
build/block-library/blocks/navigation/style.css 2.16 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 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 260 B
build/block-library/blocks/paragraph/style.css 260 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 493 B
build/block-library/blocks/post-comments-form/style.css 493 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 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 547 B
build/block-library/blocks/post-featured-image/editor.css 545 B
build/block-library/blocks/post-featured-image/style-rtl.css 315 B
build/block-library/blocks/post-featured-image/style.css 315 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/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 282 B
build/block-library/blocks/post-template/style.css 282 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 100 B
build/block-library/blocks/post-title/style.css 100 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 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 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 282 B
build/block-library/blocks/query-pagination/style.css 278 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 439 B
build/block-library/blocks/query/editor.css 439 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 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 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 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 464 B
build/block-library/blocks/shortcode/editor.css 464 B
build/block-library/blocks/site-logo/editor-rtl.css 488 B
build/block-library/blocks/site-logo/editor.css 488 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 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 184 B
build/block-library/blocks/social-link/editor.css 184 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.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 322 B
build/block-library/blocks/spacer/editor.css 322 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 494 B
build/block-library/blocks/table/editor.css 494 B
build/block-library/blocks/table/style-rtl.css 611 B
build/block-library/blocks/table/style.css 609 B
build/block-library/blocks/table/theme-rtl.css 190 B
build/block-library/blocks/table/theme.css 190 B
build/block-library/blocks/tag-cloud/style-rtl.css 239 B
build/block-library/blocks/tag-cloud/style.css 239 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 561 B
build/block-library/blocks/video/editor.css 563 B
build/block-library/blocks/video/style-rtl.css 174 B
build/block-library/blocks/video/style.css 174 B
build/block-library/blocks/video/theme-rtl.css 126 B
build/block-library/blocks/video/theme.css 126 B
build/block-library/common-rtl.css 1.02 kB
build/block-library/common.css 1.02 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11 kB
build/block-library/editor.css 11 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.2 kB
build/block-library/style.css 12.2 kB
build/block-library/theme-rtl.css 719 B
build/block-library/theme.css 722 B
build/block-serialization-default-parser/index.min.js 1.1 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 49.8 kB
build/components/style-rtl.css 11.4 kB
build/components/style.css 11.5 kB
build/compose/index.min.js 12.5 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 kB
build/data-controls/index.min.js 653 B
build/data/index.min.js 8.08 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 507 B
build/dom-ready/index.min.js 324 B
build/dom/index.min.js 4.7 kB
build/edit-navigation/index.min.js 16 kB
build/edit-navigation/style-rtl.css 3.99 kB
build/edit-navigation/style.css 4 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/edit-post/style-rtl.css 6.94 kB
build/edit-post/style.css 6.94 kB
build/edit-site/style-rtl.css 8.36 kB
build/edit-site/style.css 8.34 kB
build/edit-widgets/index.min.js 16.5 kB
build/edit-widgets/style-rtl.css 4.34 kB
build/edit-widgets/style.css 4.34 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 6.76 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.64 kB
build/html-entities/index.min.js 448 B
build/i18n/index.min.js 3.77 kB
build/is-shallow-equal/index.min.js 527 B
build/keyboard-shortcuts/index.min.js 1.78 kB
build/keycodes/index.min.js 1.83 kB
build/list-reusable-blocks/index.min.js 1.74 kB
build/list-reusable-blocks/style-rtl.css 835 B
build/list-reusable-blocks/style.css 835 B
build/media-utils/index.min.js 2.93 kB
build/notices/index.min.js 953 B
build/nux/index.min.js 2.05 kB
build/nux/style-rtl.css 732 B
build/nux/style.css 728 B
build/plugins/index.min.js 1.94 kB
build/preferences-persistence/index.min.js 2.22 kB
build/preferences/index.min.js 1.3 kB
build/primitives/index.min.js 933 B
build/priority-queue/index.min.js 1.58 kB
build/react-i18n/index.min.js 696 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.74 kB
build/reusable-blocks/index.min.js 2.21 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.6 kB
build/server-side-render/index.min.js 1.61 kB
build/shortcode/index.min.js 1.53 kB
build/token-list/index.min.js 644 B
build/url/index.min.js 3.61 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 268 B
build/widgets/index.min.js 7.18 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.19 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@SantosGuillamot
Copy link
Contributor Author

So far, I just replaced the micromodal library and tried to replicate the functionalities described here using Alpinejs. These are the directives I needed:

  • x-data: This is the state to be able to define if the modal is open or not.
  • x-on:click: To change the state to true/false when the buttons are clicked.
  • x-on:keydown.escape: To change the state to false if the ESC button is pressed.
  • x-bind:class: To add is-menu-open and has-modal-open classes when the modal is open.
  • x-bind:aria-hidden: To toggle the aria-hidden attribute between true/false depending on the state.
  • x-trap: This one is part of the @alpine/focus plugin. It allows us to trap the focus within the modal.
  • x-ref & $focus.within($refs.items).first(): To be able to focus the first element of the list. The $focus is also part of the plugin.

In the beginning, I was using the x-show directive, but it causes issues because, in most cases, we only want to apply it when the screen size is <600px. Later I realized that just adding/removing the classes handled the display with css.

Apart from replacing micromodal, I want to review the rest of interactivity and code and check if there is anything else to consider.

cc: @luisherranz

Copy link
Member

@luisherranz luisherranz left a comment

Choose a reason for hiding this comment

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

This is looking great so far!

Your plan is to get rid of the code on the view.js file as well, is that correct?

packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
packages/block-library/src/navigation/index.php Outdated Show resolved Hide resolved
<div class="wp-block-navigation__responsive-close" tabindex="-1" data-micromodal-close>
<div class="wp-block-navigation__responsive-dialog" aria-label="%8$s">
<button %4$s data-micromodal-close class="wp-block-navigation__responsive-container-close">%10$s</button>
'<button x-on:click="open = true; $focus.within($refs.items).first()" aria-haspopup="true" %3$s class="%6$s">%9$s</button>
Copy link
Member

Choose a reason for hiding this comment

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

A few things here with the $focus.within($refs.items):

  • The $focus.within($refs.items).first() part is not triggered when you focus on the hamburguer menu and use Enter to open the menu.

    I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple x-effect that reacts to open === true to make it more declarative?

  • $focus.within($refs.items).first() is focusing the last element to me! I have no idea why.

    ezgif-4-d303afd612.mp4
  • On close, the micromodal version focus the hamburguer menu (shown in video above). We should include that.

  • What do you think about the $focus.within() API. Was it easy to understand? Would it be an easier way to deal with the focus?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • The $focus.within($refs.items).first() part is not triggered when you focus on the hamburguer menu and use Enter to open the menu.

I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple x-effect that reacts to open === true to make it more declarative?

  • $focus.within($refs.items).first() is focusing the last element to me! I have no idea why.

I'm not sure about these two points. It seems to be working for me. Or am I doing something wrong?

https://www.loom.com/share/a144d46e28e6403ca77e2fa7674c87f2

On close, the micromodal version focus the hamburguer menu (shown in video above). We should include that.

Regarding this, I believed it was working 🤷 I have just pushed a commit fixing it using x-ref and $focus again. Not sure if it is the best way though, maybe we could use just something like document.querySelector(".hamburger").focus().

What do you think about the $focus.within() API. Was it easy to understand? Would it be an easier way to deal with the focus?

For me, it was easy to understand but maybe it was just because there is an example really similar to this use case in the docs. If that wasn't the case, I would have probably struggled to understand it.

Regarding if there is a better way to handle the focus, maybe for these cases using the directives is not 100% necessary and we could use just document.querySelector(".hamburger").focus() as mentioned above.

Anyway, the functions of the $focus seem easy to use to me and cover many use cases.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about these two points. It seems to be working for me. Or am I doing something wrong?

Oh, you're right. Alpine uses tappable, and the list of focusable elements is not the same as the one in micromodal, so maybe that's why. Don't worry about it. It's not important.

I wonder what directive/pattern we could use here to take into account both the click and the keyboard. Maybe a simple x-effect that reacts to open === true to make it more declarative?

I've moved the focus to an x-effect directive (which is similar to React's useEffect) in 0a0598f to make it more declarative. It seems to work fine, but could you please check it out?

x-effect="open === true ? $focus.within($refs.items).first() : $focus.focus($refs.hamburger)

I couldn't use if ... else inside the x-effect. I'm not sure if I was doing something wrong.

Not sure if it is the best way though, maybe we could use just something like document.querySelector(".hamburger").focus().

Good point!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved the focus to an x-effect directive (which is similar to React's useEffect) in 0a0598f to make it more declarative. It seems to work fine, but could you please check it out?

Oh, I missed the x-effect comment sorry. It seems clearer this way. However, if I am not mistaken when the page is loaded open = false so it leads to focusing on the hamburger even if the user hasn't interacted with the menu. I assume this shouldn't be the case right? The only thing I can think of to solve it is to change the initial state of open to undefined or an empty string and change the conditional to only focus on true /false:

x-effect="if (open === true) { $focus.within($refs.items).first() } else if (open === false) { $focus.focus($refs.hamburger) }"

This way it seems to work for me.

And using the if ... else is working for me 🤷

Copy link
Member

Choose a reason for hiding this comment

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

However, if I am not mistaken when the page is loaded open = false so it leads to focusing on the hamburger even if the user hasn't interacted with the menu

Oh, true. That's a bummer.

Copy link
Member

@luisherranz luisherranz Sep 27, 2022

Choose a reason for hiding this comment

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

$focus.within($refs.items).first() is focusing the last element to me! I have no idea why.

I think I've discovered why. One of the items has tabindex="0" in the HTML. I don't know where did it come from.

<a
  class="wp-block-navigation-item__content"
  href="http://localhost:8888/eius-magnam-sed-laboriosam-reprehenderit-exercitationem/"
  tabindex="0"
>
  <span class="wp-block-navigation-item__label">Eius magnam</span>
</a>

So it is not a problem for this experiment, don't worry 🙂

@SantosGuillamot
Copy link
Contributor Author

Your plan is to get rid of the code on the view.js file as well, is that correct?

Yes, I am reviewing the view.js files of navigation-submenu and navigation blocks to understand everything better. So far, it seems that using the same directives should be possible.

@SantosGuillamot
Copy link
Contributor Author

I have just added the directives to replicate the submenu functionalities. To open the submenu hovering over the link css is used, so it doesn't apply here. However, you can open the submenu by clicking the arrow button. I just replicated the basic use cases, I am still working on some of them and I have to review the settings. So far, the directives used:

  • x-data: This is the state to be able to define if the submenu is open or not.
  • x-on:click: To toggle between open/close when clicking the arrow.
  • x-on:click.outside: To close the submenu when clicking outside.
  • x-on:keydown.escape: To change the state to false if the ESC button is pressed.
  • x-bind:aria-expanded: To toggle the aria-expanded attribute between true/false depending on the state.

I was trying to close the submenu when the focus is outside it, but I haven't been able to do it yet. I hoped that something like x-on:keyup.outside could work, but it doesn't. Maybe we need a custom event on keyup.

Moreover, we can't use x-show in this case either (I believe), because it adds a display:none if it isn't open, so it interrupts opening the submenu on hover. So this has to be handled with classes, which is already the case.

Apart from that, I was checking the navigation-submenu block view.js file because I'm not sure what it is doing. It isn't defined in the block.json (there is no viewScript field) and it doesn't seem to load in the browser. Furthermore, it seems the navigation block view.js file is doing mostly the same. This is the one loaded in the browser. I will keep researching to check if we have to replicate more functionalities.

@SantosGuillamot
Copy link
Contributor Author

I was trying to close the submenu when the focus is outside it, but I haven't been able to do it yet. I hoped that something like x-on:keyup.outside could work, but it doesn't. Maybe we need a custom event on keyup.

The only way I could think of to make this work, which is far far from perfect, has been:

  • Add a $dispatch in the submenu elements:
    @close-submenu.window="open = false"
  • Call that dispatch when tabbing in the parent navigation block and the previousSibling has the class has-child in the parent navigation block with something like this:
    x-on:keyup.tab="$event.target.parentElement.previousSibling?.classList.contains(\'has-child\') && $dispatch(\'close-submenu\')"

It works in my case, but it doesn't seem reliable. Any ideas how this could be handled?

@luisherranz
Copy link
Member

Moreover, we can't use x-show in this case either (I believe), because it adds a display:none if it isn't open, so it interrupts opening the submenu on hover. So this has to be handled with classes, which is already the case.

Why not use on:mouseover to open it instead of CSS?

@SantosGuillamot
Copy link
Contributor Author

Why not use on:mouseover to open it instead of CSS?

I didn't think about that option, it could work as well. However, there is more CSS added to the classes (these lines for example), so toggling the class would be needed anyway. Having said that, the purpose was to find which directives were needed. From there, the developers could use whatever they prefer I guess.

@SantosGuillamot
Copy link
Contributor Author

Now that the view.js and view-modal.js files have been removed and replicated using directives, and we have a better idea of which ones would be needed, should we consider this part of the experiment done? Do you think there is anything else left to explore in this regard?

@luisherranz
Copy link
Member

luisherranz commented Sep 28, 2022

Yeah, I think we can consider this finished, at least for now. Let's focus on replicating the Alpine directives with our own 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants