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

Experimental: Navigation block with the Interactivity API #50041

Merged
merged 85 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
fcd792d
Add interactivity runtime
luisherranz Apr 21, 2023
9b0a62e
Add it to the image block
luisherranz Apr 21, 2023
d2c0803
Add a separate webpack config
luisherranz Apr 21, 2023
ed1df51
Make sure the runtime is imported only once
luisherranz Apr 21, 2023
ed043f5
Use sideEffects instead of init
luisherranz Apr 21, 2023
c9f389f
Move script registration to a general file
luisherranz Apr 21, 2023
261dacf
Add `defer` to the interactivity scripts
luisherranz Apr 21, 2023
27cfc1f
Revert changes of the image block
luisherranz Apr 21, 2023
7cf6ba9
Fix init import name
luisherranz Apr 21, 2023
55d37ef
Add experimental setting to use Interactivity API
SantosGuillamot Apr 24, 2023
7cfbffa
Add basic `interactivity.js` file
SantosGuillamot Apr 24, 2023
2a970e3
Enqueue old script/interactivity API conditionally
SantosGuillamot Apr 24, 2023
84146ae
Add `tick()` function until Preact bug is solved
SantosGuillamot Apr 24, 2023
c2c96da
Add code to handle the overlayMenu
SantosGuillamot Apr 24, 2023
71fbd35
Add Interactivity API to submenu block
SantosGuillamot Apr 24, 2023
85bf58f
Add Interactivity API to page list block
SantosGuillamot Apr 24, 2023
027e2a1
Change code to be more declarative and simple
SantosGuillamot Apr 26, 2023
0e4a604
Use `__DIR__` instead of `__FILE__`
SantosGuillamot Apr 27, 2023
67ffd65
Change loading script conditional
SantosGuillamot Apr 27, 2023
122a154
Fix issues momentarily
SantosGuillamot Apr 27, 2023
a6b1e62
Fix some issues with focus
SantosGuillamot Apr 27, 2023
e63c002
Add tabindex to modal
SantosGuillamot Apr 27, 2023
8f388df
Revert to current navigation block
SantosGuillamot Apr 27, 2023
938d57d
Add directives through a filter
SantosGuillamot Apr 27, 2023
1d0472d
Dont add latest modifications to navigation block
SantosGuillamot Apr 27, 2023
d5250fa
Ensure focus doesn't get inside menu after closing
SantosGuillamot Apr 27, 2023
3ae8097
Add conditionals and change function names
SantosGuillamot Apr 28, 2023
624bdb0
Use `gutenberg_is_experiment_enabled` function
SantosGuillamot Apr 28, 2023
ebba7b4
Add interactivity runtime
luisherranz Apr 21, 2023
af59781
Add it to the image block
luisherranz Apr 21, 2023
cca3d60
Add a separate webpack config
luisherranz Apr 21, 2023
160a029
Make sure the runtime is imported only once
luisherranz Apr 21, 2023
7f16f27
Use sideEffects instead of init
luisherranz Apr 21, 2023
f4b2ee8
Move script registration to a general file
luisherranz Apr 21, 2023
378b041
Add `defer` to the interactivity scripts
luisherranz Apr 21, 2023
409d161
Revert changes of the image block
luisherranz Apr 21, 2023
29e11ab
Fix init import name
luisherranz Apr 21, 2023
f4b6c0a
Move and refactor the interactive scritps registration
gziolo Apr 28, 2023
3d94473
Fix code style violations
gziolo Apr 28, 2023
6ae760f
Use `wp-interactivity-` prefix for script handles
gziolo Apr 28, 2023
9d6869e
Improve the matcher for side effects in `package.json`
gziolo Apr 28, 2023
3393bc2
Merge branch 'add-interactivity-runtime' into navigation-block-with-i…
SantosGuillamot May 3, 2023
32013ae
Enqueue interactivity scripts through hook
SantosGuillamot May 3, 2023
f829206
Revert `client-assets.php` file
SantosGuillamot May 3, 2023
3258326
Adapt to latest changes in base branch
SantosGuillamot May 3, 2023
c6d02d8
Add custom useSignalEffect
DAreRodz May 4, 2023
bb36577
Merge branch 'add-interactivity-runtime' into navigation-block-with-i…
SantosGuillamot May 4, 2023
9c95302
Move role attribute to selectors
SantosGuillamot May 4, 2023
af55917
Call `init` after `store` has been initialized
DAreRodz May 4, 2023
b58e6af
Merge branch 'add-interactivity-runtime' into navigation-block-with-i…
SantosGuillamot May 5, 2023
66b765c
Change focusable elements
SantosGuillamot May 5, 2023
7f1db8c
Add namespaces to context
SantosGuillamot May 5, 2023
79fd7b7
Move PHP file to interactivity-api folder
SantosGuillamot May 5, 2023
b553b04
Add comments with the markup to the PHP filter
SantosGuillamot May 5, 2023
182ed89
Remove micromodal attributes
SantosGuillamot May 5, 2023
5751344
Add interactivity runtime
luisherranz Apr 21, 2023
e8201c2
Add it to the image block
luisherranz Apr 21, 2023
df844f0
Add a separate webpack config
luisherranz Apr 21, 2023
d883391
Make sure the runtime is imported only once
luisherranz Apr 21, 2023
b1ea5e3
Use sideEffects instead of init
luisherranz Apr 21, 2023
20d6213
Move script registration to a general file
luisherranz Apr 21, 2023
6fb8aa7
Add `defer` to the interactivity scripts
luisherranz Apr 21, 2023
6c96509
Revert changes of the image block
luisherranz Apr 21, 2023
e843b80
Fix init import name
luisherranz Apr 21, 2023
cdf74b9
Move and refactor the interactive scritps registration
gziolo Apr 28, 2023
de0e874
Fix code style violations
gziolo Apr 28, 2023
fa7c00d
Use `wp-interactivity-` prefix for script handles
gziolo Apr 28, 2023
0d88c77
Improve the matcher for side effects in `package.json`
gziolo Apr 28, 2023
142050c
Add custom useSignalEffect
DAreRodz May 4, 2023
e65b91e
Call `init` after `store` has been initialized
DAreRodz May 4, 2023
9a31bb4
Update lib/experimental/interactivity-api/script-loader.php
gziolo May 5, 2023
0cdab08
Plugin: Ensure that translations are set correctly when overriding sc…
gziolo May 5, 2023
5dcf88e
Remove unnecessary comment in webpack config
SantosGuillamot May 5, 2023
5171e47
Merge branch 'add-interactivity-runtime' into navigation-block-with-i…
SantosGuillamot May 5, 2023
5af4b51
Clean up code to fix PHP coding standards issues
SantosGuillamot May 5, 2023
d4a16f3
Remove extra space
SantosGuillamot May 5, 2023
6f34728
Merge branch 'trunk' into navigation-block-with-interactivity-api
SantosGuillamot May 5, 2023
066d946
Add tests to the navigation block interactivity
SantosGuillamot May 8, 2023
91796b9
Modify `saveSiteEditorEntities` function to wait
SantosGuillamot May 8, 2023
c358346
Fix page-list tests
SantosGuillamot May 9, 2023
68b3dec
Remove e2e tests that are already included in trunk
gziolo May 9, 2023
c6ee68a
Fix the navigation menu when the overlay is not present
gziolo May 10, 2023
15d3546
Ensure that all scripts using Intereactivity API have defer attribute
gziolo May 10, 2023
4367b4d
Remove unused param in the callback used by hook
gziolo May 10, 2023
1626f90
Merge remote-tracking branch 'origin/trunk' into navigation-block-wit…
gziolo May 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/experimental/editor-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ function gutenberg_enable_experiments() {
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-details-blocks', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableDetailsBlocks = true', 'before' );
}
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-interactivity-api-navigation-block', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableNavigationBlockInteractivity = true', 'before' );
}
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-theme-previews', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableThemePreviews = true', 'before' );
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
<?php
/**
* Extend WordPress core navigation block to use the Interactivity API.
* Interactivity API directives are added using the Tag Processor while it is experimental.
*
* @package gutenberg
*/

/**
* Add Interactivity API directives to the navigation block markup using the Tag Processor
* The final HTML of the navigation block will look similar to this:
*
* <nav
* data-wp-island
* data-wp-context='{ "core": { "navigation": { "isMenuOpen": false, "overlay": true, "roleAttribute": "" } } }'
* >
* <button
* class="wp-block-navigation__responsive-container-open"
* data-wp-on.click="actions.core.navigation.openMenu"
* data-wp-on.keydown="actions.core.navigation.handleMenuKeydown"
* >
* <div
* class="wp-block-navigation__responsive-container"
* data-wp-class.has-modal-open="context.core.navigation.isMenuOpen"
* data-wp-class.is-menu-open="context.core.navigation.isMenuOpen"
* data-wp-bind.aria-hidden="!context.core.navigation.isMenuOpen"
* data-wp-effect="effects.core.navigation.initModal"
* data-wp-on.keydow="actions.core.navigation.handleMenuKeydown"
* data-wp-on.focusout="actions.core.navigation.handleMenuFocusout"
* tabindex="-1"
* >
* <div class="wp-block-navigation__responsive-close">
* <div
* class="wp-block-navigation__responsive-dialog"
* data-wp-bind.aria-modal="context.core.navigation.isMenuOpen"
* data-wp-bind.role="selectors.core.navigation.roleAttribute"
* data-wp-effect="effects.core.navigation.focusFirstElement"
* >
* <button
* class="wp-block-navigation__responsive-container-close"
* data-wp-on.click="actions.core.navigation.closeMenu"
* >
* <svg>
* <button>
* MENU ITEMS
* </div>
* </div>
* </div>
* </nav>
*
* @param string $block_content Markup of the navigation block.
*
* @return string Navigation block markup with the proper directives
*/
function gutenberg_block_core_navigation_add_directives_to_markup( $block_content ) {
$w = new WP_HTML_Tag_Processor( $block_content );
// Add directives to the `<nav>` element.
if ( $w->next_tag( 'nav' ) ) {
$w->set_attribute( 'data-wp-island', '' );
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": false, "overlay": true, "roleAttribute": "" } } }' );
};

// Add directives to the open menu button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation__responsive-container-open',
)
) ) {
$w->set_attribute( 'data-wp-on.click', 'actions.core.navigation.openMenu' );
$w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->remove_attribute( 'data-micromodal-trigger' );
} else {
// If the open modal button not found, we handle submenus immediately.
$w = new WP_HTML_Tag_Processor( $w->get_updated_html() );

// Add directives to the menu container.
if ( $w->next_tag(
array(
'tag_name' => 'UL',
'class_name' => 'wp-block-navigation__container',
)
) ) {
$w->set_attribute( 'data-wp-class.is-menu-open', 'context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-bind.aria-hidden', '!context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initModal' );
Copy link
Member

Choose a reason for hiding this comment

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

@SantosGuillamot, would it make sense to rename the effect to reflect the fact it works with the menu when there is no modal, too?

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 renamed it to initMenu in this commit.

$w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' );
$w->set_attribute( 'tabindex', '-1' );
};

gutenberg_block_core_navigation_add_directives_to_submenu( $w );

return $w->get_updated_html();
}

// Add directives to the menu container.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-container',
)
) ) {
$w->set_attribute( 'data-wp-class.has-modal-open', 'context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-class.is-menu-open', 'context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-bind.aria-hidden', '!context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initModal' );
$w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' );
$w->set_attribute( 'tabindex', '-1' );
};

// Remove micromodal attribute.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-close',
)
) ) {
$w->remove_attribute( 'data-micromodal-close' );
};

// Add directives to the dialog container.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-dialog',
)
) ) {
$w->set_attribute( 'data-wp-bind.aria-modal', 'context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-bind.role', 'selectors.core.navigation.roleAttribute' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.focusFirstElement' );
};

// Add directives to the close button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation__responsive-container-close',
)
) ) {
$w->set_attribute( 'data-wp-on.click', 'actions.core.navigation.closeMenu' );
$w->remove_attribute( 'data-micromodal-close' );
};

// Submenus.
gutenberg_block_core_navigation_add_directives_to_submenu( $w );

return $w->get_updated_html();
};

/**
* Add Interactivity API directives to the navigation-submenu and page-list blocks markup using the Tag Processor
* The final HTML of the navigation-submenu and the page-list blocks will look similar to this:
*
* <li
* class="has-child"
* data-wp-context='{ "core": { "navigation": { "isMenuOpen": false, "overlay": false } } }'
* >
* <button
* class="wp-block-navigation-submenu__toggle"
* data-wp-on.click="actions.core.navigation.openMenu"
* data-wp-bind.aria-expanded="context.core.navigation.isMenuOpen"
* data-wp-on.keydown="actions.core.navigation.handleMenuKeydown"
* data-wp-on.focusout="actions.core.navigation.handleMenuFocusout"
* >
* </button>
* <span>Title</span>
* <ul
* class="wp-block-navigation__submenu-container"
* data-wp-effect="effects.core.navigation.initModal"
* data-wp-on.focusout="actions.core.navigation.handleMenuFocusout"
* data-wp-on.keydown="actions.core.navigation.handleMenuKeydown"
* >
* SUBMENU ITEMS
* </ul>
* </li>
*
* @param string $w Markup of the navigation block.
*
* @return void
*/
function gutenberg_block_core_navigation_add_directives_to_submenu( $w ) {
while ( $w->next_tag(
array(
'tag_name' => 'LI',
'class_name' => 'has-child',
)
) ) {
// Add directives to the parent `<li>`.
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": false, "overlay": false } } }' );

// Add directives to the toggle submenu button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation-submenu__toggle',
)
) ) {
$w->set_attribute( 'data-wp-on.click', 'actions.core.navigation.openMenu' );
$w->set_attribute( 'data-wp-bind.aria-expanded', 'context.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' );
};

// Add directives to the `<ul>` containing the subitems.
if ( $w->next_tag(
array(
'tag_name' => 'UL',
'class_name' => 'wp-block-navigation__submenu-container',
)
) ) {
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initModal' );
$w->set_attribute( 'data-wp-on.focusout', 'actions.core.navigation.handleMenuFocusout' );
$w->set_attribute( 'data-wp-on.keydown', 'actions.core.navigation.handleMenuKeydown' );
};
// Iterate through subitems if exist.
gutenberg_block_core_navigation_add_directives_to_submenu( $w );
}
};

add_filter( 'render_block_core/navigation', 'gutenberg_block_core_navigation_add_directives_to_markup', 10, 1 );

// Enqueue the `interactivity.js` file with the store.
add_filter(
'block_type_metadata',
function ( $metadata ) {
if ( 'core/navigation' === $metadata['name'] ) {
wp_register_script(
'wp-block-navigation-view',
gutenberg_url( 'build/block-library/interactive-blocks/navigation.min.js' ),
array( 'wp-interactivity-runtime' )
);
$metadata['viewScript'] = array( 'wp-block-navigation-view' );
}
return $metadata;
},
10,
1
);
7 changes: 3 additions & 4 deletions lib/experimental/interactivity-api/script-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@ function gutenberg_register_interactivity_scripts( $scripts ) {
* Adds the "defer" attribute to all the interactivity script tags.
*
* @param string $tag The generated script tag.
* @param string $handle The script's registered handle.
*
* @return string The modified script tag.
*/
function gutenberg_interactivity_scripts_add_defer_attribute( $tag, $handle ) {
if ( str_starts_with( $handle, 'wp-interactivity-' ) ) {
function gutenberg_interactivity_scripts_add_defer_attribute( $tag ) {
if ( str_contains( $tag, '/block-library/interactive-blocks/' ) ) {
$p = new WP_HTML_Tag_Processor( $tag );
$p->next_tag( array( 'tag' => 'script' ) );
$p->set_attribute( 'defer', true );
return $p->get_updated_html();
}
return $tag;
}
add_filter( 'script_loader_tag', 'gutenberg_interactivity_scripts_add_defer_attribute', 10, 2 );
add_filter( 'script_loader_tag', 'gutenberg_interactivity_scripts_add_defer_attribute', 10, 1 );
12 changes: 12 additions & 0 deletions lib/experiments-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ function gutenberg_initialize_experiments_settings() {
)
);

add_settings_field(
'gutenberg-interactivity-api-navigation-block',
__( 'Navigation block', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
'label' => __( 'Test the Navigation block using the Interactivity API', 'gutenberg' ),
'id' => 'gutenberg-interactivity-api-navigation-block',
)
);

register_setting(
'gutenberg-experiments',
'gutenberg-experiments'
Expand Down
3 changes: 3 additions & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/experimental/kses.php';
require __DIR__ . '/experimental/l10n.php';
require __DIR__ . '/experimental/navigation-fallback.php';
if ( gutenberg_is_experiment_enabled( 'gutenberg-interactivity-api-navigation-block' ) ) {
require __DIR__ . '/experimental/interactivity-api/navigation-block-interactivity.php';
}

// Fonts API.
if ( ! class_exists( 'WP_Fonts' ) ) {
Expand Down
Loading