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

+ +
+ Rule order checker +

I should remain green

+
+