Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0874d3a
Initial block reg
getdave Dec 3, 2025
a3a2aaa
Use placeholder icon
getdave Dec 3, 2025
a41e5da
typographt styles
getdave Dec 3, 2025
509ba4d
Use richtext
getdave Dec 3, 2025
65c6620
Make desc more generic
getdave Dec 3, 2025
efd367b
Rename block with navigation namespace
getdave Dec 5, 2025
f0ced15
Update remaining references to old name
getdave Dec 5, 2025
f8da4fe
Use new icon supplied by design
getdave Dec 5, 2025
e66deed
Restrict insertion to only when editing a overlay template part
getdave Dec 5, 2025
65367c3
Register server side
getdave Dec 10, 2025
dbe8322
Apply recommended identifier to Richtext
getdave Dec 10, 2025
4f6867e
i18n of close text
getdave Dec 10, 2025
82c78bc
Tweal function naming
getdave Dec 10, 2025
8eacbee
Avoid wrapper to simplify
getdave Dec 10, 2025
e26bf85
Simplify as a result of skipping serialization
getdave Dec 10, 2025
6728514
Remove anchor support
getdave Dec 10, 2025
e2db952
Correct since doc
getdave Dec 10, 2025
f46c64a
Fix blank file PHP
getdave Dec 10, 2025
9ec0ffd
Try fix to lint error in save def
getdave Dec 11, 2025
741539f
Only apply default aria label when text is not being controlled
getdave Dec 11, 2025
3a6d9f0
Same aria lavel fix but for save
getdave Dec 11, 2025
733ca79
Mark block experimental in metadata
getdave Dec 11, 2025
7fe8323
Remove i18n from save def
getdave Dec 11, 2025
3f80654
Refactor to ToolsPanel
getdave Dec 11, 2025
a66d451
Simplify RichText usage
getdave Dec 11, 2025
e10225a
Reinstate only allowing selected formats
getdave Dec 11, 2025
75a34c7
Style button manually
getdave Dec 11, 2025
48ab8c2
Add safeguard around direct usage of editor store
getdave Dec 11, 2025
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
9 changes: 9 additions & 0 deletions docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,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

A customizable button to close overlays. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-overlay-close))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a note about when it's allowed to be inserted (overlay template part)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would require updating the block description in block.json as this is auto generated from that. Not sure 😬


- **Name:** core/navigation-overlay-close
- **Category:** design
- **Supports:** color (background, text, ~~gradients~~), spacing (padding), typography (fontSize, lineHeight)
Copy link

Copilot AI Dec 10, 2025

Choose a reason for hiding this comment

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

The typography supports documentation is incomplete. The block.json file shows that the block supports additional typography features including fontFamily, fontWeight, fontStyle, textTransform, textDecoration, and letterSpacing, but the documentation only lists fontSize and lineHeight.

Suggested change
- **Supports:** color (background, text, ~~gradients~~), spacing (padding), typography (fontSize, lineHeight)
- **Supports:** color (background, text, ~~gradients~~), spacing (padding), typography (fontSize, lineHeight, fontFamily, fontWeight, fontStyle, textTransform, textDecoration, letterSpacing)

Copilot uses AI. Check for mistakes.
- **Attributes:** displayMode, text

## Submenu

Add a submenu to your navigation. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-submenu))
Expand Down
5 changes: 5 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import * as navigation from './navigation';
import * as navigationLink from './navigation-link';
import * as navigationSubmenu from './navigation-submenu';
import * as nextpage from './nextpage';
import * as navigationOverlayClose from './navigation-overlay-close';
import * as pattern from './pattern';
import * as pageList from './page-list';
import * as pageListItem from './page-list-item';
Expand Down Expand Up @@ -276,6 +277,10 @@ const getAllBlocks = () => {
blocks.push( formSubmissionNotification );
}

if ( window?.__experimentalNavigationOverlays ) {
blocks.push( navigationOverlayClose );
}

// When in a WordPress context, conditionally
// add the classic block and TinyMCE editor
// under any of the following conditions:
Expand Down
53 changes: 53 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,53 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
Copy link
Member

Choose a reason for hiding this comment

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

Should this have a "parent" definition to restrict insertion to the overlay template part?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting. I didn't think that would work at the entity level. I'll give that a try now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't. I've used a filter to restrict insertion to when we're editing an overlay template part.

It still shows up in the inserter but that's because we don't seem to have a way to filter that dynamically as it relies on getBlockType settings.

We could consider hiding blocks that can't be inserted from the inserter. That would seem to make sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

While we can't use "parent" since the Navigation Overlay isn't a distinct block type (but rather a core/template-part with area set to overlay), we could still use it to limit the usage of the block to Template Parts (in addition to the filter that Dave added). This would at least prevent the block from showing up outside of Template Parts.

Aside, maybe "ancestor" instead of "parent" would be a better fit? In case the Overlay Close button isn't a direct child of a Navigation Overlay but e.g. inside of some Group or Column block 🤔

diff --git a/packages/block-library/src/navigation-overlay-close/block.json b/packages/block-library/src/navigation-overlay-close/block.json
index 96cdabca2a2..aade2aaf570 100644
--- a/packages/block-library/src/navigation-overlay-close/block.json
+++ b/packages/block-library/src/navigation-overlay-close/block.json
@@ -6,6 +6,7 @@
        "category": "design",
        "description": "A customizable button to close overlays.",
        "keywords": [ "close", "overlay", "navigation", "menu" ],
+       "ancestor": [ "core/template-part" ],
        "textdomain": "default",
        "attributes": {
                "displayMode": {
Before After
image image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out this won't work because when in focused template part editing mode we don't have a template part block. As a result with that attribute in place you can no longer add a Close block to the overlay template.

Copy link
Contributor

Choose a reason for hiding this comment

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

Turns out this won't work because when in focused template part editing mode we don't have a template part block. As a result with that attribute in place you can no longer add a Close block to the overlay template.

You're right 😢

image

BTW this raises the question if we should make Gutenberg smart enough to understand that if we're currently in focused "x entity" editing mode, and a block includes x in its "parent" or "ancestor" fields, then it should be included in the inserter. I might look into that.

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 think it should yes. Or we allow blocks to define the inserter setting as a function. That function would need sufficient context to be able to determine whether or not the block should show in a given scenario.

Copy link
Contributor

Choose a reason for hiding this comment

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

I've filed an issue: #73827

Or we allow blocks to define the inserter setting as a function. That function would need sufficient context to be able to determine whether or not the block should show in a given scenario.

One thing I've discussed with @mtias is to

  1. allow block variations in places such as the "parent" and "ancestor" fields in block.json (using a syntax where the variation name is slash-appended to the block name, e.g. core/heading/h2), and to
  2. create core/template-part variations for each area (resulting in e.g. core/template-part/overlay).

Together, those changes should allow us to limit the block to the Navigation Overlay.

(Note that @mtias is also modifying the behavior of the block scope in variations: #73823)

Copy link
Contributor

Choose a reason for hiding this comment

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

  1. allow block variations in places such as the "parent" and "ancestor" fields in block.json (using a syntax where the variation name is slash-appended to the block name, e.g. core/heading/h2)

Draft PR: #73828

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ockham Thank you for your work here. As it's experimental, I'm going to go ahead and merge the block and then follow up to include your work when it lands as it looks to be exactly what we'll need here 🙇

"apiVersion": 3,
"name": "core/navigation-overlay-close",
"title": "Navigation Overlay Close",
"category": "design",
"description": "A customizable button to close overlays.",
"keywords": [ "close", "overlay", "navigation", "menu" ],
"textdomain": "default",
"attributes": {
"displayMode": {
"type": "string",
"enum": [ "icon", "text", "both" ],
"default": "icon"
},
"text": {
"type": "rich-text",
"source": "rich-text",
"selector": "span",
"default": "Close"
}
},
"supports": {
"color": {
"gradients": false,
"__experimentalDefaultControls": {
"background": true,
"text": true
}
},
"spacing": {
"padding": true,
"__experimentalDefaultControls": {
"padding": true
}
},
"typography": {
"fontSize": true,
"lineHeight": true,
"__experimentalFontFamily": true,
"__experimentalFontWeight": true,
"__experimentalFontStyle": true,
"__experimentalTextTransform": true,
"__experimentalTextDecoration": true,
"__experimentalLetterSpacing": true,
"__experimentalDefaultControls": {
"fontSize": true
}
}
},
"editorStyle": "wp-block-navigation-overlay-close-editor",
"style": "wp-block-navigation-overlay-close"
}
82 changes: 82 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,82 @@
/**
* WordPress dependencies
*/
import {
InspectorControls,
useBlockProps,
RichText,
} from '@wordpress/block-editor';
import {
PanelBody,
__experimentalToggleGroupControl as ToggleGroupControl,
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
Button,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { close as closeIcon } from '@wordpress/icons';

export default function NavigationOverlayCloseEdit( {
attributes,
setAttributes,
} ) {
const { displayMode, text } = attributes;
const showIcon = displayMode === 'icon' || displayMode === 'both';
const showText = displayMode === 'text' || displayMode === 'both';

const blockProps = useBlockProps( {
className: 'wp-block-navigation-overlay-close',
} );

return (
<>
<InspectorControls>
<PanelBody title={ __( 'Display Settings' ) }>
<ToggleGroupControl
label={ __( 'Display Mode' ) }
value={ displayMode }
onChange={ ( value ) =>
setAttributes( { displayMode: value } )
}
isBlock
__next40pxDefaultSize
__nextHasNoMarginBottom
>
<ToggleGroupControlOption
value="icon"
label={ __( 'Icon' ) }
/>
<ToggleGroupControlOption
value="text"
label={ __( 'Text' ) }
/>
<ToggleGroupControlOption
value="both"
label={ __( 'Both' ) }
/>
</ToggleGroupControl>
</PanelBody>
</InspectorControls>
<Button
{ ...blockProps }
icon={ showIcon ? closeIcon : undefined }
aria-label={ __( 'Close' ) }
__next40pxDefaultSize
>
{ showText && (
<RichText
identifier="text"
value={ text }
onChange={ ( value ) =>
setAttributes( { text: value } )
}
placeholder={ __( 'Close' ) }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
withoutInteractiveFormatting
tagName="span"
className="wp-block-navigation-overlay-close__text"
/>
) }
</Button>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.block-editor-block-list__block[data-type="core/navigation-overlay-close"] {
.wp-block-navigation-overlay-close {
min-height: 44px;
min-width: 44px;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have some scss variables we could use instead? Maybe a min button size variable?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, could the font-size impact this icon? Right now the icon is always the same size even when interacting with the font size scale. It feels a bit odd to have the close text really large and the icon stay small. I'm not sure using font size is the right approach for customizing that, but it might work well.

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 switched to em so it's proportional.

I think we should look at a control for icon size in a followup though. It's likely to be needed.

}
}

10 changes: 10 additions & 0 deletions packages/block-library/src/navigation-overlay-close/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* WordPress dependencies
*/
import { SVG, Path } from '@wordpress/primitives';

export default (
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<Path d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2Zm.5 14c0 .3-.2.5-.5.5H6c-.3 0-.5-.2-.5-.5V6c0-.3.2-.5.5-.5h12c.3 0 .5.2.5.5v12ZM15 8l-3 3-3-3-1.1 1.1 3 3-3 3L9 16.2l3-3 3 3 1.1-1.1-3-3 3-3L15 8Z" />
</SVG>
);
70 changes: 70 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,70 @@
/**
* WordPress dependencies
*/
import { addFilter } from '@wordpress/hooks';
import { select } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import initBlock from '../utils/init-block';
import edit from './edit';
import metadata from './block.json';
import save from './save';
import icon from './icon';

const { name } = metadata;

export { metadata, name };

export const settings = {
icon,
edit,
save,
};

function isWithinOverlay() {
// @wordpress/block-library should not depend on @wordpress/editor.
// Blocks can be loaded into a *non-post* block editor, so to avoid
// declaring @wordpress/editor as a dependency, we must access its
// store by string.
// eslint-disable-next-line @wordpress/data-no-store-string-literals
const { getCurrentPostType, getCurrentPostId } = select( 'core/editor' );
const { getEditedEntityRecord } = select( coreStore );

const postType = getCurrentPostType();
const postId = getCurrentPostId();

if ( postType === 'wp_template_part' && postId ) {
const templatePartEntity = getEditedEntityRecord(
'postType',
'wp_template_part',
postId
);

return templatePartEntity?.area === 'overlay';
}

return false;
}

export const init = () => {
addFilter(
'blockEditor.__unstableCanInsertBlockType',
'core/navigation-overlay-close/restrict-to-overlay-template-parts',
( canInsert, blockType ) => {
if ( blockType.name !== 'core/navigation-overlay-close' ) {
return canInsert;
}

if ( ! canInsert ) {
return canInsert;
}

return isWithinOverlay();
}
);

return initBlock( { name, metadata, settings } );
};
18 changes: 18 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,18 @@
<?php
/**
* Server-side registering of the `core/navigation-overlay-close` block.
*
* @package WordPress
*/

/**
* Registers the navigation overlay close block.
*
* @since 7.0.0
*/
function register_block_core_navigation_overlay_close() {
register_block_type_from_metadata(
__DIR__ . '/navigation-overlay-close'
);
}
add_action( 'init', 'register_block_core_navigation_overlay_close' );
40 changes: 40 additions & 0 deletions packages/block-library/src/navigation-overlay-close/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* WordPress dependencies
*/
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

export default function NavigationOverlayCloseSave( { attributes } ) {
const { displayMode, text } = attributes;
const showIcon = displayMode === 'icon' || displayMode === 'both';
const showText = displayMode === 'text' || displayMode === 'both';

// eslint-disable-next-line react-compiler/react-compiler
const blockProps = useBlockProps.save( {
className: 'wp-block-navigation-overlay-close',
} );

return (
<button { ...blockProps } type="button" aria-label={ __( 'Close' ) }>
{ showIcon && (
<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-1-6.1 6.2-6.1-6.2-1.1 1 6.1 6.3-6.5 6.7 1.1 1 6.5-6.6 6.5 6.6 1.1-1z" />
</svg>
) }
{ showText && (
<RichText.Content
tagName="span"
value={ text }
className="wp-block-navigation-overlay-close__text"
/>
) }
</button>
);
}
32 changes: 32 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,32 @@
.wp-block-navigation-overlay-close {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5em;
padding: 0.5em;
border: none;
background: transparent;
cursor: pointer;
text-decoration: none;
transition: opacity 0.2s;

&:hover {
opacity: 0.8;
}

&:focus {
outline: 2px solid currentColor;
outline-offset: 2px;
}

svg {
width: 1.5em;
height: 1.5em;
fill: currentColor;
}

span {
display: inline-block;
}
}

Loading