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

Navigation Overlay customisation via Template Parts #55657

Draft
wants to merge 3 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ A collection of blocks that allow visitors to get around your site. ([Source](ht
- **Name:** core/navigation
- **Category:** theme
- **Supports:** align (full, wide), ariaLabel, inserter, interactivity, layout (allowSizingOnChildren, default, ~~allowInheriting~~, ~~allowSwitching~~, ~~allowVerticalAlignment~~), spacing (blockGap, units), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~
- **Attributes:** __unstableLocation, backgroundColor, customBackgroundColor, customOverlayBackgroundColor, customOverlayTextColor, customTextColor, hasIcon, icon, maxNestingLevel, openSubmenusOnClick, overlayBackgroundColor, overlayMenu, overlayTextColor, ref, rgbBackgroundColor, rgbTextColor, showSubmenuIcon, templateLock, textColor
- **Attributes:** __unstableLocation, backgroundColor, customBackgroundColor, customOverlayBackgroundColor, customOverlayTextColor, customTextColor, hasIcon, icon, maxNestingLevel, openSubmenusOnClick, overlayBackgroundColor, overlayId, overlayMenu, overlayTextColor, ref, rgbBackgroundColor, rgbTextColor, showSubmenuIcon, templateLock, textColor

## Custom Link

Expand All @@ -473,6 +473,15 @@ Add a page, link, or another item to your navigation. ([Source](https://github.c
- **Supports:** interactivity (clientNavigation), typography (fontSize, lineHeight), ~~html~~, ~~renaming~~, ~~reusable~~
- **Attributes:** description, id, isTopLevelLink, kind, label, opensInNewTab, rel, title, type, url

## Navigation Overlay Close

Add a Close button to your Navigation Overlay. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-overlay-close))

- **Name:** core/navigation-overlay-close
- **Category:** design
- **Supports:** anchor, color (background, text, ~~link~~), dimensions (height, width), interactivity, spacing (margin, padding, units), ~~html~~, ~~multiple~~, ~~reusable~~
- **Attributes:** hasIcon

## Submenu

Add a submenu to your navigation. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-submenu))
Expand Down
1 change: 1 addition & 0 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function gutenberg_reregister_core_block_types() {
'navigation.php' => 'core/navigation',
'navigation-link.php' => 'core/navigation-link',
'navigation-submenu.php' => 'core/navigation-submenu',
'navigation-overlay-close.php' => 'core/navigation-overlay-close',
'page-list.php' => 'core/page-list',
'page-list-item.php' => 'core/page-list-item',
'pattern.php' => 'core/pattern',
Expand Down
65 changes: 65 additions & 0 deletions lib/experimental/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,68 @@
add_filter( 'render_block', $callback, 10, 2 );
}
}

function add_navigation_overlay_area( $areas ) {

Check failure on line 81 in lib/experimental/blocks.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

The "add_navigation_overlay_area()" function should be guarded against redeclaration.
$areas[] = array(
'area' => 'navigation-overlay',
'label' => _x( 'Navigation Overlay', 'template part area' ),

Check warning on line 84 in lib/experimental/blocks.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Missing $domain parameter in function call to _x(). If this text string is supposed to use a WP Core translation, use the "default" text domain.
'description' => __(

Check warning on line 85 in lib/experimental/blocks.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Missing $domain parameter in function call to __(). If this text string is supposed to use a WP Core translation, use the "default" text domain.
'An area for navigation overlay content.'
),
'area_tag' => 'section',
'icon' => 'handle',
);
return $areas;
}
add_filter( 'default_wp_template_part_areas', 'add_navigation_overlay_area', 10, 1 );
draganescu marked this conversation as resolved.
Show resolved Hide resolved

function add_default_navigation_overlay_template_part( $block_template, $id, $template_type ) {

Check failure on line 95 in lib/experimental/blocks.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

The "add_default_navigation_overlay_template_part()" function should be guarded against redeclaration.

// if the template type is not template part, return the block template
if ( 'wp_template_part' !== $template_type ) {
return $block_template;
}

// If its not the "Core" Navigation Overlay, return the block template.
if ( $id !== 'core//navigation-overlay' ) {

Check failure on line 103 in lib/experimental/blocks.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Use Yoda Condition checks, you must.
return $block_template;
}

// If the block template is not empty, return the "found" block template.
// Failure to do this will override any "found" overlay template part from the Theme.
if ( ! empty( $block_template ) ) {
return $block_template;
}

// Return a default template part for the Navigation Overlay.
// This is essentially a "Core" fallback in case the Theme does not provide one.
$template = new WP_Block_Template();

// TODO: should we provide "$theme" here at all as this is a "Core" template.
$template->id = 'core' . '//' . 'navigation-overlay';
$template->theme = 'core';
$template->slug = 'navigation-overlay';
$template->source = 'custom';
$template->type = 'wp_template_part';
$template->title = 'Navigation Overlay';
$template->status = 'publish';
$template->has_theme_file = null;
$template->is_custom = false;
$template->modified = null;
$template->origin = null;
$template->author = null;

// Set the area to match the Navigation Overlay area.
$template->area = 'navigation-overlay';

// The content is the default Navigation Overlay template part. This will only be used
// if the Theme does not provide a template part for the Navigation Overlay.
// PHP is used here to allow for translation of the default template part.
ob_start();
include __DIR__ . '/navigation-overlay.php';
$template->content = ob_get_clean();

return $template;
}

add_filter( 'get_block_file_template', 'add_default_navigation_overlay_template_part', 10, 3 );
9 changes: 9 additions & 0 deletions lib/experimental/navigation-overlay.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- wp:group {"lock":{"move":true,"remove":true},"metadata":{"name":"<?php echo __( 'Overlay' ); ?>"},"style":{"dimensions":{"minHeight":"100vh"},"spacing":{"padding":{"top":"clamp(1rem, calc(var(\u002d\u002dwp\u002dadmin\u002d\u002dadmin\u002dbar\u002d\u002dheight, 1rem) + var(\u002d\u002dwp\u002d\u002dstyle\u002d\u002droot\u002d\u002dpadding\u002dtop, 1rem)), 20rem)","bottom":"clamp(1rem, var(\u002d\u002dwp\u002d\u002dstyle\u002d\u002droot\u002d\u002dpadding\u002dbottom, 1rem), 20rem)","left":"clamp(1rem, var(\u002d\u002dwp\u002d\u002dstyle\u002d\u002droot\u002d\u002dpadding\u002dleft), 20rem)","right":"clamp(1rem, var(\u002d\u002dwp\u002d\u002dstyle\u002d\u002droot\u002d\u002dpadding\u002dright), 20rem)"}}},"layout":{"type":"constrained","justifyContent":"center"}} -->

Check warning on line 1 in lib/experimental/navigation-overlay.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Missing $domain parameter in function call to __(). If this text string is supposed to use a WP Core translation, use the "default" text domain.
<div class="wp-block-group" style="min-height:100vh;padding-top:clamp(1rem, calc(var(--wp-admin--admin-bar--height, 1rem) + var(--wp--style--root--padding-top, 1rem)), 20rem);padding-right:clamp(1rem, var(--wp--style--root--padding-right), 20rem);padding-bottom:clamp(1rem, var(--wp--style--root--padding-bottom, 1rem), 20rem);padding-left:clamp(1rem, var(--wp--style--root--padding-left), 20rem)"><!-- wp:group {"metadata":{"name":"Close"},"align":"wide","layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"right"}} -->
<div class="wp-block-group alignwide"><!-- wp:navigation-overlay-close {"lock":{"move":false,"remove":true},"metadata":{},"className":"wp-block-navigation-overlay-close"} /--></div>
<!-- /wp:group -->

<!-- wp:group {"metadata":{"name":"<?php echo __( 'Contents' ); ?>"},"align":"wide","style":{"spacing":{"blockGap":"var:preset|spacing|30"}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"right"}} -->

Check warning on line 6 in lib/experimental/navigation-overlay.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Missing $domain parameter in function call to __(). If this text string is supposed to use a WP Core translation, use the "default" text domain.
<div class="wp-block-group alignwide"><!-- wp:navigation {"overlayMenu":"never","align":"wide","layout":{"type":"flex","orientation":"vertical","justifyContent":"right"}} /--></div>
<!-- /wp:group --></div>
<!-- /wp:group -->
2 changes: 2 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions packages/block-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"@wordpress/private-apis": "file:../private-apis",
"@wordpress/reusable-blocks": "file:../reusable-blocks",
"@wordpress/rich-text": "file:../rich-text",
"@wordpress/router": "file:../router",
Copy link
Contributor

Choose a reason for hiding this comment

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

Router shouldn't be a dependency of the block library package as not every editor has one.

@glendaviesnz added a way to handle navigation in #57036 via an editor setting that will work across the post and site editors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the pointer Dan 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

There may be some modifications coming to that approach now as we need to extend it a little probably in order to get rid of the template-only mode, will hopefully get that sorted today.

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 template-only mode

What is this mode you speak of?

Copy link
Contributor

@glendaviesnz glendaviesnz Jan 11, 2024

Choose a reason for hiding this comment

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

What is this mode you speak of?

https://github.com/WordPress/gutenberg/blob/trunk/packages/editor/src/store/actions.js#L579

It was added temporarily as part of the editor unification work, but we are now in the process of pulling it out again. Context being we wanted a way to edit a synced pattern in isolation in the post editor, so we looked at adding a pattern-only mode, but it was then decided that this was not very scalable as we didn't want modes for lots of different entities.

It was decided that a better approach would be to change the entity that was passed into the editor provider, and we added a getPostLinkProps editor setting which is a callback that returns an onClick event and href that changes the current entity in the editor.

We initially just used this for editing synced patterns in the post editor but I am now looking at doing the same for editing templates from the post editor, which currently uses the template-only mode. When working through this it seems our initial implementation doesn't extend quite so well for the wider use case, so I have a suggested refactoring of this here.

"@wordpress/server-side-render": "file:../server-side-render",
"@wordpress/url": "file:../url",
"@wordpress/viewport": "file:../viewport",
Expand Down
2 changes: 2 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import * as more from './more';
import * as navigation from './navigation';
import * as navigationLink from './navigation-link';
import * as navigationSubmenu from './navigation-submenu';
import * as navigationOverlayClose from './navigation-overlay-close';
import * as nextpage from './nextpage';
import * as pattern from './pattern';
import * as pageList from './page-list';
Expand Down Expand Up @@ -186,6 +187,7 @@ const getAllBlocks = () => {
navigation,
navigationLink,
navigationSubmenu,
navigationOverlayClose,
siteLogo,
siteTitle,
siteTagline,
Expand Down
49 changes: 49 additions & 0 deletions packages/block-library/src/navigation-overlay-close/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "core/navigation-overlay-close",
"title": "Navigation Overlay Close",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't worry - we can make a separate PR for this block if/when we decide to merge this branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@WordPress/interactivity-api This block is going to effectively be the same as the existing button which toggles the overlay. It's required because when editing the overlay within the editor, users need to be able to:

  • perceive the presence of the Close button
  • style the Close button directly

I'd really appreciate any advice/help on how best to transfer the interactivity directives over the this block 🙏

Copy link
Member

Choose a reason for hiding this comment

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

We've been doing so with the WP_HTML_Tag_Processor quite successfully so far.

We basically use the WP_HTML_Tag_Processor on the render callback of the block, search for the inner block, and add the necessary directives. Something like this:

$p = new WP_HTML_Tag_Processor( $block_content );

if ( $p->next_tag( array( 'class' => 'wp-block-button' ) ) ) {
  $p->set_attribute( 'data-wp-on--click', 'actions.openMenu' );
}

"category": "design",
"description": "Add a Close button to your Navigation Overlay.",
"textdomain": "default",
"icon": "dismiss",
"attributes": {
"hasIcon": {
"type": "boolean",
"default": true
}
},
"usesContext": [
"textColor",
"customTextColor",
"backgroundColor",
"customBackgroundColor"
],
"supports": {
"multiple": false,
"reusable": false,
getdave marked this conversation as resolved.
Show resolved Hide resolved
"html": false,
"dimensions": {
"width": true,
"height": true
},
"color": {
"link": false,
"text": true,
"background": true
},
"interactivity": true,
"anchor": true,
"spacing": {
"margin": true,
"padding": true,
"units": [ "px", "em", "rem", "vh", "vw" ],
"__experimentalDefaultControls": {
"margin": true,
"padding": true
}
}
},
"editorStyle": "wp-block-navigation-overlay-close-editor",
"style": "wp-block-navigation-overlay-close"
}
55 changes: 55 additions & 0 deletions packages/block-library/src/navigation-overlay-close/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* WordPress dependencies
*/
import { Button, Icon, ToggleControl, PanelBody } from '@wordpress/components';
import { close } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';

/**
* Internal dependencies
*/
import { unlock } from '../lock-unlock';

const { useHistory } = unlock( routerPrivateApis );

export default function Edit( { attributes, isSelected, setAttributes } ) {
const blockProps = useBlockProps();
const history = useHistory();
const { hasIcon } = attributes;

const closeText = __( 'Close' );

const onClick = () => {
if ( isSelected ) {
// Exit navigation overlay edit mode.
history.back();
Copy link
Contributor

Choose a reason for hiding this comment

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

There are more routes available, so this doesn't work. Example repro:

  • From the Site Editor
  • Go to the Overlay Template Editor
  • Click the Site Logo/W in the top Left to open up the left Sidebar
  • Click the Editor Canvas
  • Click the Overlay X
  • The Editor Sidebar will open, and you can't exit the overlay edit directly back to the edtior

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, we should still have the Back button navigation in the central header area as on other templates.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, we should still have the Back button navigation in the central header area as on other templates.

That's turned into a wider problem. I agree we need it but it will need to be a seperate PR.

}
};

blockProps.onClick = onClick;

return (
<>
<InspectorControls>
<PanelBody title={ __( 'Display' ) }>
<ToggleControl
__nextHasNoMarginBottom
label={ __( 'Use icon' ) }
help={ __(
'Configure whether the button use an icon or text.'
) }
onChange={ ( value ) =>
setAttributes( { hasIcon: value } )
}
checked={ hasIcon }
/>
</PanelBody>
</InspectorControls>
<Button { ...blockProps } aria-label={ hasIcon && closeText }>
{ hasIcon ? <Icon icon={ close } /> : closeText }
</Button>
</>
);
}
16 changes: 16 additions & 0 deletions packages/block-library/src/navigation-overlay-close/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Internal dependencies
*/
import initBlock from '../utils/init-block';
import metadata from './block.json';
import edit from './edit';

const { name } = metadata;

export { metadata, name };

export const settings = {
edit,
};

export const init = () => initBlock( { name, metadata, settings } );
48 changes: 48 additions & 0 deletions packages/block-library/src/navigation-overlay-close/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php


function render_block_core_navigation_overlay_close( $attributes ) {

// This icon is duplicated in the Navigation Block itself.

Check failure on line 6 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Tabs must be used to indent lines; spaces are not allowed
// See WP_Navigation_Block_Renderer::get_responsive_container_markup().

Check failure on line 7 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Tabs must be used to indent lines; spaces are not allowed
// Changes to this icon should be reflected there as well.

Check failure on line 8 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Tabs must be used to indent lines; spaces are not allowed
$close_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>';

$hasIcon = ! empty( $attributes['hasIcon'] );

Check failure on line 11 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Variable "$hasIcon" is not in valid snake_case format, try "$has_icon"

$wrapper_attributes = get_block_wrapper_attributes(
array_filter( // Removes any empty attributes.
// Attributes
array(
// This directive is duplicated in the Navigation Block itself.
// See WP_Navigation_Block_Renderer::get_responsive_container_markup().
// Changes to this directive should be reflected there as well.
'data-wp-on--click' => 'actions.closeMenuOnClick',
'aria-label' => $hasIcon ? __( 'Close menu' ) : false,

Check failure on line 21 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Variable "$hasIcon" is not in valid snake_case format, try "$has_icon"
)
)
);

$content = $hasIcon ? $close_icon : __( 'Close menu' );

Check failure on line 26 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Variable "$hasIcon" is not in valid snake_case format, try "$has_icon"

return sprintf(
'<button %1$s>%2$s</button>',
$wrapper_attributes,
$content,

Check failure on line 31 in packages/block-library/src/navigation-overlay-close/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Trailing comma's are not allowed in function calls in PHP 7.2 or earlier
);

}


/**
* Registers the `core/navigation-overlay-close` block on server.
*/
function register_block_core_navigation_overlay_close() {
register_block_type_from_metadata(
__DIR__ . '/navigation-overlay-close',
array(
'render_callback' => 'render_block_core_navigation_overlay_close',
)
);
}
add_action( 'init', 'register_block_core_navigation_overlay_close' );
6 changes: 6 additions & 0 deletions packages/block-library/src/navigation-overlay-close/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* Internal dependencies
*/
import { init } from './';

export default init();
34 changes: 34 additions & 0 deletions packages/block-library/src/navigation-overlay-close/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

// Size of burger and close icons.
$navigation-icon-size: 24px;

// Menu and close buttons.
.wp-block-navigation-overlay-close {
height: auto; // remove default height applied to button component
vertical-align: middle;
cursor: pointer;
border: none;
margin: 0;
padding: 0;
text-transform: inherit;
z-index: 2; // Needs to be above the modal z index itself.
background-color: inherit; // remove user agent stylesheet default.
color: inherit; // remove user agent stylesheet default.

// When set to collapse into a text button, it should inherit the parent font.
// This needs specificity to override inherited properties by the button element and component.
&.wp-block-navigation-overlay-close {
font-family: inherit;
font-weight: inherit;
font-size: inherit;
}

svg {
fill: currentColor;
pointer-events: none;
display: block;
width: $navigation-icon-size;
height: $navigation-icon-size;
}
}

5 changes: 4 additions & 1 deletion packages/block-library/src/navigation/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"textdomain": "default",
"attributes": {
"ref": {
"type": "number"
"type": [ "number", "string" ]
},
"textColor": {
"type": "string"
Expand Down Expand Up @@ -84,6 +84,9 @@
"templateLock": {
"type": [ "string", "boolean" ],
"enum": [ "all", "insert", "contentOnly", false ]
},
"overlayId": {
"type": "string"
}
},
"providesContext": {
Expand Down
2 changes: 2 additions & 0 deletions packages/block-library/src/navigation/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export const PRIORITIZED_INSERTER_BLOCKS = [
'core/navigation-link',
];

export const NAVIGATION_OVERLAY_TEMPLATE_PART_AREA = 'navigation-overlay';

// These parameters must be kept aligned with those in
// lib/compat/wordpress-6.3/navigation-block-preloading.php
// and
Expand Down
Loading
Loading