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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
22c3f1a
First WordPress directives
luisherranz Sep 27, 2022
4af14d6
Fix return of components
luisherranz Sep 27, 2022
9195ddf
Delete not used view-modal file
luisherranz Sep 27, 2022
a28ccfd
Merge remote-tracking branch 'origin/trunk' into experiment/navigatio…
luisherranz Sep 29, 2022
1ee977c
Refactor directives logic to match last version in BHE
luisherranz Sep 29, 2022
5a5b451
Preliminary support for prefix/suffix in directives
luisherranz Sep 29, 2022
cd01ffa
Update package.lock
luisherranz Sep 29, 2022
eabeed9
Remove support for modifiers
luisherranz Sep 29, 2022
ced9cbf
Move rename and value to the vdom file
luisherranz Sep 29, 2022
2d8dc0c
Add wp-class directive
luisherranz Sep 29, 2022
546b5b8
Remove camelcase in directive suffix
luisherranz Sep 29, 2022
7807a98
Add first directives to open and close the menu
luisherranz Sep 30, 2022
4534457
Pass ref, use it to set focus of first element
luisherranz Sep 30, 2022
e80249f
Try new API
luisherranz Sep 30, 2022
7d868f9
Remove wp-log
luisherranz Sep 30, 2022
d85c56b
Fix variable typo
luisherranz Sep 30, 2022
9309a91
Rename directive props to directive args
luisherranz Sep 30, 2022
265763e
Switch to signals
luisherranz Oct 3, 2022
1b244bb
Don't enqueue view-modal
luisherranz Oct 3, 2022
fa5c532
Add preliminary support for components
luisherranz Oct 3, 2022
221ea02
Rename directives file
luisherranz Oct 3, 2022
21d937e
Move context to wpx file
luisherranz Oct 3, 2022
d0db1e8
Add wp-bind:attr directive
luisherranz Oct 3, 2022
42e4612
Deep signal: Add all the supported arrays
luisherranz Oct 3, 2022
62e46a4
Move stuff to utils
luisherranz Oct 3, 2022
d54ab56
Refactor to wpx folder
luisherranz Oct 3, 2022
4c82fbd
Move function to JS file to avoid eval
luisherranz Oct 3, 2022
b2e0e6a
Namespace navigation context
luisherranz Oct 3, 2022
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
20 changes: 20 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/block-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
],
"dependencies": {
"@babel/runtime": "^7.16.0",
"@preact/signals": "^1.1.1",
"@wordpress/a11y": "file:../a11y",
"@wordpress/api-fetch": "file:../api-fetch",
"@wordpress/autop": "file:../autop",
Expand Down Expand Up @@ -64,6 +65,7 @@
"lodash": "^4.17.21",
"memize": "^1.1.0",
"micromodal": "^0.4.10",
"preact": "^10.11.0",
"remove-accents": "^0.4.2"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/navigation/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
}
}
},
"viewScript": [ "file:./view.min.js", "file:./view-modal.min.js" ],
"viewScript": [ "file:./view.min.js" ],
"editorStyle": "wp-block-navigation-editor",
"style": "wp-block-navigation"
}
46 changes: 35 additions & 11 deletions packages/block-library/src/navigation/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {

$should_load_modal_view_script = isset( $attributes['overlayMenu'] ) && 'never' !== $attributes['overlayMenu'];
if ( $should_load_modal_view_script ) {
wp_enqueue_script( 'wp-block-navigation-view-modal' );
// wp_enqueue_script( 'wp-block-navigation-view-modal' );
}

$inner_blocks = $block->inner_blocks;
Expand Down Expand Up @@ -556,6 +556,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {

$inner_blocks_html = '';
$is_list_open = false;
$is_first_item = false;
foreach ( $inner_blocks as $inner_block ) {
if ( ( 'core/navigation-link' === $inner_block->name || 'core/home-link' === $inner_block->name || 'core/site-title' === $inner_block->name || 'core/site-logo' === $inner_block->name || 'core/navigation-submenu' === $inner_block->name ) && ! $is_list_open ) {
$is_list_open = true;
Expand All @@ -566,6 +567,13 @@ function render_block_core_navigation( $attributes, $content, $block ) {
$inner_blocks_html .= '</ul>';
}
$inner_block_content = $inner_block->render();
if (!$is_first_item) {
$w = new WP_HTML_Tag_Processor($inner_block_content);
$w->next_tag('a');
$w->set_attribute('wp-effect', 'core.navigation.addFirstElementToContext');
$inner_block_content = (string) $w;
$is_first_item = true;
}
if ( 'core/site-title' === $inner_block->name || ( 'core/site-logo' === $inner_block->name && $inner_block_content ) ) {
$inner_blocks_html .= '<li class="wp-block-navigation-item">' . $inner_block_content . '</li>';
} else {
Expand Down Expand Up @@ -632,17 +640,33 @@ function render_block_core_navigation( $attributes, $content, $block ) {
$toggle_aria_label_close = $should_display_icon_label ? 'aria-label="' . __( 'Close menu' ) . '"' : ''; // Close button label.

$responsive_container_markup = sprintf(
'<button aria-haspopup="true" %3$s class="%6$s" data-micromodal-trigger="%1$s">%9$s</button>
<div class="%5$s" style="%7$s" id="%1$s">
<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>
<div class="wp-block-navigation__responsive-container-content" id="%1$s-content">
%2$s
</div>
'<button
wp-on:click="core.navigation.openMenu"
wp-effect:on-open="core.navigation.focusFirstElement"
wp-effect:on-close="core.navigation.focusLastFocusedElement"
aria-haspopup="true"
%3$s
class="%6$s"
>
%9$s
</button>
<div
class="%5$s"
wp-class:is-menu-open="core.navigation.isMenuOpen"
wp-class:has-modal-open="core.navigation.isMenuOpen"
wp-bind:aria-hidden="core.navigation.isMenuClosed"
style="%7$s"
id="%1$s"
>
<div class="wp-block-navigation__responsive-close" tabindex="-1">
<div class="wp-block-navigation__responsive-dialog" aria-label="%8$s" aria-modal="true" role="dialog">
<button wp-on:click="core.navigation.closeMenu" %4$s class="wp-block-navigation__responsive-container-close">%10$s</button>
<div class="wp-block-navigation__responsive-container-content" id="%1$s-content">
%2$s
</div>
</div>
</div>',
</div>
</div>',
esc_attr( $modal_unique_id ),
$inner_blocks_html,
$toggle_aria_label_open,
Expand All @@ -656,7 +680,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {
);

return sprintf(
'<nav %1$s>%2$s</nav>',
'<wp-context data=\'{"navigation": {"open": false}}\'><nav %1$s >%2$s</nav></wp-context>',
$wrapper_attributes,
$responsive_container_markup
);
Expand Down
68 changes: 0 additions & 68 deletions packages/block-library/src/navigation/view-modal.js

This file was deleted.

102 changes: 31 additions & 71 deletions packages/block-library/src/navigation/view.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,34 @@
// Open on click functionality.
function closeSubmenus( element ) {
element
.querySelectorAll( '[aria-expanded="true"]' )
.forEach( function ( toggle ) {
toggle.setAttribute( 'aria-expanded', 'false' );
} );
}
/**
* Internal dependencies
*/
import wpx from './wpx';

function toggleSubmenuOnClick( event ) {
const buttonToggle = event.target.closest( '[aria-expanded]' );
const isSubmenuOpen = buttonToggle.getAttribute( 'aria-expanded' );

if ( isSubmenuOpen === 'true' ) {
closeSubmenus( buttonToggle.closest( '.wp-block-navigation-item' ) );
} else {
// Close all sibling submenus.
const parentElement = buttonToggle.closest(
'.wp-block-navigation-item'
);
const navigationParent = buttonToggle.closest(
'.wp-block-navigation__submenu-container, .wp-block-navigation__container, .wp-block-page-list'
);
navigationParent
.querySelectorAll( '.wp-block-navigation-item' )
.forEach( function ( child ) {
if ( child !== parentElement ) {
closeSubmenus( child );
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.
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

navigation.firstMenuElement.focus();
}
} );
// Open submenu.
buttonToggle.setAttribute( 'aria-expanded', 'true' );
}
}

// Necessary for some themes such as TT1 Blocks, where
// scripts could be loaded before the body.
window.addEventListener( 'load', () => {
const submenuButtons = document.querySelectorAll(
'.wp-block-navigation-submenu__toggle'
);

submenuButtons.forEach( function ( button ) {
button.addEventListener( 'click', toggleSubmenuOnClick );
} );

// Close on click outside.
document.addEventListener( 'click', function ( event ) {
const navigationBlocks = document.querySelectorAll(
'.wp-block-navigation'
);
navigationBlocks.forEach( function ( block ) {
if ( ! block.contains( event.target ) ) {
closeSubmenus( block );
}
} );
} );
// Close on focus outside or escape key.
document.addEventListener( 'keyup', function ( event ) {
const submenuBlocks = document.querySelectorAll(
'.wp-block-navigation-item.has-child'
);
submenuBlocks.forEach( function ( block ) {
if ( ! block.contains( event.target ) ) {
closeSubmenus( block );
} else if ( event.key === 'Escape' ) {
const toggle = block.querySelector( '[aria-expanded="true"]' );
closeSubmenus( block );
// Focus the submenu trigger so focus does not get trapped in the closed submenu.
toggle?.focus();
}
} );
} );
},
focusLastFocusedElement: ( { context: { navigation } } ) => {
if ( ! navigation.open && navigation.previousElementWithFocus )
navigation.previousElementWithFocus.focus();
},
},
},
} );
23 changes: 23 additions & 0 deletions packages/block-library/src/navigation/wpx/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable jsdoc/check-tag-names */
/** @jsx h */

/**
* External dependencies
*/
import { h } from 'preact';
import { useMemo } from 'preact/hooks';

/**
* Internal dependencies
*/
import { deepSignal } from './deep-signal';
import { component } from './hooks';

export default () => {
const WpContext = ( { children, data, context: { Provider } } ) => {
const signals = useMemo( () => deepSignal( JSON.parse( data ) ), [] );
return <Provider value={ signals }>{ children }</Provider>;
};
component( 'wp-context', WpContext );
};
Loading