diff --git a/packages/block-editor/src/components/block-preview/index.js b/packages/block-editor/src/components/block-preview/index.js index b0d5ebb098815..0545d22fec57f 100644 --- a/packages/block-editor/src/components/block-preview/index.js +++ b/packages/block-editor/src/components/block-preview/index.js @@ -16,6 +16,7 @@ import deprecated from '@wordpress/deprecated'; */ import { ExperimentalBlockEditorProvider } from '../provider'; import AutoHeightBlockPreview from './auto'; +import EditorStyles from '../editor-styles'; import { store as blockEditorStore } from '../../store'; import { BlockListItems } from '../block-list'; @@ -113,7 +114,11 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { [] ); const settings = useMemo( - () => ( { ...originalSettings, __unstableIsPreviewMode: true } ), + () => ( { + ...originalSettings, + styles: undefined, // Clear styles included by the parent settings, as they are already output by the parent's EditorStyles. + __unstableIsPreviewMode: true, + } ), [ originalSettings ] ); const disabledRef = useDisabled(); @@ -128,6 +133,7 @@ export function useBlockPreview( { blocks, props = {}, layout } ) { value={ renderedBlocks } settings={ settings } > + ); diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 2bbe18793fe55..39a8979782a0c 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -37,11 +37,22 @@ import { scopeSelector } from '../components/global-styles/utils'; import { useBlockSettings } from './utils'; import { default as StylesFiltersPanel } from '../components/global-styles/filters-panel'; import { useBlockEditingMode } from '../components/block-editing-mode'; +import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs'; import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; const EMPTY_ARRAY = []; +// Safari does not always update the duotone filter when the duotone colors +// are changed. This browser check is later used to force a re-render of the block +// element to ensure the duotone filter is updated. The check is included at the +// root of this file as it only needs to be run once per page load. +const isSafari = + window?.navigator.userAgent && + window.navigator.userAgent.includes( 'Safari' ) && + ! window.navigator.userAgent.includes( 'Chrome' ) && + ! window.navigator.userAgent.includes( 'Chromium' ); + extend( [ namesPlugin ] ); function useMultiOriginPresets( { presetSetting, defaultSetting } ) { @@ -223,6 +234,7 @@ const withDuotoneControls = createHigherOrderComponent( ); function DuotoneStyles( { + clientId, id: filterId, selector: duotoneSelector, attribute: duotoneAttr, @@ -278,6 +290,8 @@ function DuotoneStyles( { useDispatch( blockEditorStore ) ); + const blockElement = useBlockElement( clientId ); + useEffect( () => { if ( ! isValidFilter ) return; @@ -294,12 +308,30 @@ function DuotoneStyles( { __unstableType: 'svgs', } ); + // Safari does not always update the duotone filter when the duotone colors + // are changed. When using Safari, force the block element to be repainted by + // the browser to ensure any changes are reflected visually. This logic matches + // that used on the site frontend in `block-supports/duotone.php`. + if ( blockElement && isSafari ) { + const display = blockElement.style.display; + // Switch to `inline-block` to force a repaint. In the editor, `inline-block` + // is used instead of `none` to ensure that scroll position is not affected, + // as `none` results in the editor scrolling to the top of the block. + blockElement.style.display = 'inline-block'; + // Simply accessing el.offsetHeight flushes layout and style + // changes in WebKit without having to wait for setTimeout. + // eslint-disable-next-line no-unused-expressions + blockElement.offsetHeight; + blockElement.style.display = display; + } + return () => { deleteStyleOverride( filterId ); deleteStyleOverride( `duotone-${ filterId }` ); }; }, [ isValidFilter, + blockElement, colors, selector, filterId, @@ -378,6 +410,7 @@ const withDuotoneStyles = createHigherOrderComponent( <> { shouldRender && ( { if ( ! css ) return; - setStyleOverride( id, { css } ); + setStyleOverride( selector, { css } ); return () => { - deleteStyleOverride( id ); + deleteStyleOverride( selector ); }; - }, [ id, css, setStyleOverride, deleteStyleOverride ] ); + }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); return ( { if ( ! css ) return; - setStyleOverride( id, { css } ); + setStyleOverride( selector, { css } ); return () => { - deleteStyleOverride( id ); + deleteStyleOverride( selector ); }; - }, [ id, css, setStyleOverride, deleteStyleOverride ] ); + }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); return ; }, diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 87e17a4c136b4..64b7457dd863d 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -170,8 +170,8 @@ function block_core_image_render_lightbox( $block_content, $block ) { if ( isset( $block['attrs']['id'] ) ) { $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] ); $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); - $img_width = $img_metadata['width']; - $img_height = $img_metadata['height']; + $img_width = $img_metadata['width'] ?? 'none'; + $img_height = $img_metadata['height'] ?? 'none'; } else { $img_uploaded_src = $processor->get_attribute( 'src' ); $img_width = 'none'; diff --git a/packages/block-serialization-default-parser/class-wp-block-parser.php b/packages/block-serialization-default-parser/class-wp-block-parser.php index 5790e97f8cf29..543f53691ccb1 100644 --- a/packages/block-serialization-default-parser/class-wp-block-parser.php +++ b/packages/block-serialization-default-parser/class-wp-block-parser.php @@ -48,14 +48,6 @@ class WP_Block_Parser { */ public $stack; - /** - * Empty associative array, here due to PHP quirks - * - * @since 4.4.0 - * @var array empty associative array - */ - public $empty_attrs; - /** * Parses a document and returns a list of block structures * @@ -69,11 +61,10 @@ class WP_Block_Parser { * @return array[] */ public function parse( $document ) { - $this->document = $document; - $this->offset = 0; - $this->output = array(); - $this->stack = array(); - $this->empty_attrs = array(); + $this->document = $document; + $this->offset = 0; + $this->output = array(); + $this->stack = array(); while ( $this->proceed() ) { continue; @@ -287,7 +278,7 @@ public function next_token() { */ $attrs = $has_attrs ? json_decode( $matches['attrs'][0], /* as-associative */ true ) - : $this->empty_attrs; + : array(); /* * This state isn't allowed @@ -318,7 +309,7 @@ public function next_token() { * @return WP_Block_Parser_Block freeform block object. */ public function freeform( $inner_html ) { - return new WP_Block_Parser_Block( null, $this->empty_attrs, array(), $inner_html, array( $inner_html ) ); + return new WP_Block_Parser_Block( null, array(), array(), $inner_html, array( $inner_html ) ); } /** diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 70adcb535181d..beeb854be5bac 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- `ProgressBar`: use text color to ensure enough contrast against background ([#55285](https://github.com/WordPress/gutenberg/pull/55285)). + ### Bug Fix - `Placeholder`: Improved DOM structure and screen reader announcements ([#45801](https://github.com/WordPress/gutenberg/pull/45801)). diff --git a/packages/components/src/progress-bar/styles.ts b/packages/components/src/progress-bar/styles.ts index e983797d3d92b..041b2402f0324 100644 --- a/packages/components/src/progress-bar/styles.ts +++ b/packages/components/src/progress-bar/styles.ts @@ -27,11 +27,17 @@ export const Track = styled.div` width: 100%; max-width: 160px; height: ${ CONFIG.borderWidthFocus }; - background-color: var( - --wp-components-color-gray-300, - ${ COLORS.gray[ 300 ] } + /* Text color at 10% opacity */ + background-color: color-mix( + in srgb, + var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ), + transparent 90% ); border-radius: ${ CONFIG.radiusBlockUi }; + + // Windows high contrast mode. + outline: 2px solid transparent; + outline-offset: 2px; `; export const Indicator = styled.div< { @@ -43,7 +49,16 @@ export const Indicator = styled.div< { top: 0; height: 100%; border-radius: ${ CONFIG.radiusBlockUi }; - background-color: ${ COLORS.theme.accent }; + /* Text color at 90% opacity */ + background-color: color-mix( + in srgb, + var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ), + transparent 10% + ); + + // Windows high contrast mode. + outline: 2px solid transparent; + outline-offset: -2px; ${ ( { isIndeterminate, value } ) => isIndeterminate diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 07f3c7a95c800..3560ef139fa3f 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -85,23 +85,35 @@ .edit-site-global-styles-variations_item { box-sizing: border-box; + // To round the outline in Windows 10 high contrast mode. + border-radius: $radius-block-ui; .edit-site-global-styles-variations_item-preview { padding: $border-width * 2; border-radius: $radius-block-ui; - border: $gray-200 $border-width solid; + box-shadow: 0 0 0 $border-width $gray-200; + // Shown in Windows 10 high contrast mode. + outline: 1px solid transparent; } &.is-active .edit-site-global-styles-variations_item-preview { - border: $gray-900 $border-width solid; + box-shadow: 0 0 0 $border-width $gray-900; + // Shown in Windows 10 high contrast mode. + outline-width: 3px; } &:hover .edit-site-global-styles-variations_item-preview { - border: var(--wp-admin-theme-color) $border-width solid; + box-shadow: 0 0 0 $border-width var(--wp-admin-theme-color); } &:focus .edit-site-global-styles-variations_item-preview { - border: var(--wp-admin-theme-color) var(--wp-admin-border-width-focus) solid; + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + } + + &:focus-visible { + // Shown in Windows 10 high contrast mode. + outline: 3px solid transparent; + outline-offset: 0; } } diff --git a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/last-revision.js b/packages/edit-site/src/components/sidebar-edit-mode/template-panel/last-revision.js index a4c5e29aeba69..b81c1b8b6ddbe 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/template-panel/last-revision.js +++ b/packages/edit-site/src/components/sidebar-edit-mode/template-panel/last-revision.js @@ -31,6 +31,10 @@ const useRevisionData = () => { function PostLastRevisionCheck( { children } ) { const { lastRevisionId, revisionsCount } = useRevisionData(); + if ( ! process.env.IS_GUTENBERG_PLUGIN ) { + return null; + } + if ( ! lastRevisionId || revisionsCount < 2 ) { return null; } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss index 4efdbad33a543..f658083cc19f4 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss @@ -90,17 +90,16 @@ } .edit-site-global-styles-variations_item-preview { - border: $gray-900 $border-width solid; + box-shadow: 0 0 0 $border-width $gray-900; } .edit-site-global-styles-variations_item.is-active .edit-site-global-styles-variations_item-preview { - border: $gray-100 $border-width solid; + box-shadow: 0 0 0 $border-width $gray-100; } .edit-site-global-styles-variations_item:hover .edit-site-global-styles-variations_item-preview { - border: var(--wp-admin-theme-color) $border-width solid; + box-shadow: 0 0 0 $border-width var(--wp-admin-theme-color); } - .edit-site-global-styles-variations_item:focus .edit-site-global-styles-variations_item-preview { - border: var(--wp-admin-theme-color) var(--wp-admin-border-width-focus) solid; + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); } }