diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php index 5c1639d3d2ce6..c4b6935142dc3 100644 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -1151,15 +1151,6 @@ protected static function get_property_value( $styles, $path, $theme_json = null 'classes' => array(), 'properties' => array( 'padding', 'margin' ), ), - array( - 'path' => array( 'spacing', 'spacingScale' ), - 'prevent_override' => false, - 'use_default_names' => true, - 'value_key' => 'size', - 'css_vars' => '--wp--preset--spacing--$slug', - 'classes' => array(), - 'properties' => array( 'padding', 'margin' ), - ), ); /** diff --git a/packages/block-editor/src/components/block-parent-selector/index.js b/packages/block-editor/src/components/block-parent-selector/index.js index 8d24ba26794d5..caf488ac06ec6 100644 --- a/packages/block-editor/src/components/block-parent-selector/index.js +++ b/packages/block-editor/src/components/block-parent-selector/index.js @@ -83,10 +83,10 @@ export default function BlockParentSelector() { label={ sprintf( /* translators: %s: Name of the block's parent. */ __( 'Select %s' ), - blockInformation.title + blockInformation?.title ) } showTooltip - icon={ } + icon={ } /> ); diff --git a/packages/block-editor/src/components/block-popover/inbetween.js b/packages/block-editor/src/components/block-popover/inbetween.js index e7e207cb733f1..ae8a3b3203800 100644 --- a/packages/block-editor/src/components/block-popover/inbetween.js +++ b/packages/block-editor/src/components/block-popover/inbetween.js @@ -226,7 +226,7 @@ function BlockPopoverInbetween( { forcePopoverRecompute ); return () => { - previousElement.ownerDocument.defaultView.removeEventListener( + previousElement.ownerDocument.defaultView?.removeEventListener( 'resize', forcePopoverRecompute ); diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 03913faa26e42..7ece8e428317c 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -42,24 +42,15 @@ function BlockPopover( ref, usePopoverScroll( __unstableContentRef ), ] ); - const style = useMemo( () => { - if ( ! selectedElement || lastSelectedElement !== selectedElement ) { - return {}; - } - - return { - position: 'absolute', - width: selectedElement.offsetWidth, - height: selectedElement.offsetHeight, - }; - }, [ selectedElement, lastSelectedElement, __unstableRefreshSize ] ); - const [ popoverAnchorRecomputeCounter, forceRecomputePopoverAnchor ] = - useReducer( - // Module is there to make sure that the counter doesn't overflow. - ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER, - 0 - ); + const [ + popoverDimensionsRecomputeCounter, + forceRecomputePopoverDimensions, + ] = useReducer( + // Module is there to make sure that the counter doesn't overflow. + ( s ) => ( s + 1 ) % MAX_POPOVER_RECOMPUTE_COUNTER, + 0 + ); // When blocks are moved up/down, they are animated to their new position by // updating the `transform` property manually (i.e. without using CSS @@ -74,7 +65,7 @@ function BlockPopover( } const observer = new window.MutationObserver( - forceRecomputePopoverAnchor + forceRecomputePopoverDimensions ); observer.observe( selectedElement, { attributes: true } ); @@ -83,12 +74,36 @@ function BlockPopover( }; }, [ selectedElement ] ); + const style = useMemo( () => { + if ( + // popoverDimensionsRecomputeCounter is by definition always equal or greater + // than 0. This check is only there to satisfy the correctness of the + // exhaustive-deps rule for the `useMemo` hook. + popoverDimensionsRecomputeCounter < 0 || + ! selectedElement || + lastSelectedElement !== selectedElement + ) { + return {}; + } + + return { + position: 'absolute', + width: selectedElement.offsetWidth, + height: selectedElement.offsetHeight, + }; + }, [ + selectedElement, + lastSelectedElement, + __unstableRefreshSize, + popoverDimensionsRecomputeCounter, + ] ); + const popoverAnchor = useMemo( () => { if ( - // popoverAnchorRecomputeCounter is by definition always equal or greater + // popoverDimensionsRecomputeCounter is by definition always equal or greater // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. - popoverAnchorRecomputeCounter < 0 || + popoverDimensionsRecomputeCounter < 0 || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { @@ -132,7 +147,7 @@ function BlockPopover( bottomClientId, lastSelectedElement, selectedElement, - popoverAnchorRecomputeCounter, + popoverDimensionsRecomputeCounter, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { diff --git a/packages/block-editor/src/components/image-editor/use-transform-image.js b/packages/block-editor/src/components/image-editor/use-transform-image.js index d3e514d0f33f1..885ae8894c092 100644 --- a/packages/block-editor/src/components/image-editor/use-transform-image.js +++ b/packages/block-editor/src/components/image-editor/use-transform-image.js @@ -41,7 +41,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) { if ( angle === 0 ) { setEditedUrl(); setRotation( angle ); - setAspect( 1 / aspect ); + setAspect( naturalWidth / naturalHeight ); setPosition( { x: -( position.y * naturalAspectRatio ), y: position.x * naturalAspectRatio, @@ -80,7 +80,7 @@ function useTransformState( { url, naturalWidth, naturalHeight } ) { canvas.toBlob( ( blob ) => { setEditedUrl( URL.createObjectURL( blob ) ); setRotation( angle ); - setAspect( 1 / aspect ); + setAspect( canvas.width / canvas.height ); setPosition( { x: -( position.y * naturalAspectRatio ), y: position.x * naturalAspectRatio, diff --git a/packages/block-editor/src/components/spacing-sizes-control/index.js b/packages/block-editor/src/components/spacing-sizes-control/index.js index ba379713b4bcc..7b016e7a08ee7 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/index.js +++ b/packages/block-editor/src/components/spacing-sizes-control/index.js @@ -1,9 +1,14 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { __experimentalText as Text } from '@wordpress/components'; +import { BaseControl } from '@wordpress/components'; /** * Internal dependencies @@ -68,8 +73,15 @@ export default function SpacingSizesControl( { }; return ( -
- { label } +
+ + { label } + { ! hasOneSide && ( ) } diff --git a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js index c0d2573b42e80..cf9a663fe1fa1 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/spacing-input-control.js @@ -9,12 +9,12 @@ import classnames from 'classnames'; import { useState, useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { + BaseControl, Button, RangeControl, CustomSelectControl, __experimentalUnitControl as UnitControl, __experimentalHStack as HStack, - __experimentalText as Text, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, } from '@wordpress/components'; @@ -167,21 +167,21 @@ export default function SpacingInputControl( { <> { side !== 'all' && ( - + { LABELS[ side ] } - + { showHint && ( - + { currentValueHint } - + ) } ) } { side === 'all' && showHint && ( - + { currentValueHint } - + ) } { ! disableCustomSpacingSizes && ( @@ -256,6 +256,7 @@ export default function SpacingInputControl( { marks={ marks } label={ ariaLabel } hideLabelFromVision={ true } + __nextHasNoMarginBottom={ true } /> ) } { ! showRangeControl && ! showCustomValueControl && ( diff --git a/packages/block-editor/src/components/spacing-sizes-control/style.scss b/packages/block-editor/src/components/spacing-sizes-control/style.scss index 448a21cc0ac1b..27b83a9ba5ca8 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/style.scss +++ b/packages/block-editor/src/components/spacing-sizes-control/style.scss @@ -1,7 +1,8 @@ .tools-panel-item-spacing { display: grid; grid-template-columns: auto 1fr auto; - grid-row-gap: $grid-unit-05; + align-items: center; + grid-template-rows: 25px auto; } .component-spacing-sizes-control { @@ -17,21 +18,34 @@ align-self: center; } + .components-base-control__label { + margin-bottom: 0; + height: $grid-unit-20; + } + .components-spacing-sizes-control__side-labels { grid-column: 1 / 1; - min-height: 30px; justify-content: left; + height: $grid-unit-20; + margin-top: $grid-unit-15; + } + + .components-spacing-sizes-control__side-label { + grid-column: 1 / 1; + justify-self: left; + margin-bottom: 0; } - .components-spacing-sizes-control__hint-single { - margin-top: 0; - margin-left: 0; + &.is-unlinked { + .components-range-control.components-spacing-sizes-control__range-control { + margin-top: $grid-unit-15; + } } .components-spacing-sizes-control__hint-single, .components-spacing-sizes-control__hint-all { color: $gray-700; - font-size: 12px; + margin-bottom: 0; } .components-spacing-sizes-control__hint-all { @@ -47,6 +61,11 @@ grid-row: 1 / 1; justify-self: end; padding: 0; + &.is-small.has-icon { + padding: 0; + min-width: $icon-size; + height: $grid-unit-20; + } } .component-spacing-sizes-control__linked-button ~ .components-spacing-sizes-control__custom-toggle-all { @@ -56,13 +75,11 @@ .components-spacing-sizes-control__custom-toggle-single { grid-column: 3 / 3; justify-self: end; - } - - .components-spacing-sizes-control__custom-toggle-all, - .components-spacing-sizes-control__custom-toggle-single { &.is-small.has-icon { padding: 0; min-width: $icon-size; + height: $grid-unit-20; + margin-top: $grid-unit-15; } } @@ -75,7 +92,6 @@ .components-spacing-sizes-control__custom-value-range { grid-column: span 2; margin-left: $grid-unit-10; - padding-right: $grid-unit-10; height: 30px; } @@ -85,12 +101,7 @@ .components-spacing-sizes-control__range-control { grid-column: span 3; - padding-right: $grid-unit-10; - height: 30px; - } - - .components-range-control__wrapper { - margin-bottom: 0; + height: 40px; } .components-range-control__mark { @@ -112,13 +123,6 @@ z-index: 3; } - .components-spacing-sizes-control__side-label { - margin-right: $grid-unit-05; - grid-column: 1 / 1; - justify-self: left; - font-size: 12px; - } - .components-spacing-sizes-control__custom-select-control { grid-column: span 3; } diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 60a34f6ea55fb..f6fa73a053ac5 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -20,6 +20,7 @@ import './metadata'; import './metadata-name'; export { useCustomSides } from './dimensions'; +export { useLayoutClasses, useLayoutStyles } from './layout'; export { getBorderClassesAndStyles, useBorderProps } from './use-border-props'; export { getColorClassesAndStyles, useColorProps } from './use-color-props'; export { getSpacingClassesAndStyles } from './use-spacing-props'; diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index ac24fa6f4e232..73d655c57c2ac 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -37,58 +37,101 @@ import { getLayoutType, getLayoutTypes } from '../layouts'; const layoutBlockSupportKey = '__experimentalLayout'; /** - * Generates the utility classnames for the given blocks layout attributes. - * This method was primarily added to reintroduce classnames that were removed - * in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719), rather - * than providing an extensive list of all possible layout classes. The plan is to - * have the style engine generate a more extensive list of utility classnames which - * will then replace this method. + * Generates the utility classnames for the given block's layout attributes. * - * @param { Object } layout Layout object. - * @param { Object } layoutDefinitions An object containing layout definitions, stored in theme.json. + * @param { Object } block Block object. * * @return { Array } Array of CSS classname strings. */ -function useLayoutClasses( layout, layoutDefinitions ) { +export function useLayoutClasses( block = {} ) { const rootPaddingAlignment = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); return getSettings().__experimentalFeatures ?.useRootPaddingAwareAlignments; }, [] ); + const globalLayoutSettings = useSetting( 'layout' ) || {}; + + const { attributes = {}, name } = block; + const { layout } = attributes; + + const { default: defaultBlockLayout } = + getBlockSupport( name, layoutBlockSupportKey ) || {}; + const usedLayout = + layout?.inherit || layout?.contentSize || layout?.wideSize + ? { ...layout, type: 'constrained' } + : layout || defaultBlockLayout || {}; + const layoutClassnames = []; - if ( layoutDefinitions?.[ layout?.type || 'default' ]?.className ) { + if ( + globalLayoutSettings?.definitions?.[ usedLayout?.type || 'default' ] + ?.className + ) { layoutClassnames.push( - layoutDefinitions?.[ layout?.type || 'default' ]?.className + globalLayoutSettings?.definitions?.[ usedLayout?.type || 'default' ] + ?.className ); } if ( - ( layout?.inherit || - layout?.contentSize || - layout?.type === 'constrained' ) && + ( usedLayout?.inherit || + usedLayout?.contentSize || + usedLayout?.type === 'constrained' ) && rootPaddingAlignment ) { layoutClassnames.push( 'has-global-padding' ); } - if ( layout?.orientation ) { - layoutClassnames.push( `is-${ kebabCase( layout.orientation ) }` ); + if ( usedLayout?.orientation ) { + layoutClassnames.push( `is-${ kebabCase( usedLayout.orientation ) }` ); } - if ( layout?.justifyContent ) { + if ( usedLayout?.justifyContent ) { layoutClassnames.push( - `is-content-justification-${ kebabCase( layout.justifyContent ) }` + `is-content-justification-${ kebabCase( + usedLayout.justifyContent + ) }` ); } - if ( layout?.flexWrap && layout.flexWrap === 'nowrap' ) { + if ( usedLayout?.flexWrap && usedLayout.flexWrap === 'nowrap' ) { layoutClassnames.push( 'is-nowrap' ); } return layoutClassnames; } +/** + * Generates a CSS rule with the given block's layout styles. + * + * @param { Object } block Block object. + * @param { string } selector A selector to use in generating the CSS rule. + * + * @return { string } CSS rule. + */ +export function useLayoutStyles( block = {}, selector ) { + const { attributes = {}, name } = block; + const { layout = {}, style = {} } = attributes; + // Update type for blocks using legacy layouts. + const usedLayout = + layout?.inherit || layout?.contentSize || layout?.wideSize + ? { ...layout, type: 'constrained' } + : layout || {}; + const fullLayoutType = getLayoutType( usedLayout?.type || 'default' ); + const globalLayoutSettings = useSetting( 'layout' ) || {}; + const blockGapSupport = useSetting( 'spacing.blockGap' ); + const hasBlockGapSupport = blockGapSupport !== null; + const css = fullLayoutType?.getLayoutStyle?.( { + blockName: name, + selector, + layout, + layoutDefinitions: globalLayoutSettings?.definitions, + style, + hasBlockGapSupport, + } ); + return css; +} + function LayoutPanel( { setAttributes, attributes, name: blockName } ) { const { layout } = attributes; const defaultThemeLayout = useSetting( 'layout' ); @@ -299,7 +342,7 @@ export const withInspectorControls = createHigherOrderComponent( */ export const withLayoutStyles = createHigherOrderComponent( ( BlockListBlock ) => ( props ) => { - const { name, attributes } = props; + const { name, attributes, block } = props; const hasLayoutBlockSupport = hasBlockSupport( name, layoutBlockSupportKey @@ -321,7 +364,7 @@ export const withLayoutStyles = createHigherOrderComponent( ? { ...layout, type: 'constrained' } : layout || defaultBlockLayout || {}; const layoutClasses = hasLayoutBlockSupport - ? useLayoutClasses( usedLayout, defaultThemeLayout?.definitions ) + ? useLayoutClasses( block ) : null; const selector = `.${ getBlockDefaultClassName( name diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index ec0f20a8f9c89..1c81c910b21e1 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -12,6 +12,8 @@ export { getSpacingClassesAndStyles as __experimentalGetSpacingClassesAndStyles, getGapCSSValue as __experimentalGetGapCSSValue, useCachedTruthy, + useLayoutClasses as __experimentaluseLayoutClasses, + useLayoutStyles as __experimentaluseLayoutStyles, } from './hooks'; export * from './components'; export * from './elements'; diff --git a/packages/block-library/src/code/style.scss b/packages/block-library/src/code/style.scss index e8d3b07cd034f..670a4f7f1ef4c 100644 --- a/packages/block-library/src/code/style.scss +++ b/packages/block-library/src/code/style.scss @@ -1,8 +1,13 @@ -// Provide a minimum of overflow handling and ensure the code markup inherits -// the font-family set on pre. -.wp-block-code code { - display: block; - font-family: inherit; - overflow-wrap: break-word; - white-space: pre-wrap; +.wp-block-code { + // This block has customizable padding, border-box makes that more predictable. + box-sizing: border-box; + + // Provide a minimum of overflow handling and ensure the code markup inherits + // the font-family set on pre. + code { + display: block; + font-family: inherit; + overflow-wrap: break-word; + white-space: pre-wrap; + } } diff --git a/packages/block-library/src/navigation/edit/index.js b/packages/block-library/src/navigation/edit/index.js index 751d33b9b501f..6cb773e60107b 100644 --- a/packages/block-library/src/navigation/edit/index.js +++ b/packages/block-library/src/navigation/edit/index.js @@ -282,16 +282,18 @@ function Navigation( { hasResolvedNavigationMenus && ! hasUncontrolledInnerBlocks; - if ( isPlaceholder && ! ref ) { - /** - * this fallback only displays (both in editor and on front) - * the list of pages block if no menu is available as a fallback. - * We don't want the fallback to request a save, - * nor to be undoable, hence we mark it non persistent. - */ - __unstableMarkNextChangeAsNotPersistent(); - replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] ); - } + useEffect( () => { + if ( isPlaceholder && ! ref ) { + /** + * this fallback only displays (both in editor and on front) + * the list of pages block if no menu is available as a fallback. + * We don't want the fallback to request a save, + * nor to be undoable, hence we mark it non persistent. + */ + __unstableMarkNextChangeAsNotPersistent(); + replaceInnerBlocks( clientId, [ createBlock( 'core/page-list' ) ] ); + } + }, [ clientId, isPlaceholder, ref ] ); const isEntityAvailable = ! isNavigationMenuMissing && isNavigationMenuResolved; diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js index 233399a63f8d5..1949553b2540f 100644 --- a/packages/block-library/src/post-content/edit.js +++ b/packages/block-library/src/post-content/edit.js @@ -46,7 +46,9 @@ function EditableContent( { layout, context = {} } ) { return getSettings()?.supportsLayout; }, [] ); const defaultLayout = useSetting( 'layout' ) || {}; - const usedLayout = !! layout && layout.inherit ? defaultLayout : layout; + const usedLayout = ! layout?.type + ? { ...defaultLayout, ...layout, type: 'default' } + : { ...defaultLayout, ...layout }; const [ blocks, onInput, onChange ] = useEntityBlockEditor( 'postType', postType, diff --git a/packages/block-library/src/post-featured-image/block.json b/packages/block-library/src/post-featured-image/block.json index 1072c7576d645..40f51cffa06e7 100644 --- a/packages/block-library/src/post-featured-image/block.json +++ b/packages/block-library/src/post-featured-image/block.json @@ -62,7 +62,7 @@ "color": true, "radius": true, "width": true, - "__experimentalSelector": "img, .block-editor-media-placeholder", + "__experimentalSelector": "img, .block-editor-media-placeholder, .wp-block-post-featured-image__overlay", "__experimentalSkipSerialization": true, "__experimentalDefaultControls": { "color": true, diff --git a/packages/block-library/src/post-featured-image/editor.scss b/packages/block-library/src/post-featured-image/editor.scss index c52d14f44f7a6..1af6e63e1be4a 100644 --- a/packages/block-library/src/post-featured-image/editor.scss +++ b/packages/block-library/src/post-featured-image/editor.scss @@ -6,87 +6,94 @@ backdrop-filter: none; // Removes background blur so the overlay's actual color is visible. } - &.wp-block-post-featured-image { - // Style the placeholder. - .wp-block-post-featured-image__placeholder, - .components-placeholder { - justify-content: center; - align-items: center; - padding: 0; + // Style the placeholder. + .wp-block-post-featured-image__placeholder, + .components-placeholder { + justify-content: center; + align-items: center; + padding: 0; - // Hide the upload button, as it's also available in the media library. - .components-form-file-upload { - display: none; - } + // Hide the upload button, as it's also available in the media library. + .components-form-file-upload { + display: none; + } - // Style the upload button. - .components-button.components-button { - padding: 0; - display: flex; - justify-content: center; - align-items: center; - width: $grid-unit-60; - height: $grid-unit-60; - border-radius: 50%; - position: relative; - background: var(--wp-admin-theme-color); - border-color: var(--wp-admin-theme-color); - border-style: solid; - color: $white; + // Style the upload button. + .components-button { + padding: 0; + display: flex; + justify-content: center; + align-items: center; + width: $grid-unit-60; + height: $grid-unit-60; + border-radius: 50%; + position: relative; + background: var(--wp-admin-theme-color); + border-color: var(--wp-admin-theme-color); + border-style: solid; + color: $white; - > svg { - color: inherit; - } + > svg { + color: inherit; } + } - // Show default placeholder height when not resized. - min-height: 200px; - - // The following override the default placeholder styles that remove - // its border so that a user selection for border color or width displays - // a visual border. - &:where(.has-border-color) { - border-style: solid; - } - &:where([style*="border-top-color"]) { - border-top-style: solid; - } - &:where([style*="border-right-color"]) { - border-right-style: solid; - } - &:where([style*="border-bottom-color"]) { - border-bottom-style: solid; - } - &:where([style*="border-left-color"]) { - border-left-style: solid; - } + // Show default placeholder height when not resized. + min-height: 200px; + } - &:where([style*="border-width"]) { - border-style: solid; - } - &:where([style*="border-top-width"]) { - border-top-style: solid; - } - &:where([style*="border-right-width"]) { - border-right-style: solid; - } - &:where([style*="border-bottom-width"]) { - border-bottom-style: solid; - } - &:where([style*="border-left-width"]) { - border-left-style: solid; - } + // The following override the default placeholder styles that remove + // its border so that a user selection for border color or width displays + // a visual border. They also override the `img { border: none; }` applied + // by core. + .wp-block-post-featured-image__placeholder, + .components-placeholder, + img { + // The following is required to overcome WP Core applying styles that clear + // img borders with a higher specificity than those added by the border + // block support to provide a default border-style of solid when a border + // color or width has been set. + &:where(.has-border-color) { + border-style: solid; + } + &:where([style*="border-top-color"]) { + border-top-style: solid; + } + &:where([style*="border-right-color"]) { + border-right-style: solid; + } + &:where([style*="border-bottom-color"]) { + border-bottom-style: solid; + } + &:where([style*="border-left-color"]) { + border-left-style: solid; } - // Provide a minimum size for the placeholder when resized. - // Note, this should be as small as we can afford it, and exists only - // to ensure there's room for the upload button. - &[style*="height"] .components-placeholder { - min-height: $grid-unit-60; - min-width: $grid-unit-60; - height: 100%; - width: 100%; + &:where([style*="border-width"]) { + border-style: solid; + } + &:where([style*="border-top-width"]) { + border-top-style: solid; + } + &:where([style*="border-right-width"]) { + border-right-style: solid; } + &:where([style*="border-bottom-width"]) { + border-bottom-style: solid; + } + &:where([style*="border-left-width"]) { + border-left-style: solid; + } + } + + // Provide a minimum size for the placeholder when resized. + // Note, this should be as small as we can afford it, and exists only + // to ensure there's room for the upload button. + &[style*="height"] .components-placeholder { + min-height: $grid-unit-60; + min-width: $grid-unit-60; + height: 100%; + width: 100%; } } diff --git a/packages/block-library/src/post-featured-image/index.php b/packages/block-library/src/post-featured-image/index.php index 595f58cbfe95e..de5683b297027 100644 --- a/packages/block-library/src/post-featured-image/index.php +++ b/packages/block-library/src/post-featured-image/index.php @@ -83,16 +83,25 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes $has_custom_gradient = isset( $attributes['customGradient'] ) && $attributes['customGradient']; $has_solid_overlay = isset( $attributes['overlayColor'] ) && $attributes['overlayColor']; $has_custom_overlay = isset( $attributes['customOverlayColor'] ) && $attributes['customOverlayColor']; - $class_names = array( - 'wp-block-post-featured-image__overlay', - ); - $styles_properties = array(); + $class_names = array( 'wp-block-post-featured-image__overlay' ); + $styles = array(); if ( ! $has_dim_background ) { return ''; } - // Generate required classes for the element. + // Apply border classes and styles. + $border_attributes = get_block_core_post_featured_image_border_attributes( $attributes ); + + if ( ! empty( $border_attributes['class'] ) ) { + $class_names[] = $border_attributes['class']; + } + + if ( ! empty( $border_attributes['style'] ) ) { + $styles[] = $border_attributes['style']; + } + + // Apply overlay and gradient classes. if ( $has_dim_background ) { $class_names[] = 'has-background-dim'; $class_names[] = "has-background-dim-{$attributes['dimRatio']}"; @@ -110,35 +119,20 @@ function get_block_core_post_featured_image_overlay_element_markup( $attributes $class_names[] = "has-{$attributes['gradient']}-gradient-background"; } - // Generate required CSS properties and their values. - if ( ! empty( $attributes['style']['border']['radius'] ) ) { - $styles_properties['border-radius'] = $attributes['style']['border']['radius']; - } - - if ( ! empty( $attributes['style']['border']['width'] ) ) { - $styles_properties['border-width'] = $attributes['style']['border']['width']; - } - + // Apply background styles. if ( $has_custom_gradient ) { - $styles_properties['background-image'] = $attributes['customGradient']; + $styles[] = sprintf( 'background-image: %s;', $attributes['customGradient'] ); } if ( $has_custom_overlay ) { - $styles_properties['background-color'] = $attributes['customOverlayColor']; - } - - $styles = ''; - - foreach ( $styles_properties as $style_attribute => $style_attribute_value ) { - $styles .= "{$style_attribute}: $style_attribute_value; "; + $styles[] = sprintf( 'background-color: %s;', $attributes['customOverlayColor'] ); } return sprintf( '', esc_attr( implode( ' ', $class_names ) ), - esc_attr( trim( $styles ) ) + esc_attr( safecss_filter_attr( implode( ' ', $styles ) ) ) ); - } /** diff --git a/packages/block-library/src/post-featured-image/overlay.js b/packages/block-library/src/post-featured-image/overlay.js index 572cef64801e7..f577978b9a3c9 100644 --- a/packages/block-library/src/post-featured-image/overlay.js +++ b/packages/block-library/src/post-featured-image/overlay.js @@ -47,20 +47,23 @@ const Overlay = ( { return ( <> -