diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 69fd34d709bdc..1a2094cce578e 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -2,6 +2,9 @@
https://github.com/WordPress/gutenberg/blob/trunk/CONTRIBUTING.md -->
## What?
+
+Closes
+
## Why?
diff --git a/backport-changelog/6.8/8212.md b/backport-changelog/6.8/8212.md
new file mode 100644
index 0000000000000..a4488d2da99f2
--- /dev/null
+++ b/backport-changelog/6.8/8212.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/8212
+
+* https://github.com/WordPress/gutenberg/pull/68926
diff --git a/bin/generate-php-sync-issue.mjs b/bin/generate-php-sync-issue.mjs
index bd627aeb65107..9ea79c4f165e9 100644
--- a/bin/generate-php-sync-issue.mjs
+++ b/bin/generate-php-sync-issue.mjs
@@ -156,17 +156,6 @@ async function main() {
fs.writeFileSync( nodePath.join( __dirname, 'issueContent.md' ), content );
}
-/**
- * Checks if the first date is after the second date.
- *
- * @param {string} date1 - The first date.
- * @param {string} date2 - The second date.
- * @return {boolean} - Returns true if the first date is after the second date, false otherwise.
- */
-function isAfter( date1, date2 ) {
- return new Date( date1 ) > new Date( date2 );
-}
-
function validateDate( sinceArg ) {
const sinceDate = new Date( sinceArg );
const maxPreviousDate = new Date();
diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md
index db5dcb6289aff..7ac8591cd1931 100644
--- a/docs/reference-guides/core-blocks.md
+++ b/docs/reference-guides/core-blocks.md
@@ -78,7 +78,7 @@ Display a list of all terms of a given taxonomy. ([Source](https://github.com/Wo
- **Name:** core/categories
- **Category:** widgets
-- **Supports:** align, interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
+- **Supports:** align, color (background, gradients, link, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~
- **Attributes:** displayAsDropdown, label, showEmpty, showHierarchy, showLabel, showOnlyTopLevel, showPostCounts, taxonomy
## Code
diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php
index 6cfa98691020e..90be78cd1457f 100644
--- a/lib/compat/wordpress-6.8/blocks.php
+++ b/lib/compat/wordpress-6.8/blocks.php
@@ -5,14 +5,79 @@
* @package gutenberg
*/
-function gutenberg_apply_block_hooks_to_post_content( $content ) {
- // The `the_content` filter does not provide the post that the content is coming from.
- // However, we can infer it by calling `get_post()`, which will return the current post
- // if no post ID is provided.
- return apply_block_hooks_to_content( $content, get_post(), 'insert_hooked_blocks' );
+if ( ! function_exists( 'apply_block_hooks_to_content_from_post_object' ) ) {
+ /**
+ * Run the Block Hooks algorithm on a post object's content.
+ *
+ * This function is different from `apply_block_hooks_to_content` in that
+ * it takes ignored hooked block information from the post's metadata into
+ * account. This ensures that any blocks hooked as first or last child
+ * of the block that corresponds to the post type are handled correctly.
+ *
+ * @since 6.8.0
+ * @access private
+ *
+ * @param string $content Serialized content.
+ * @param WP_Post|null $post A post object that the content belongs to. If set to `null`,
+ * `get_post()` will be called to use the current post as context.
+ * Default: `null`.
+ * @param callable $callback A function that will be called for each block to generate
+ * the markup for a given list of blocks that are hooked to it.
+ * Default: 'insert_hooked_blocks'.
+ * @return string The serialized markup.
+ */
+ function apply_block_hooks_to_content_from_post_object( $content, WP_Post $post = null, $callback = 'insert_hooked_blocks' ) {
+ // Default to the current post if no context is provided.
+ if ( null === $post ) {
+ $post = get_post();
+ }
+
+ if ( ! $post instanceof WP_Post ) {
+ return apply_block_hooks_to_content( $content, $post, $callback );
+ }
+
+ $attributes = array();
+
+ // If context is a post object, `ignoredHookedBlocks` information is stored in its post meta.
+ $ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
+ if ( ! empty( $ignored_hooked_blocks ) ) {
+ $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
+ $attributes['metadata'] = array(
+ 'ignoredHookedBlocks' => $ignored_hooked_blocks,
+ );
+ }
+
+ // We need to wrap the content in a temporary wrapper block with that metadata
+ // so the Block Hooks algorithm can insert blocks that are hooked as first or last child
+ // of the wrapper block.
+ // To that end, we need to determine the wrapper block type based on the post type.
+ if ( 'wp_navigation' === $post->post_type ) {
+ $wrapper_block_type = 'core/navigation';
+ } elseif ( 'wp_block' === $post->post_type ) {
+ $wrapper_block_type = 'core/block';
+ } else {
+ $wrapper_block_type = 'core/post-content';
+ }
+
+ $content = get_comment_delimited_block_content(
+ $wrapper_block_type,
+ $attributes,
+ $content
+ );
+
+ // Apply Block Hooks.
+ $content = apply_block_hooks_to_content( $content, $post, $callback );
+
+ // Finally, we need to remove the temporary wrapper block.
+ $content = remove_serialized_parent_block( $content );
+
+ return $content;
+ }
+ // We need to apply this filter before `do_blocks` (which is hooked to `the_content` at priority 9).
+ add_filter( 'the_content', 'apply_block_hooks_to_content_from_post_object', 8 );
+ // Remove apply_block_hooks_to_content filter (previously added in Core).
+ remove_filter( 'the_content', 'apply_block_hooks_to_content', 8 );
}
-// We need to apply this filter before `do_blocks` (which is hooked to `the_content` at priority 9).
-add_filter( 'the_content', 'gutenberg_apply_block_hooks_to_post_content', 8 );
/**
* Hooks into the REST API response for the Posts endpoint and adds the first and last inner blocks.
@@ -29,57 +94,32 @@ function gutenberg_insert_hooked_blocks_into_rest_response( $response, $post ) {
return $response;
}
- $attributes = array();
- $ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
- if ( ! empty( $ignored_hooked_blocks ) ) {
- $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
- $attributes['metadata'] = array(
- 'ignoredHookedBlocks' => $ignored_hooked_blocks,
- );
- }
-
- if ( 'wp_navigation' === $post->post_type ) {
- $wrapper_block_type = 'core/navigation';
- } elseif ( 'wp_block' === $post->post_type ) {
- $wrapper_block_type = 'core/block';
- } else {
- $wrapper_block_type = 'core/post-content';
- }
-
- $content = get_comment_delimited_block_content(
- $wrapper_block_type,
- $attributes,
- $response->data['content']['raw']
- );
-
- $content = apply_block_hooks_to_content(
- $content,
+ $response->data['content']['raw'] = apply_block_hooks_to_content_from_post_object(
+ $response->data['content']['raw'],
$post,
'insert_hooked_blocks_and_set_ignored_hooked_blocks_metadata'
);
- // Remove mock block wrapper.
- $content = remove_serialized_parent_block( $content );
-
- $response->data['content']['raw'] = $content;
-
// If the rendered content was previously empty, we leave it like that.
if ( empty( $response->data['content']['rendered'] ) ) {
return $response;
}
// No need to inject hooked blocks twice.
- $priority = has_filter( 'the_content', 'apply_block_hooks_to_content' );
+ $priority = has_filter( 'the_content', 'apply_block_hooks_to_content_from_post_object' );
if ( false !== $priority ) {
- remove_filter( 'the_content', 'apply_block_hooks_to_content', $priority );
+ remove_filter( 'the_content', 'apply_block_hooks_to_content_from_post_object', $priority );
}
/** This filter is documented in wp-includes/post-template.php */
- $response->data['content']['rendered'] = apply_filters( 'the_content', $content );
+ $response->data['content']['rendered'] = apply_filters(
+ 'the_content',
+ $response->data['content']['raw']
+ );
// Add back the filter.
if ( false !== $priority ) {
- add_filter( 'the_content', 'apply_block_hooks_to_content', $priority );
+ add_filter( 'the_content', 'apply_block_hooks_to_content_from_post_object', $priority );
}
return $response;
diff --git a/package.json b/package.json
index 7d09fb4c22c35..b5fd51d6edd49 100644
--- a/package.json
+++ b/package.json
@@ -181,7 +181,7 @@
"build": "npm run build:packages && wp-scripts build",
"build:analyze-bundles": "npm run build -- --webpack-bundle-analyzer",
"build:package-types": "node ./bin/packages/validate-typescript-version.js && ( tsc --build || ( echo 'tsc failed. Try cleaning up first: `npm run clean:package-types`'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js",
- "build:profile-types": "rimraf ./ts-traces && npm run clean:package-types && node ./bin/packages/validate-typescript-version.js && ( tsc --build --extendedDiagnostics --generateTrace ./ts-traces || ( echo 'tsc failed.'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js && npx --yes @typescript/analyze-trace ts-traces > ts-traces/analysis.txt && echo $'\n\nDone! Build traces saved to ts-traces/ directory.\nTrace analysis saved to ts-traces/analysis.txt.'",
+ "build:profile-types": "rimraf ./ts-traces && npm run clean:package-types && node ./bin/packages/validate-typescript-version.js && ( tsc --build --extendedDiagnostics --generateTrace ./ts-traces || ( echo 'tsc failed.'; exit 1 ) ) && node ./bin/packages/check-build-type-declaration-files.js && npx --yes @typescript/analyze-trace ts-traces > ts-traces/analysis.txt && node -p \"'\\n\\nDone! Build traces saved to ts-traces/ directory.\\nTrace analysis saved to ts-traces/analysis.txt.'\"",
"prebuild:packages": "npm run clean:packages && npm run --if-present --workspaces build",
"build:packages": "npm run --silent build:package-types && node ./bin/packages/build.js",
"postbuild:packages": " npm run --if-present --workspaces build:wp",
diff --git a/packages/block-editor/src/components/block-canvas/style.scss b/packages/block-editor/src/components/block-canvas/style.scss
index ea54646e64a59..c6688f5f387e0 100644
--- a/packages/block-editor/src/components/block-canvas/style.scss
+++ b/packages/block-editor/src/components/block-canvas/style.scss
@@ -4,7 +4,8 @@ iframe[name="editor-canvas"] {
height: 100%;
display: block;
// Handles transitions between device previews
- transition: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96);
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: all 400ms cubic-bezier(0.46, 0.03, 0.52, 0.96);
+ }
background-color: $gray-300;
}
diff --git a/packages/block-editor/src/components/block-draggable/style.scss b/packages/block-editor/src/components/block-draggable/style.scss
index f716f2d32a1d4..f420251510ac6 100644
--- a/packages/block-editor/src/components/block-draggable/style.scss
+++ b/packages/block-editor/src/components/block-draggable/style.scss
@@ -59,7 +59,9 @@
justify-content: center;
align-items: center;
background-color: transparent;
- transition: all 0.1s linear 0.1s;
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.1s linear 0.1s;
+ }
.block-editor-block-draggable-chip__disabled-icon {
width: $grid-unit-50 * 0.5;
diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss
index cd517fced833e..b39e9b144bbc9 100644
--- a/packages/block-editor/src/components/block-list/content.scss
+++ b/packages/block-editor/src/components/block-list/content.scss
@@ -58,10 +58,12 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
background: var(--wp-admin-theme-color);
opacity: 0.4;
- // Animate.
- animation: selection-overlay__fade-in-animation 0.1s ease-out;
- animation-fill-mode: forwards;
- @include reduce-motion("animation");
+ @media not ( prefers-reduced-motion ) {
+
+ // Animate.
+ animation: selection-overlay__fade-in-animation 0.1s ease-out;
+ animation-fill-mode: forwards;
+ }
// Show outline in high contrast mode.
outline: 2px solid transparent;
@@ -271,8 +273,9 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
// Spotlight mode. Fade out blocks unless they contain a selected block.
.is-focus-mode .block-editor-block-list__block:not(.has-child-selected) {
opacity: 0.2;
- transition: opacity 0.1s linear;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: opacity 0.1s linear;
+ }
// Nested blocks should never be faded. If the parent block is already faded
// out, it shouldn't be faded out more. If the parent block in not faded
@@ -339,9 +342,10 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
// Hide the appender that sits at the end of block lists, when inside a nested block,
// unless the block itself, or a parent, is selected.
.wp-block .block-list-appender .block-editor-inserter__toggle {
- animation: block-editor-inserter__toggle__fade-in-animation 0.1s ease;
- animation-fill-mode: forwards;
- @include reduce-motion("animation");
+ @media not ( prefers-reduced-motion ) {
+ animation: block-editor-inserter__toggle__fade-in-animation 0.1s ease;
+ animation-fill-mode: forwards;
+ }
}
.block-editor-block-list__block:not(.is-selected):not(.has-child-selected) .block-editor-default-block-appender {
@@ -367,8 +371,9 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
font-family: $editor-html-font;
font-size: $text-editor-font-size;
line-height: 1.5;
- transition: padding 0.2s linear;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: padding 0.2s linear;
+ }
&:focus {
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
@@ -400,7 +405,9 @@ _::-webkit-full-page-media, _:future, :root [data-has-multi-selection="true"] .b
// Additional -1px is required to avoid sub pixel rounding errors allowing background to show.
margin-left: -1px;
margin-right: -1px;
- transition: background-color 0.3s ease;
+ @media not ( prefers-reduced-motion ) {
+ transition: background-color 0.3s ease;
+ }
display: flex;
align-items: center;
justify-content: center;
diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js
index bcf6783a10d1c..d3a2f0ae0795c 100644
--- a/packages/block-editor/src/components/block-list/index.js
+++ b/packages/block-editor/src/components/block-list/index.js
@@ -19,6 +19,7 @@ import {
useCallback,
useEffect,
} from '@wordpress/element';
+import { getDefaultBlockName } from '@wordpress/blocks';
/**
* Internal dependencies
@@ -171,13 +172,13 @@ function Items( {
const {
getSettings,
getBlockOrder,
- getSelectedBlockClientId,
getSelectedBlockClientIds,
__unstableGetVisibleBlocks,
getTemplateLock,
getBlockEditingMode,
isSectionBlock,
isZoomOut: _isZoomOut,
+ canInsertBlockType,
} = unlock( select( blockEditorStore ) );
const _order = getBlockOrder( rootClientId );
@@ -190,10 +191,20 @@ function Items( {
};
}
- const selectedBlockClientId = getSelectedBlockClientId();
+ const selectedBlockClientIds = getSelectedBlockClientIds();
+ const selectedBlockClientId = selectedBlockClientIds[ 0 ];
+ const showRootAppender =
+ ! rootClientId &&
+ ! selectedBlockClientId &&
+ ( ! _order.length ||
+ ! canInsertBlockType(
+ getDefaultBlockName(),
+ rootClientId
+ ) );
+
return {
order: _order,
- selectedBlocks: getSelectedBlockClientIds(),
+ selectedBlocks: selectedBlockClientIds,
visibleBlocks: __unstableGetVisibleBlocks(),
isZoomOut: _isZoomOut(),
shouldRenderAppender:
@@ -203,10 +214,8 @@ function Items( {
hasAppender &&
! _isZoomOut() &&
( hasCustomAppender ||
- rootClientId === selectedBlockClientId ||
- ( ! rootClientId &&
- ! selectedBlockClientId &&
- ! _order.length ) ),
+ showRootAppender ||
+ rootClientId === selectedBlockClientId ),
};
},
[ rootClientId, hasAppender, hasCustomAppender ]
diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss
index 7d23c0f1e5a98..2560fe59de4fa 100644
--- a/packages/block-editor/src/components/block-mover/style.scss
+++ b/packages/block-editor/src/components/block-mover/style.scss
@@ -87,10 +87,11 @@
right: $grid-unit-10;
z-index: -1;
- // Animate in.
- animation: components-button__appear-animation 0.1s ease;
- animation-fill-mode: forwards;
- @include reduce-motion("animation");
+ @media not ( prefers-reduced-motion ) {
+ // Animate in.
+ animation: components-button__appear-animation 0.1s ease;
+ animation-fill-mode: forwards;
+ }
}
// Don't show the focus inherited by the Button component.
diff --git a/packages/block-editor/src/components/block-pattern-setup/style.scss b/packages/block-editor/src/components/block-pattern-setup/style.scss
index 10582a7a2ce49..98537f9cb9b7d 100644
--- a/packages/block-editor/src/components/block-pattern-setup/style.scss
+++ b/packages/block-editor/src/components/block-pattern-setup/style.scss
@@ -130,7 +130,9 @@
background-color: $white;
margin: auto;
padding: 0;
- transition: transform 0.5s, z-index 0.5s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.5s, z-index 0.5s;
+ }
z-index: z-index(".block-editor-block-pattern-setup .pattern-slide");
&.active-slide {
diff --git a/packages/block-editor/src/components/block-patterns-list/style.scss b/packages/block-editor/src/components/block-patterns-list/style.scss
index 8b1b0b54c9b1a..fcf1a23c0b7ca 100644
--- a/packages/block-editor/src/components/block-patterns-list/style.scss
+++ b/packages/block-editor/src/components/block-patterns-list/style.scss
@@ -44,9 +44,9 @@
outline: $border-width solid rgba($black, 0.1);
outline-offset: -$border-width;
border-radius: $radius-medium;
-
- transition: outline 0.1s linear;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: outline 0.1s linear;
+ }
}
}
diff --git a/packages/block-editor/src/components/block-popover/use-popover-scroll.js b/packages/block-editor/src/components/block-popover/use-popover-scroll.js
index 8aeb768e302f6..97bc4c5b29937 100644
--- a/packages/block-editor/src/components/block-popover/use-popover-scroll.js
+++ b/packages/block-editor/src/components/block-popover/use-popover-scroll.js
@@ -2,24 +2,29 @@
* WordPress dependencies
*/
import { useRefEffect } from '@wordpress/compose';
+import { getScrollContainer } from '@wordpress/dom';
+
+const scrollContainerCache = new WeakMap();
/**
* Allow scrolling "through" popovers over the canvas. This is only called for
* as long as the pointer is over a popover. Do not use React events because it
* will bubble through portals.
*
- * @param {Object} scrollableRef
+ * @param {Object} contentRef
*/
-function usePopoverScroll( scrollableRef ) {
+function usePopoverScroll( contentRef ) {
return useRefEffect(
( node ) => {
- if ( ! scrollableRef ) {
- return;
- }
-
function onWheel( event ) {
const { deltaX, deltaY } = event;
- scrollableRef.current.scrollBy( deltaX, deltaY );
+ const contentEl = contentRef.current;
+ let scrollContainer = scrollContainerCache.get( contentEl );
+ if ( ! scrollContainer ) {
+ scrollContainer = getScrollContainer( contentEl );
+ scrollContainerCache.set( contentEl, scrollContainer );
+ }
+ scrollContainer.scrollBy( deltaX, deltaY );
}
// Tell the browser that we do not call event.preventDefault
// See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
@@ -29,7 +34,7 @@ function usePopoverScroll( scrollableRef ) {
node.removeEventListener( 'wheel', onWheel, options );
};
},
- [ scrollableRef ]
+ [ contentRef ]
);
}
diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss
index 62a7bebe95d27..2762308eec961 100644
--- a/packages/block-editor/src/components/block-switcher/style.scss
+++ b/packages/block-editor/src/components/block-switcher/style.scss
@@ -129,7 +129,9 @@
.block-editor-block-switcher__preview-patterns-container-list__item {
height: 100%;
border-radius: $radius-small;
- transition: all 0.05s ease-in-out;
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.05s ease-in-out;
+ }
position: relative;
border: $border-width solid transparent;
diff --git a/packages/block-editor/src/components/block-toolbar/style.scss b/packages/block-editor/src/components/block-toolbar/style.scss
index 26bf71356925e..2a3543f5ec797 100644
--- a/packages/block-editor/src/components/block-toolbar/style.scss
+++ b/packages/block-editor/src/components/block-toolbar/style.scss
@@ -12,9 +12,11 @@
overflow-y: hidden;
overflow-x: auto;
- // Animation
- transition: border-color 0.1s linear, box-shadow 0.1s linear;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+
+ // Animation
+ transition: border-color 0.1s linear, box-shadow 0.1s linear;
+ }
@include break-small() {
overflow: inherit;
diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js
index c6378130b7da4..0724928cfeacb 100644
--- a/packages/block-editor/src/components/block-tools/block-toolbar-popover.js
+++ b/packages/block-editor/src/components/block-tools/block-toolbar-popover.js
@@ -11,7 +11,7 @@ import { useShortcut } from '@wordpress/keyboard-shortcuts';
/**
* Internal dependencies
*/
-import BlockPopover from '../block-popover';
+import { PrivateBlockPopover } from '../block-popover';
import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props';
import useSelectedBlockToolProps from './use-selected-block-tool-props';
import { store as blockEditorStore } from '../../store';
@@ -58,7 +58,7 @@ export default function BlockToolbarPopover( {
return (
! isTyping && (
-
-
+
)
);
}
diff --git a/packages/block-editor/src/components/block-tools/style.scss b/packages/block-editor/src/components/block-tools/style.scss
index 35d075c1a99b7..35d0f99c827b6 100644
--- a/packages/block-editor/src/components/block-tools/style.scss
+++ b/packages/block-editor/src/components/block-tools/style.scss
@@ -191,9 +191,12 @@
.is-dragging-components-draggable & {
opacity: 0;
- // Use a minimal duration to delay hiding the element, see hide-during-dragging animation for more details.
- // It's essential to hide the toolbar/popover so that `dragEnter` events can pass through them to the underlying elements.
- animation: hide-during-dragging 1ms linear forwards;
+ @media not ( prefers-reduced-motion ) {
+
+ // Use a minimal duration to delay hiding the element, see hide-during-dragging animation for more details.
+ // It's essential to hide the toolbar/popover so that `dragEnter` events can pass through them to the underlying elements.
+ animation: hide-during-dragging 1ms linear forwards;
+ }
}
.block-editor-block-parent-selector {
diff --git a/packages/block-editor/src/components/button-block-appender/content.scss b/packages/block-editor/src/components/button-block-appender/content.scss
index f5486d3f6f608..dd6f092483567 100644
--- a/packages/block-editor/src/components/button-block-appender/content.scss
+++ b/packages/block-editor/src/components/button-block-appender/content.scss
@@ -79,10 +79,8 @@
background-color: var(--wp-admin-theme-color);
box-shadow: inset 0 0 0 $border-width $light-gray-placeholder;
color: $light-gray-placeholder;
- transition: background-color 0.2s ease-in-out;
-
- @media ( prefers-reduced-motion: reduce ) {
- transition: none;
+ @media not ( prefers-reduced-motion ) {
+ transition: background-color 0.2s ease-in-out;
}
}
}
diff --git a/packages/block-editor/src/components/colors-gradients/style.scss b/packages/block-editor/src/components/colors-gradients/style.scss
index 661318e558241..6a882c4b1883c 100644
--- a/packages/block-editor/src/components/colors-gradients/style.scss
+++ b/packages/block-editor/src/components/colors-gradients/style.scss
@@ -129,8 +129,9 @@ $swatch-gap: 12px;
top: $grid-unit;
margin: auto $grid-unit auto;
opacity: 0;
- transition: opacity 0.1s ease-in-out;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: opacity 0.1s ease-in-out;
+ }
&.block-editor-panel-color-gradient-settings__reset {
border-radius: $radius-small;
diff --git a/packages/block-editor/src/components/global-styles/style.scss b/packages/block-editor/src/components/global-styles/style.scss
index e0782fdb01b1d..c51ffa3116d9f 100644
--- a/packages/block-editor/src/components/global-styles/style.scss
+++ b/packages/block-editor/src/components/global-styles/style.scss
@@ -53,7 +53,9 @@
box-sizing: border-box;
transform: scale(1);
- transition: transform 0.1s ease;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.1s ease;
+ }
will-change: transform;
&:focus {
diff --git a/packages/block-editor/src/components/grid/style.scss b/packages/block-editor/src/components/grid/style.scss
index e6d9e65d6db9e..ab36ed12984bd 100644
--- a/packages/block-editor/src/components/grid/style.scss
+++ b/packages/block-editor/src/components/grid/style.scss
@@ -126,10 +126,11 @@
right: $grid-unit-10;
z-index: -1;
- // Animate in.
- animation: components-button__appear-animation 0.1s ease;
- animation-fill-mode: forwards;
- @include reduce-motion("animation");
+ @media not ( prefers-reduced-motion ) {
+ // Animate in.
+ animation: components-button__appear-animation 0.1s ease;
+ animation-fill-mode: forwards;
+ }
}
// Don't show the focus inherited by the Button component.
diff --git a/packages/block-editor/src/components/iframe/content.scss b/packages/block-editor/src/components/iframe/content.scss
index 05bbdb25c2dc6..8a85ea186b2e6 100644
--- a/packages/block-editor/src/components/iframe/content.scss
+++ b/packages/block-editor/src/components/iframe/content.scss
@@ -4,8 +4,11 @@
.block-editor-iframe__html {
transform-origin: top center;
- // Prevents a flash of background color change when entering/exiting zoom out
- transition: background-color 400ms;
+
+ @media not ( prefers-reduced-motion ) {
+ // Prevents a flash of background color change when entering/exiting zoom out
+ transition: background-color 400ms;
+ }
&.zoom-out-animation {
$scroll-top: var(--wp-block-editor-iframe-zoom-out-scroll-top, 0);
diff --git a/packages/block-editor/src/components/inserter-list-item/style.scss b/packages/block-editor/src/components/inserter-list-item/style.scss
index 435f60ed9e2f1..68d4059340f5c 100644
--- a/packages/block-editor/src/components/inserter-list-item/style.scss
+++ b/packages/block-editor/src/components/inserter-list-item/style.scss
@@ -43,8 +43,9 @@
cursor: pointer;
background: transparent;
word-break: break-word;
- transition: all 0.05s ease-in-out;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.05s ease-in-out;
+ }
position: relative;
height: auto;
@@ -97,8 +98,9 @@
.block-editor-block-types-list__item-icon {
padding: 12px 20px;
color: $gray-900;
- transition: all 0.05s ease-in-out;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.05s ease-in-out;
+ }
.block-editor-block-icon {
margin-left: auto;
@@ -106,8 +108,9 @@
}
svg {
- transition: all 0.15s ease-out;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.15s ease-out;
+ }
}
.block-editor-block-types-list__list-item[draggable="true"] & {
diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss
index c6522671f938d..fe0893b0619a7 100644
--- a/packages/block-editor/src/components/inserter/style.scss
+++ b/packages/block-editor/src/components/inserter/style.scss
@@ -83,8 +83,9 @@ $block-inserter-tabs-height: 44px;
border: none;
outline: none;
padding: 0;
- transition: color 0.2s ease;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: color 0.2s ease;
+ }
}
.block-editor-inserter__menu {
@@ -563,8 +564,9 @@ $block-inserter-tabs-height: 44px;
outline-color: var(--wp-admin-theme-color);
outline-width: var(--wp-admin-border-width-focus);
outline-offset: calc((-1 * var(--wp-admin-border-width-focus)));
- transition: outline 0.1s linear;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: outline 0.1s linear;
+ }
}
}
diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss
index 16493e1a5aa7f..c10135f8e441a 100644
--- a/packages/block-editor/src/components/link-control/style.scss
+++ b/packages/block-editor/src/components/link-control/style.scss
@@ -289,8 +289,10 @@ $block-editor-link-control-number-of-actions: 1;
right: 0;
bottom: 0;
border-radius: 100%;
- animation: loadingpulse 1s linear infinite;
- animation-delay: 0.5s; // avoid animating for fast network responses
+ @media not ( prefers-reduced-motion ) {
+ animation: loadingpulse 1s linear infinite;
+ animation-delay: 0.5s; // avoid animating for fast network responses
+ }
}
}
}
@@ -381,16 +383,19 @@ $block-editor-link-control-number-of-actions: 1;
// Point downwards when open (same as list view expander)
&[aria-expanded="true"] svg {
visibility: visible;
- transition: transform 0.1s ease;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.1s ease;
+ }
transform: rotate(90deg);
- @include reduce-motion("transition");
+
}
// Point rightwards when closed (same as list view expander)
&[aria-expanded="false"] svg {
visibility: visible;
transform: rotate(0deg);
- transition: transform 0.1s ease;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.1s ease;
+ }
}
}
}
diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss
index 138029262cd7f..bc68cb2663790 100644
--- a/packages/block-editor/src/components/list-view/style.scss
+++ b/packages/block-editor/src/components/list-view/style.scss
@@ -158,21 +158,27 @@
// without attaching the transition to the list view leaf itself. This prevents rows
// from animating too much once the user has dropped the block.
&.is-displacement-normal {
- transition: transform 0.2s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform: translateY(0);
- @include reduce-motion("transition");
+
}
&.is-displacement-up {
- transition: transform 0.2s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform: translateY(-32px);
- @include reduce-motion("transition");
+
}
&.is-displacement-down {
- transition: transform 0.2s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform: translateY(32px);
- @include reduce-motion("transition");
+
}
// Collapse multi-selections down into a single row space while dragging. The following
@@ -180,23 +186,30 @@
// when displacing up and down. The result is that there should only ever be a single row's
// worth of space for the visual indicator of where a block will be placed when dropped.
&.is-after-dragged-blocks {
- transition: transform 0.2s;
+
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform: translateY(calc(var(--wp-admin--list-view-dragged-items-height, 32px) * -1));
- @include reduce-motion("transition");
+
}
&.is-after-dragged-blocks.is-displacement-up {
- transition: transform 0.2s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform: translateY(calc(-32px + var(--wp-admin--list-view-dragged-items-height, 32px) * -1));
- @include reduce-motion("transition");
+
}
&.is-after-dragged-blocks.is-displacement-down {
- transition: transform 0.2s;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s;
+ }
transform:
translateY(calc(32px + var(--wp-admin--list-view-dragged-items-height, 32px) *
-1));
- @include reduce-motion("transition");
+
}
// To ensure displaced rows behave correctly, ensure that blocks that are currently being dragged
@@ -233,7 +246,9 @@
font-weight: 400;
margin: 0;
text-decoration: none;
- transition: box-shadow 0.1s linear;
+ @media not ( prefers-reduced-motion ) {
+ transition: box-shadow 0.1s linear;
+ }
.components-modal__content & {
padding-left: 0;
@@ -496,9 +511,10 @@ $block-navigation-max-indent: 8;
.block-editor-list-view__expander
svg {
visibility: visible;
- transition: transform 0.2s ease;
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s ease;
+ }
transform: rotate(90deg);
- @include reduce-motion("transition");
}
// Point rightwards when closed
@@ -507,8 +523,9 @@ svg {
svg {
visibility: visible;
transform: rotate(0deg);
- transition: transform 0.2s ease;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: transform 0.2s ease;
+ }
}
.block-editor-list-view-drop-indicator {
diff --git a/packages/block-editor/src/components/url-input/style.scss b/packages/block-editor/src/components/url-input/style.scss
index ef37566f8e34e..579b311766299 100644
--- a/packages/block-editor/src/components/url-input/style.scss
+++ b/packages/block-editor/src/components/url-input/style.scss
@@ -33,8 +33,9 @@ $input-size: 300px;
// Suggestions
.block-editor-url-input__suggestions {
max-height: 200px;
- transition: all 0.15s ease-in-out;
- @include reduce-motion("transition");
+ @media not ( prefers-reduced-motion ) {
+ transition: all 0.15s ease-in-out;
+ }
padding: 4px 0;
// To match the url-input width: input width + padding + 2 buttons.
width: $input-size + 2;
diff --git a/packages/block-library/src/block/index.php b/packages/block-library/src/block/index.php
index e8075115cabda..94df5d5df6c07 100644
--- a/packages/block-library/src/block/index.php
+++ b/packages/block-library/src/block/index.php
@@ -87,25 +87,8 @@ function render_block_core_block( $attributes ) {
add_filter( 'render_block_context', $filter_block_context, 1 );
}
- $ignored_hooked_blocks = get_post_meta( $attributes['ref'], '_wp_ignored_hooked_blocks', true );
- if ( ! empty( $ignored_hooked_blocks ) ) {
- $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
- $attributes['metadata'] = array(
- 'ignoredHookedBlocks' => $ignored_hooked_blocks,
- );
- }
-
- // Wrap in "Block" block so the Block Hooks algorithm can insert blocks
- // that are hooked as first or last child of `core/block`.
- $content = get_comment_delimited_block_content(
- 'core/block',
- $attributes,
- $content
- );
// Apply Block Hooks.
- $content = apply_block_hooks_to_content( $content, $reusable_block );
- // Remove block wrapper.
- $content = remove_serialized_parent_block( $content );
+ $content = apply_block_hooks_to_content_from_post_object( $content, $reusable_block );
$content = do_blocks( $content );
unset( $seen_refs[ $attributes['ref'] ] );
diff --git a/packages/block-library/src/categories/block.json b/packages/block-library/src/categories/block.json
index 3609bdf9ab97c..8320fa912a175 100644
--- a/packages/block-library/src/categories/block.json
+++ b/packages/block-library/src/categories/block.json
@@ -66,6 +66,15 @@
"fontSize": true
}
},
+ "color": {
+ "gradients": true,
+ "link": true,
+ "__experimentalDefaultControls": {
+ "background": true,
+ "text": true,
+ "link": true
+ }
+ },
"interactivity": {
"clientNavigation": true
},
diff --git a/packages/block-library/src/navigation-link/editor.scss b/packages/block-library/src/navigation-link/editor.scss
index c48af79385c47..b27c4520921fd 100644
--- a/packages/block-library/src/navigation-link/editor.scss
+++ b/packages/block-library/src/navigation-link/editor.scss
@@ -104,7 +104,7 @@
&.is-invalid,
&.is-draft {
span {
- --wp-underline-color: var(--wp--preset--color--vivid-red);
+ --wp-underline-color: #{$alert-red};
}
}
}
diff --git a/packages/block-library/src/navigation/index.php b/packages/block-library/src/navigation/index.php
index 43ca833153427..d52b67b7e1958 100644
--- a/packages/block-library/src/navigation/index.php
+++ b/packages/block-library/src/navigation/index.php
@@ -241,11 +241,12 @@ private static function get_inner_blocks_from_navigation_post( $attributes ) {
// it encounters whitespace. This code strips it.
$blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
- // Run Block Hooks algorithm to inject hooked blocks.
- $markup = block_core_navigation_insert_hooked_blocks( $blocks, $navigation_post );
- $root_nav_block = parse_blocks( $markup )[0];
-
- $blocks = isset( $root_nav_block['innerBlocks'] ) ? $root_nav_block['innerBlocks'] : $blocks;
+ // Re-serialize, and run Block Hooks algorithm to inject hooked blocks.
+ // TODO: See if we can move the apply_block_hooks_to_content_from_post_object() call
+ // before the parse_blocks() call further above, to avoid the extra serialization/parsing.
+ $markup = serialize_blocks( $blocks );
+ $markup = apply_block_hooks_to_content_from_post_object( $markup, $navigation_post );
+ $blocks = parse_blocks( $markup );
// TODO - this uses the full navigation block attributes for the
// context which could be refined.
@@ -1077,12 +1078,11 @@ function block_core_navigation_get_fallback_blocks() {
// Run Block Hooks algorithm to inject hooked blocks.
// We have to run it here because we need the post ID of the Navigation block to track ignored hooked blocks.
- $markup = block_core_navigation_insert_hooked_blocks( $fallback_blocks, $navigation_post );
- $blocks = parse_blocks( $markup );
-
- if ( isset( $blocks[0]['innerBlocks'] ) ) {
- $fallback_blocks = $blocks[0]['innerBlocks'];
- }
+ // TODO: See if we can move the apply_block_hooks_to_content_from_post_object() call
+ // before the parse_blocks() call further above, to avoid the extra serialization/parsing.
+ $markup = serialize_blocks( $fallback_blocks );
+ $markup = apply_block_hooks_to_content_from_post_object( $markup, $navigation_post );
+ $fallback_blocks = parse_blocks( $markup );
}
/**
@@ -1436,61 +1436,3 @@ function block_core_navigation_get_most_recently_published_navigation() {
return null;
}
-
-/**
- * Mock a parsed block for the Navigation block given its inner blocks and the `wp_navigation` post object.
- * The `wp_navigation` post's `_wp_ignored_hooked_blocks` meta is queried to add the `metadata.ignoredHookedBlocks` attribute.
- *
- * @since 6.5.0
- *
- * @param array $inner_blocks Parsed inner blocks of a Navigation block.
- * @param WP_Post $post `wp_navigation` post object corresponding to the block.
- *
- * @return array the normalized parsed blocks.
- */
-function block_core_navigation_mock_parsed_block( $inner_blocks, $post ) {
- $attributes = array();
-
- if ( isset( $post->ID ) ) {
- $ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
- if ( ! empty( $ignored_hooked_blocks ) ) {
- $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
- $attributes['metadata'] = array(
- 'ignoredHookedBlocks' => $ignored_hooked_blocks,
- );
- }
- }
-
- $mock_anchor_parent_block = array(
- 'blockName' => 'core/navigation',
- 'attrs' => $attributes,
- 'innerBlocks' => $inner_blocks,
- 'innerContent' => array_fill( 0, count( $inner_blocks ), null ),
- );
-
- return $mock_anchor_parent_block;
-}
-
-/**
- * Insert hooked blocks into a Navigation block.
- *
- * Given a Navigation block's inner blocks and its corresponding `wp_navigation` post object,
- * this function inserts hooked blocks into it, and returns the serialized inner blocks in a
- * mock Navigation block wrapper.
- *
- * If there are any hooked blocks that need to be inserted as the Navigation block's first or last
- * children, the `wp_navigation` post's `_wp_ignored_hooked_blocks` meta is checked to see if any
- * of those hooked blocks should be exempted from insertion.
- *
- * @since 6.5.0
- *
- * @param array $inner_blocks Parsed inner blocks of a Navigation block.
- * @param WP_Post $post `wp_navigation` post object corresponding to the block.
- * @return string Serialized inner blocks in mock Navigation block wrapper, with hooked blocks inserted, if any.
- */
-function block_core_navigation_insert_hooked_blocks( $inner_blocks, $post ) {
- $mock_navigation_block = block_core_navigation_mock_parsed_block( $inner_blocks, $post );
-
- $mock_navigation_block_markup = serialize_block( $mock_navigation_block );
- return apply_block_hooks_to_content( $mock_navigation_block_markup, $post, 'insert_hooked_blocks' );
-}
diff --git a/packages/block-library/src/post-content/index.php b/packages/block-library/src/post-content/index.php
index e0a06b7217eeb..25be880cc4788 100644
--- a/packages/block-library/src/post-content/index.php
+++ b/packages/block-library/src/post-content/index.php
@@ -46,33 +46,10 @@ function render_block_core_post_content( $attributes, $content, $block ) {
$content .= wp_link_pages( array( 'echo' => 0 ) );
}
- $ignored_hooked_blocks = get_post_meta( $post_id, '_wp_ignored_hooked_blocks', true );
- if ( ! empty( $ignored_hooked_blocks ) ) {
- $ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
- $attributes['metadata'] = array(
- 'ignoredHookedBlocks' => $ignored_hooked_blocks,
- );
- }
-
- // Wrap in Post Content block so the Block Hooks algorithm can insert blocks
- // that are hooked as first or last child of `core/post-content`.
- $content = get_comment_delimited_block_content(
- 'core/post-content',
- $attributes,
- $content
- );
-
- // We need to remove the `core/post-content` block wrapper after the Block Hooks algorithm,
- // but before `do_blocks` runs, as it would otherwise attempt to render the same block again --
- // thus recursing infinitely.
- add_filter( 'the_content', 'remove_serialized_parent_block', 8 );
-
/** This filter is documented in wp-includes/post-template.php */
$content = apply_filters( 'the_content', str_replace( ']]>', ']]>', $content ) );
unset( $seen_ids[ $post_id ] );
- remove_filter( 'the_content', 'remove_serialized_parent_block', 8 );
-
if ( empty( $content ) ) {
return '';
}
diff --git a/packages/e2e-tests/plugins/interactive-blocks/router-styles-wrapper/render.php b/packages/e2e-tests/plugins/interactive-blocks/router-styles-wrapper/render.php
index 6373e8e9bc235..683db9eea5c4c 100644
--- a/packages/e2e-tests/plugins/interactive-blocks/router-styles-wrapper/render.php
+++ b/packages/e2e-tests/plugins/interactive-blocks/router-styles-wrapper/render.php
@@ -7,6 +7,17 @@
* @phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
*/
+add_action(
+ 'wp_enqueue_scripts',
+ function () {
+ wp_enqueue_style(
+ 'wrapper-styles-from-link',
+ plugin_dir_url( __FILE__ ) . 'style-from-link.css',
+ array()
+ );
+ }
+);
+
$wrapper_attributes = get_block_wrapper_attributes();
?>
>
@@ -38,6 +49,12 @@
All
+
+
+