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 #44509

Closed

Conversation

luisherranz
Copy link
Member

@luisherranz luisherranz commented Sep 27, 2022

What?

Coauthored with @SantosGuillamot and @DAreRodz.

This is a continuation of the #44289 experiment to switch from micromodal + imperative code to declarative directives.

Why?

We are experimenting with different hydration mechanisms, and this is one of them. If you're interested in block hydration, please join the Block Hydration Experiments repository 🙂

How?

For now, we have copied the code of the Directives hydration and are trying to copy the functionality of the Alpine directives that @SantosGuillamot used in #44289.

The idea is that Gutenberg could provide all the JS code that's added here. The navigation block would only have to add the directives to the markup in PHP.

This is still very preliminary. We'll keep adding functionality in the next few days.

luisherranz and others added 3 commits September 27, 2022 17:07
Co-authored-by: Mario Santos <SantosGuillamot@users.noreply.github.com>
Co-authored-by: David Arenas <david.arenas@automattic.com>
@luisherranz luisherranz changed the title Experiment/navigation block with wordpress directives Experiment: Replicate Navigation block using vDOM-based directives Sep 27, 2022
@luisherranz
Copy link
Member Author

luisherranz commented Sep 27, 2022

I've tried renaming view.js to another thing because the diffing of that file here in GH makes no sense, but I can't make it work. If someone knows how to do it, please let me know. I gave up 🙂

EDIT: This is what I tried: 13da68a

@DAreRodz
Copy link
Contributor

I've tried renaming view.js to another thing because the diffing of that file here in GH makes no sense, but I can't make it work. If someone knows how to do it, please let me know. I gave up 🙂

EDIT: This is what I tried: 13da68a

When you change the name of that file, it stops being considered an entry point, even when you run Webpack again. It may be related to how entry points are computed. 👀 🤔

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

github-actions bot commented Sep 29, 2022

Size Change: +5.45 kB (0%)

Total Size: 1.27 MB

Filename Size Change
build/block-library/blocks/code/style-rtl.css 121 B +18 B (+17%) ⚠️
build/block-library/blocks/code/style.css 121 B +18 B (+17%) ⚠️
build/block-library/blocks/navigation-submenu/view.min.js 0 B -423 B (removed) 🏆
build/block-library/blocks/navigation/style-rtl.css 2.17 kB +2 B (0%)
build/block-library/blocks/navigation/style.css 2.16 kB +5 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 8.29 kB +7.85 kB (+1772%) 🆘
build/block-library/blocks/site-title/editor-rtl.css 116 B +32 B (+38%) 🚨
build/block-library/blocks/site-title/editor.css 116 B +32 B (+38%) 🚨
build/block-library/blocks/video/editor-rtl.css 691 B +13 B (+2%)
build/block-library/blocks/video/editor.css 694 B +13 B (+2%)
build/block-library/editor-rtl.css 11.2 kB +14 B (0%)
build/block-library/editor.css 11.2 kB +14 B (0%)
build/block-library/index.min.js 191 kB +64 B (0%)
build/block-library/style-rtl.css 12.3 kB +20 B (0%)
build/block-library/style.css 12.3 kB +23 B (0%)
build/components/index.min.js 199 kB -5 B (0%)
build/compose/index.min.js 12.5 kB +14 B (0%)
build/edit-post/style-rtl.css 6.97 kB +31 B (0%)
build/edit-post/style.css 6.97 kB +31 B (0%)
build/edit-site/index.min.js 57.9 kB +74 B (0%)
build/list-reusable-blocks/index.min.js 2.13 kB +390 B (+22%) 🚨
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 982 B
build/annotations/index.min.js 2.76 kB
build/api-fetch/index.min.js 2.26 kB
build/autop/index.min.js 2.14 kB
build/blob/index.min.js 475 B
build/block-directory/index.min.js 7.09 kB
build/block-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-editor/index.min.js 167 kB
build/block-editor/style-rtl.css 15.4 kB
build/block-editor/style.css 15.4 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 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/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 384 B
build/block-library/blocks/group/editor.css 384 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 884 B
build/block-library/blocks/image/editor.css 882 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/editor-rtl.css 2.01 kB
build/block-library/blocks/navigation/editor.css 2.02 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 317 B
build/block-library/blocks/paragraph/editor.css 317 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 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 586 B
build/block-library/blocks/post-featured-image/editor.css 584 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 96 B
build/block-library/blocks/post-terms/style.css 96 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/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 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/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/classic-rtl.css 162 B
build/block-library/classic.css 162 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/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/theme-rtl.css 719 B
build/block-library/theme.css 722 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 49.8 kB
build/components/style-rtl.css 11.2 kB
build/components/style.css 11.2 kB
build/core-data/index.min.js 15.5 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.38 kB
build/customize-widgets/style.css 1.38 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/index.min.js 31.1 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/editor/index.min.js 41.6 kB
build/editor/style-rtl.css 3.62 kB
build/editor/style.css 3.61 kB
build/element/index.min.js 4.68 kB
build/escape-html/index.min.js 537 B
build/experiments/index.min.js 868 B
build/format-library/index.min.js 6.77 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/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 963 B
build/nux/index.min.js 2.06 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/style-engine/index.min.js 1.46 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.08 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

@luisherranz
Copy link
Member Author

I've updated the directives to match the latest version on BHE.

I've also added some preliminary support for prefix/suffix in the directive name using :. Now you can use wp-on:click, although it doesn't support multiple ones in the same element yet. We need to think if we should call the directive callback once with an array of the directive values, or once for each directive value.

I added some initial support for modifiers, but I removed it afterward because P/React don't have modifiers, and I'd prefer to first try how it feels to use arrays/objects of options to keep the implementation as simple as possible.

@luisherranz
Copy link
Member Author

luisherranz commented Sep 29, 2022

I added preliminary support for wp-class:some-class="..." to toggle classes on and off. I prefer the Svelte-based syntax because it lets you add multiple directives, each own with its own logic but, as with everything, it's up for discussion 🙂

The camelcase renaming of the suffix it's not working here, so we need to think about that as well.

Screen.Capture.on.2022-09-29.at.17-53-16.mp4

EDIT: I've removed the camelcasing in the suffix for now.

@luisherranz
Copy link
Member Author

By the way, for anyone wondering why we are not using arrow functions instead of regular functions, WordPress breaks when it finds the > of the arrow in the HTML because it thinks that the <button opening tag should be closed:

<button wp-class:some-class="({ context }) => context.open">

It should be easy to fix. Although, again, I'm not sure if we should allow this type of JS inlining or not.

@luisherranz
Copy link
Member Author

luisherranz commented Sep 30, 2022

Some of the next steps here:

  • Figure out an API to deal with multiple directive declarations for things like wp-on:..., wp-class:..., wp-bind:...
  • Figure out how to pass a reference to the element for things like focus (wp-focus-trap).
  • Switch from useState to signals.
  • Create the wp-context component
  • Add wp-bind:attr directive.
  • Get rid of eval by moving expressions to a namespaced store.
  • Add directive priorities (i.e, wp-context should run before other directives).

@luisherranz
Copy link
Member Author

luisherranz commented Sep 30, 2022

I'm going to try a new API:

  1. Join wp, props, element, ref... together in the same object, but keep props in their own props property (don't spread them).
  2. Rename wp to directives, to see how it feels.
  3. Remove the camelcasing, to see how it feels.
  4. Convert all the directives to objects where the part after the colon (:) is the key. If there's no colon, the key is default.

Something like this:

<div
  wp-class="...1..."
  wp-class:some-class="...2..."
  wp-class:other-class="...3..."
>
  ...
</div>

Will end up in with this object shape:

{
  "class": {
    "default": "...1...",
    "some-class": "...2...",
    "other-class": "...3..."
  }
}

This new API makes wp-prefix:suffix the default format and opens the door for adding multiple directives for any directive, even for things like wp-effect or wp-init:

<div
  wp-effect:log-some-value="({ context }) => console.log(context.someValue)"
  wp-effect:fetch-something="() => fetch(...)"
>
  ...
</div>

Directives that should only contain one expression can ignore everything but the default key.

It's not really needed, we just added previously to test things
@luisherranz
Copy link
Member Author

I've made a video summary of the current status for anyone interested:

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

@luisherranz
Copy link
Member Author

I've created a minimalistic implementation of a deep preact signal: Gist, Stackblitz. I'll test it out on Monday 🙂

@SantosGuillamot
Copy link
Contributor

SantosGuillamot commented Oct 3, 2022

Thanks for the video! Love where the experiment is going ☺️

I've tried renaming view.js to another thing because the diffing of that file here in GH makes no sense, but I can't make it work. If someone knows how to do it, please let me know. I gave up 🙂

EDIT: This is what I tried: 13da68a

Regarding this: If I am not mistaken, the viewScript files have to start with view*, so that could be the issue. At least is what I understood in this code. If that's the case, I guess we could improve the regex to cover other names.

Btw, we don't need to enqueue the view-modal anymore, right?

Apart from that, I was thinking of making some changes to start using the render property as I feel the code could be easier to read. Could that be a problem somehow? Maybe this is a bit complex and not worthy.

@luisherranz
Copy link
Member Author

Apart from that, I was thinking of making some changes to start using the render property as I feel the code could be easier to read. Could that be a problem somehow? Maybe this is a bit complex and not worthy.

That would be very interesting. Maybe in a different PR? 🙂

Btw, we don't need to enqueue the view-modal anymore, right?

True. Fixed, thanks.

Regarding this: If I am not mistaken, the viewScript files have to start with view*, so that could be the issue. At least is what I understood in this code. If that's the case, I guess we could improve the regex to cover other names.

I think I tried with a different name starting with view, but I'll try again. Thanks 🙂


I've switched from useState (immutable object) to deep signals (mutable object).

I had to introduce a tick function similar to Vue/Svelte because the new useSignalEffect function doesn't seem to wait until the changes have been applied to the DOM. I opened an issue in the Preact signals repository to see if this can be fixed.

Other than that, it's working fine 🙂

@luisherranz
Copy link
Member Author

  • I've added preliminary support for client components (<wp-something>) components. They can't output markup yet (more about that here).
  • I've added the wp-bind:attr directive.

@luisherranz
Copy link
Member Author

For some reason, it's enqueuing wp-element (and all its dependencies). I won't debug it as it's not important at this moment. Maybe it's just because of the JSX transform.

The current size is 9.1Kb. It's not the final size, but it shouldn't grow that much. This already includes: preact, preact/hooks and @preact/signals. Although it doesn't include preact/compat, which would add another 5Kbs more or less. But maybe we can avoid it.

I've refactored it a bit into its own folder. I hope that way can be understood better.

I'll try to move the expressions to the view.js file to remove the usage of eval and see how it feels.

@luisherranz
Copy link
Member Author

I've moved the logic to the view.js file to avoid using eval. This is all the JS that the navigation block would have to write:

wpx({
  core: {
    navigation: {
      openMenu: ({ context: { navigation } }) => {
        navigation.open = true;
        navigation.previousElementWithFocus = window.document.activeElement;
      },
      closeMenu: ({ context: { navigation } }) => {
        navigation.open = false;
      },
      isMenuOpen: ({ context: { navigation } }) => navigation.open,
      isMenuClosed: ({ context: { navigation } }) => !navigation.open,
      addFirstElementToContext: ({ context: { navigation }, ref }) => {
        navigation.firstMenuElement = ref;
      },
      focusFirstElement: async ({ context: { navigation }, tick }) => {
        if (navigation.open) {
          await tick(); // We need to wait until the DOM is updated.
          navigation.firstMenuElement.focus();
        }
      },
      focusLastFocusedElement: ({ context: { navigation } }) => {
        if (!navigation.open && navigation.previousElementWithFocus)
          navigation.previousElementWithFocus.focus();
      },
    },
  },
});

I'm going to stop working on this for now, but feel free to continue adding features, trying different developer experiences or sharing your feedback about all this.

@SantosGuillamot
Copy link
Contributor

Apart from that, I was thinking of making some changes to start using the render property as I feel the code could be easier to read.

Regarding this, I decided to publish the pull request where I was testing it, in case it is helpful somehow in the future. As I say there, I just replicated the sprintf of the responsive navigation menu, because it is the one we are modifying, and didn't check the whole code.

@SantosGuillamot SantosGuillamot changed the title Experiment: Replicate Navigation block using vDOM-based directives Experiment: Replicate Navigation block using directives Jan 11, 2023
@gziolo gziolo added the [Feature] Interactivity API API to add frontend interactivity to blocks. label Apr 2, 2023
},
focusFirstElement: async ( { context: { navigation }, tick } ) => {
if ( navigation.open ) {
await tick(); // We need to wait until the DOM is updated.
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 won't be needed once this is merged: preactjs/signals#290

@luisherranz
Copy link
Member Author

Closing now that the Navigation block is already using directives in Gutenberg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [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.

4 participants