diff --git a/backport-changelog/7.0/10844.md b/backport-changelog/7.0/10844.md
new file mode 100644
index 00000000000000..aba9dd7c89c285
--- /dev/null
+++ b/backport-changelog/7.0/10844.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/10844
+
+* https://github.com/WordPress/gutenberg/pull/74968
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index 29e4dfd1c33296..52192006916819 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -548,7 +548,6 @@ Add a page, link, or another item to your navigation. ([Source](https://github.c
A customizable button to close overlays. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/navigation-overlay-close))
- **Name:** core/navigation-overlay-close
-- **Experimental:** true
- **Category:** design
- **Supports:** color (background, text, ~~gradients~~), spacing (padding), typography (fontSize, lineHeight)
- **Attributes:** displayMode, text
diff --git a/lib/compat/wordpress-7.0/rest-api.php b/lib/compat/wordpress-7.0/rest-api.php
index 285dfbc24e8df6..9bffd0971b0ba1 100644
--- a/lib/compat/wordpress-7.0/rest-api.php
+++ b/lib/compat/wordpress-7.0/rest-api.php
@@ -49,25 +49,23 @@ function gutenberg_modify_wp_template_part_post_type_args_7_0( $args ) {
add_filter( 'register_wp_template_part_post_type_args', 'gutenberg_modify_wp_template_part_post_type_args_7_0' );
/**
- * Registers the 'navigation-overlay' template part area when the experiment is enabled.
+ * Registers the 'navigation-overlay' template part area.
*
* @param array $areas Array of template part area definitions.
* @return array Modified array of template part area definitions.
*/
-if ( gutenberg_is_experiment_enabled( 'gutenberg-customizable-navigation-overlays' ) ) {
- function gutenberg_register_overlay_template_part_area( $areas ) {
- $areas[] = array(
- 'area' => 'navigation-overlay',
- 'label' => __( 'Navigation Overlay', 'gutenberg' ),
- 'description' => __( 'Custom overlay area for navigation overlays.', 'gutenberg' ),
- 'icon' => 'overlay',
- 'area_tag' => 'div',
- );
+function gutenberg_register_overlay_template_part_area( $areas ) {
+ $areas[] = array(
+ 'area' => 'navigation-overlay',
+ 'label' => __( 'Navigation Overlay', 'gutenberg' ),
+ 'description' => __( 'Custom overlay area for navigation overlays.', 'gutenberg' ),
+ 'icon' => 'overlay',
+ 'area_tag' => 'div',
+ );
- return $areas;
- }
- add_filter( 'default_wp_template_part_areas', 'gutenberg_register_overlay_template_part_area' );
+ return $areas;
}
+add_filter( 'default_wp_template_part_areas', 'gutenberg_register_overlay_template_part_area' );
/**
* Adds user global styles link relation to all theme responses.
diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php
index d3cc0612e2adeb..9c90acc005c81d 100644
--- a/lib/experimental/editor-settings.php
+++ b/lib/experimental/editor-settings.php
@@ -31,9 +31,6 @@ function gutenberg_enable_experiments() {
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-content-only-inspector-fields', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalContentOnlyInspectorFields = true', 'before' );
}
- if ( $gutenberg_experiments && array_key_exists( 'gutenberg-customizable-navigation-overlays', $gutenberg_experiments ) ) {
- wp_add_inline_script( 'wp-block-editor', 'window.__experimentalNavigationOverlays = true', 'before' );
- }
if ( gutenberg_is_experiment_enabled( 'active_templates' ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalTemplateActivate = true', 'before' );
}
diff --git a/lib/experiments-page.php b/lib/experiments-page.php
index f3c5066f9e38cd..2d4149014e627f 100644
--- a/lib/experiments-page.php
+++ b/lib/experiments-page.php
@@ -197,18 +197,6 @@ function gutenberg_initialize_experiments_settings() {
)
);
- add_settings_field(
- 'gutenberg-customizable-navigation-overlays',
- __( 'Customizable Navigation Overlays', 'gutenberg' ),
- 'gutenberg_display_experiment_field',
- 'gutenberg-experiments',
- 'gutenberg_experiments_section',
- array(
- 'label' => __( 'Enables custom mobile overlay design and content control for Navigation blocks, allowing you to create flexible, professional menu experiences.', 'gutenberg' ),
- 'id' => 'gutenberg-customizable-navigation-overlays',
- )
- );
-
add_settings_field(
'gutenberg-extensible-site-editor',
__( 'Extensible Site Editor', 'gutenberg' ),
diff --git a/lib/load.php b/lib/load.php
index c0ef5891035584..783c3f488a7178 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -200,10 +200,8 @@ function gutenberg_is_experiment_enabled( $name ) {
Gutenberg_Interactivity_API_Full_Page_Navigation::instance();
}
-// Block patterns (only load when navigation overlays experiment is enabled).
-if ( gutenberg_is_experiment_enabled( 'gutenberg-customizable-navigation-overlays' ) ) {
- require __DIR__ . '/experimental/overlay-patterns.php';
-}
+// Block patterns for navigation overlays.
+require __DIR__ . '/overlay-patterns.php';
if ( gutenberg_is_experiment_enabled( 'gutenberg-svg-icon-registry' ) ) {
require __DIR__ . '/experimental/class-wp-icons-registry.php';
diff --git a/lib/experimental/overlay-patterns.php b/lib/overlay-patterns.php
similarity index 92%
rename from lib/experimental/overlay-patterns.php
rename to lib/overlay-patterns.php
index 74e1dad99bbdb0..195999bb2fea8a 100644
--- a/lib/experimental/overlay-patterns.php
+++ b/lib/overlay-patterns.php
@@ -8,23 +8,27 @@
/**
* Registers block patterns for navigation overlays.
*
- * This function adds patterns that are specific to the navigation overlays
- * experiment. It runs after core patterns are registered to ensure all patterns
+ * This function adds patterns that are specific to navigation overlays.
+ * It runs after core patterns are registered to ensure all patterns
* are available.
*
* @since 6.0.0
*/
function gutenberg_register_overlay_block_patterns() {
- register_block_pattern_category(
- 'navigation',
- array(
- 'label' => _x( 'Navigation', 'Block pattern category', 'gutenberg' ),
- 'description' => _x( 'Display your website navigation.', 'Block pattern category', 'gutenberg' ),
- )
- );
+ // Register category only if it doesn't exist in core.
+ $category_registry = WP_Block_Pattern_Categories_Registry::get_instance();
+ if ( ! $category_registry->is_registered( 'navigation' ) ) {
+ register_block_pattern_category(
+ 'navigation',
+ array(
+ 'label' => _x( 'Navigation', 'Block pattern category', 'gutenberg' ),
+ 'description' => _x( 'Display your website navigation.', 'Block pattern category', 'gutenberg' ),
+ )
+ );
+ }
register_block_pattern(
- 'gutenberg/navigation-overlay',
+ 'core/navigation-overlay',
array(
'title' => __( 'Navigation Overlay', 'gutenberg' ),
'description' => _x( 'A simple pattern with a navigation block and a navigation overlay close button.', 'Block pattern description', 'gutenberg' ),
@@ -37,11 +41,12 @@ function gutenberg_register_overlay_block_patterns() {
',
'categories' => array( 'navigation' ),
'blockTypes' => array( 'core/template-part/navigation-overlay' ),
+ 'source' => 'core',
)
);
register_block_pattern(
- 'gutenberg/navigation-overlay-black-bg',
+ 'core/navigation-overlay-black-bg',
array(
'title' => __( 'Overlay with black background', 'gutenberg' ),
'description' => _x( 'A navigation overlay with black background and big white text', 'Block pattern description', 'gutenberg' ),
@@ -54,10 +59,11 @@ function gutenberg_register_overlay_block_patterns() {
',
'categories' => array( 'navigation' ),
'blockTypes' => array( 'core/template-part/navigation-overlay' ),
+ 'source' => 'core',
)
);
register_block_pattern(
- 'gutenberg/navigation-overlay-accent-bg',
+ 'core/navigation-overlay-accent-bg',
array(
'title' => __( 'Overlay with orange background', 'gutenberg' ),
'description' => _x( 'A navigation overlay with orange background site title and tagline', 'Block pattern description', 'gutenberg' ),
@@ -80,10 +86,11 @@ function gutenberg_register_overlay_block_patterns() {
',
'categories' => array( 'navigation' ),
'blockTypes' => array( 'core/template-part/navigation-overlay' ),
+ 'source' => 'core',
)
);
register_block_pattern(
- 'gutenberg/navigation-overlay-centered-with-extras',
+ 'core/navigation-overlay-centered-with-extras',
array(
'title' => __( 'Overlay with site info and CTA', 'gutenberg' ),
'description' => _x( 'A navigation overlay with vertically and horizontally centered navigation, site info, and a CTA', 'Block pattern description', 'gutenberg' ),
@@ -122,10 +129,11 @@ function gutenberg_register_overlay_block_patterns() {
',
'categories' => array( 'navigation' ),
'blockTypes' => array( 'core/template-part/navigation-overlay' ),
+ 'source' => 'core',
)
);
register_block_pattern(
- 'gutenberg/navigation-overlay-centered',
+ 'core/navigation-overlay-centered',
array(
'title' => __( 'Overlay with centered navigation', 'gutenberg' ),
'description' => _x( 'A navigation overlay with vertically and horizontally centered navigation', 'Block pattern description', 'gutenberg' ),
@@ -140,6 +148,7 @@ function gutenberg_register_overlay_block_patterns() {
',
'categories' => array( 'navigation' ),
'blockTypes' => array( 'core/template-part/navigation-overlay' ),
+ 'source' => 'core',
)
);
}
diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js
index 0a5f8a35525eba..3de895cdefa780 100644
--- a/packages/block-library/src/index.js
+++ b/packages/block-library/src/index.js
@@ -266,6 +266,7 @@ const getAllBlocks = () => {
tableOfContents,
homeLink,
logInOut,
+ navigationOverlayClose,
termCount,
termDescription,
termName,
@@ -291,10 +292,6 @@ const getAllBlocks = () => {
blocks.push( formSubmissionNotification );
}
- if ( window?.__experimentalNavigationOverlays ) {
- blocks.push( navigationOverlayClose );
- }
-
if ( window?.__experimentalEnableBlockExperiments ) {
blocks.push( playlist );
blocks.push( playlistTrack );
diff --git a/packages/block-library/src/navigation-overlay-close/block.json b/packages/block-library/src/navigation-overlay-close/block.json
index e08ceff76edebc..39bf2ce75b99a0 100644
--- a/packages/block-library/src/navigation-overlay-close/block.json
+++ b/packages/block-library/src/navigation-overlay-close/block.json
@@ -1,6 +1,5 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
- "__experimental": true,
"apiVersion": 3,
"name": "core/navigation-overlay-close",
"title": "Navigation Overlay Close",
diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js
index c0a05b6a9d3a21..fe74a4eee37780 100644
--- a/packages/block-library/src/navigation/edit/index.js
+++ b/packages/block-library/src/navigation/edit/index.js
@@ -65,8 +65,6 @@ import NavigationMenuDeleteControl from './navigation-menu-delete-control';
import useNavigationNotice from './use-navigation-notice';
import OverlayMenuPreview from './overlay-menu-preview';
import OverlayPanel from './overlay-panel';
-import OverlayVisibilityControl from './overlay-visibility-control';
-import OverlayMenuPreviewButton from './overlay-menu-preview-button';
import useConvertClassicToBlockMenu, {
CLASSIC_MENU_CONVERSION_ERROR,
CLASSIC_MENU_CONVERSION_PENDING,
@@ -340,10 +338,6 @@ function Navigation( {
const blockEditingMode = useBlockEditingMode();
- const isOverlayExperimentEnabled =
- typeof window !== 'undefined' &&
- window.__experimentalNavigationOverlays === true;
-
// Preload classic menus, so that they don't suddenly pop-in when viewing
// the Select Menu dropdown.
const { menus: classicMenus } = useNavigationEntities();
@@ -755,7 +749,7 @@ function Navigation( {
const stylingInspectorControls = (
<>
- { ( ! isOverlayExperimentEnabled || hasSubmenus ) && (
+ { hasSubmenus && (
{
@@ -769,50 +763,6 @@ function Navigation( {
} }
dropdownMenuProps={ dropdownMenuProps }
>
- { ! isOverlayExperimentEnabled && (
- <>
- { isResponsive && (
-
- ) }
-
- overlayMenu !== 'mobile' }
- label={ __( 'Overlay Visibility' ) }
- onDeselect={ () =>
- setAttributes( {
- overlayMenu: 'mobile',
- } )
- }
- isShownByDefault
- >
-
-
- >
- ) }
-
{ hasSubmenus && (
<>
@@ -919,7 +869,7 @@ function Navigation( {
) }
- { isOverlayExperimentEnabled && ! isWithinOverlay && (
+ { ! isWithinOverlay && (
{
} );
mockGetPatternBySlug.mockReturnValue( {
- name: 'gutenberg/navigation-overlay',
+ name: 'core/navigation-overlay',
title: 'Navigation Overlay',
content:
'',
@@ -199,7 +199,7 @@ describe( 'useCreateOverlayTemplatePart', () => {
} );
expect( mockGetPatternBySlug ).toHaveBeenCalledWith(
- 'gutenberg/navigation-overlay'
+ 'core/navigation-overlay'
);
expect( parse ).toHaveBeenCalledWith( mockGetPatternBySlug().content, {
diff --git a/packages/block-library/src/navigation/edit/use-create-overlay.js b/packages/block-library/src/navigation/edit/use-create-overlay.js
index c1cafa778783f3..370bbcbe1c0580 100644
--- a/packages/block-library/src/navigation/edit/use-create-overlay.js
+++ b/packages/block-library/src/navigation/edit/use-create-overlay.js
@@ -27,7 +27,7 @@ export default function useCreateOverlayTemplatePart( overlayTemplateParts ) {
const pattern = useSelect(
( select ) =>
unlock( select( blockEditorStore ) ).getPatternBySlug(
- 'gutenberg/navigation-overlay'
+ 'core/navigation-overlay'
),
[]
);
diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php
index c8c7384208b367..189b3d7cc11b50 100644
--- a/packages/block-library/src/navigation/index.php
+++ b/packages/block-library/src/navigation/index.php
@@ -72,17 +72,6 @@ class WP_Navigation_Block_Renderer {
*/
private static $seen_menu_names = array();
- /**
- * Returns whether the navigation overlay experiment is enabled.
- *
- * @since 6.5.0
- *
- * @return bool Returns whether the navigation overlay experiment is enabled.
- */
- private static function is_overlay_experiment_enabled() {
- $gutenberg_experiments = get_option( 'gutenberg-experiments' );
- return $gutenberg_experiments && array_key_exists( 'gutenberg-customizable-navigation-overlays', $gutenberg_experiments );
- }
/**
* Returns whether or not this is responsive navigation.
@@ -652,7 +641,6 @@ private static function get_responsive_container_classes( $is_hidden_by_default,
}
if ( $has_custom_overlay ) {
- // Only add the disable-default-overlay class if experiment is enabled AND overlay blocks actually rendered.
$responsive_container_classes[] = 'disable-default-overlay';
} else {
// Don't apply overlay color classes if using a custom overlay template part.
@@ -693,39 +681,35 @@ private static function get_responsive_container_markup( $attributes, $inner_blo
$is_hidden_by_default = isset( $attributes['overlayMenu'] ) && 'always' === $attributes['overlayMenu'];
- // Set-up variables for the custom overlay experiment.
- // Values are set to "off" so they don't affect the default behavior.
- $is_overlay_experiment_enabled = static::is_overlay_experiment_enabled();
+ // Set-up variables for custom overlays.
$has_custom_overlay = false;
$close_button_markup = '';
$has_custom_overlay_close_block = false;
$overlay_blocks_html = '';
$custom_overlay_markup = '';
- if ( $is_overlay_experiment_enabled ) {
- // Check if an overlay template part is selected and render it.
- // This needs to happen before building classes so we know if overlay blocks actually exist.
- if ( ! empty( $attributes['overlay'] ) ) {
- // Get blocks from the overlay template part.
- $overlay_blocks = static::get_overlay_blocks_from_template_part( $attributes['overlay'], $attributes );
- // Check if overlay contains a navigation-overlay-close block.
- $has_custom_overlay_close_block = block_core_navigation_block_tree_has_block_type(
- $overlay_blocks,
- 'core/navigation-overlay-close',
- array( 'core/navigation' ) // Skip navigation blocks, as they cannot contain an overlay close block
- );
- // Render template part blocks directly without navigation container wrapper.
- $overlay_blocks_html = static::get_template_part_blocks_html( $overlay_blocks );
- // Add Interactivity API directives to the overlay close block if present.
- if ( $has_custom_overlay_close_block && $is_interactive ) {
- $tags = new WP_HTML_Tag_Processor( $overlay_blocks_html );
- $overlay_blocks_html = block_core_navigation_add_directives_to_overlay_close( $tags );
- }
+ // Check if an overlay template part is selected and render it.
+ // This needs to happen before building classes so we know if overlay blocks actually exist.
+ if ( ! empty( $attributes['overlay'] ) ) {
+ // Get blocks from the overlay template part.
+ $overlay_blocks = static::get_overlay_blocks_from_template_part( $attributes['overlay'], $attributes );
+ // Check if overlay contains a navigation-overlay-close block.
+ $has_custom_overlay_close_block = block_core_navigation_block_tree_has_block_type(
+ $overlay_blocks,
+ 'core/navigation-overlay-close',
+ array( 'core/navigation' ) // Skip navigation blocks, as they cannot contain an overlay close block
+ );
+ // Render template part blocks directly without navigation container wrapper.
+ $overlay_blocks_html = static::get_template_part_blocks_html( $overlay_blocks );
+ // Add Interactivity API directives to the overlay close block if present.
+ if ( $has_custom_overlay_close_block && $is_interactive ) {
+ $tags = new WP_HTML_Tag_Processor( $overlay_blocks_html );
+ $overlay_blocks_html = block_core_navigation_add_directives_to_overlay_close( $tags );
}
-
- $has_custom_overlay = ! empty( $overlay_blocks_html );
}
+ $has_custom_overlay = ! empty( $overlay_blocks_html );
+
$responsive_container_classes = static::get_responsive_container_classes( $is_hidden_by_default, $has_custom_overlay, $colors );
$open_button_classes = array(
diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js
index 53d9e3852416cd..5f16e8f8d6c30a 100644
--- a/packages/block-library/src/template-part/edit/index.js
+++ b/packages/block-library/src/template-part/edit/index.js
@@ -40,22 +40,7 @@ import {
useTemplatePartArea,
} from './utils/hooks';
-const SUPPORTED_AREAS = [ 'header', 'footer' ];
-
-/**
- * Returns the list of supported template part areas for pattern replacement.
- * Includes 'overlay' only if the navigation overlays experiment is enabled.
- *
- * @return {string[]} Array of supported area names.
- */
-function getSupportedAreas() {
- const isOverlayExperimentEnabled =
- typeof window !== 'undefined' &&
- window.__experimentalNavigationOverlays === true;
- return isOverlayExperimentEnabled
- ? [ ...SUPPORTED_AREAS, 'navigation-overlay' ]
- : SUPPORTED_AREAS;
-}
+const SUPPORTED_AREAS = [ 'header', 'footer', 'navigation-overlay' ];
function ReplaceButton( {
isEntityAvailable,
@@ -71,9 +56,10 @@ function ReplaceButton( {
templatePartId
);
const hasReplacements = !! templateParts.length;
- const supportedAreas = getSupportedAreas();
const canReplace =
- isEntityAvailable && hasReplacements && supportedAreas.includes( area );
+ isEntityAvailable &&
+ hasReplacements &&
+ SUPPORTED_AREAS.includes( area );
if ( ! canReplace ) {
return null;
@@ -96,11 +82,10 @@ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) {
// This hook fetches patterns, so don't run it unconditionally in the main
// edit function!
const blockPatterns = useAlternativeBlockPatterns( area, clientId );
- const supportedAreas = getSupportedAreas();
const canReplace =
isEntityAvailable &&
!! blockPatterns.length &&
- supportedAreas.includes( area );
+ SUPPORTED_AREAS.includes( area );
if ( ! canReplace ) {
return null;
diff --git a/test/integration/fixtures/blocks/core__navigation-overlay-close.html b/test/integration/fixtures/blocks/core__navigation-overlay-close.html
new file mode 100644
index 00000000000000..900aed9a53399e
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__navigation-overlay-close.html
@@ -0,0 +1 @@
+
diff --git a/test/integration/fixtures/blocks/core__navigation-overlay-close.json b/test/integration/fixtures/blocks/core__navigation-overlay-close.json
new file mode 100644
index 00000000000000..1dbf1ca196fa14
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__navigation-overlay-close.json
@@ -0,0 +1,10 @@
+[
+ {
+ "name": "core/navigation-overlay-close",
+ "isValid": true,
+ "attributes": {
+ "displayMode": "icon"
+ },
+ "innerBlocks": []
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__navigation-overlay-close.parsed.json b/test/integration/fixtures/blocks/core__navigation-overlay-close.parsed.json
new file mode 100644
index 00000000000000..ae1e322eec96b7
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__navigation-overlay-close.parsed.json
@@ -0,0 +1,9 @@
+[
+ {
+ "blockName": "core/navigation-overlay-close",
+ "attrs": {},
+ "innerBlocks": [],
+ "innerHTML": "",
+ "innerContent": []
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__navigation-overlay-close.serialized.html b/test/integration/fixtures/blocks/core__navigation-overlay-close.serialized.html
new file mode 100644
index 00000000000000..900aed9a53399e
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__navigation-overlay-close.serialized.html
@@ -0,0 +1 @@
+