diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 7488b6b9cdfe8..87f3a92810fe8 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -546,7 +546,7 @@ Display a post's featured image. ([Source](https://github.com/WordPress/gutenber - **Name:** core/post-featured-image - **Category:** theme - **Supports:** align (center, full, left, right, wide), color (~~background~~, ~~text~~), spacing (margin, padding), ~~html~~ -- **Attributes:** height, isLink, linkTarget, rel, scale, sizeSlug, width +- **Attributes:** customGradient, customOverlayColor, dimRatio, gradient, height, isLink, linkTarget, overlayColor, rel, scale, sizeSlug, width ## Post Navigation Link diff --git a/packages/block-library/src/post-featured-image/block.json b/packages/block-library/src/post-featured-image/block.json index dd5956a4f9290..1072c7576d645 100644 --- a/packages/block-library/src/post-featured-image/block.json +++ b/packages/block-library/src/post-featured-image/block.json @@ -32,6 +32,22 @@ "linkTarget": { "type": "string", "default": "_self" + }, + "overlayColor": { + "type": "string" + }, + "customOverlayColor": { + "type": "string" + }, + "dimRatio": { + "type": "number", + "default": 0 + }, + "gradient": { + "type": "string" + }, + "customGradient": { + "type": "string" } }, "usesContext": [ "postId", "postType", "queryId" ], diff --git a/packages/block-library/src/post-featured-image/edit.js b/packages/block-library/src/post-featured-image/edit.js index e95c8c2253dc4..1cdc0d0fd32eb 100644 --- a/packages/block-library/src/post-featured-image/edit.js +++ b/packages/block-library/src/post-featured-image/edit.js @@ -33,6 +33,7 @@ import { store as noticesStore } from '@wordpress/notices'; * Internal dependencies */ import DimensionControls from './dimension-controls'; +import Overlay from './overlay'; const ALLOWED_MEDIA_TYPES = [ 'image' ]; @@ -170,7 +171,14 @@ function PostFeaturedImageDisplay( { return ( <> { controls } -
{ placeholder() }
+
+ { placeholder() } + +
); } @@ -247,7 +255,14 @@ function PostFeaturedImageDisplay( { ) } -
{ image }
+
+ { image } + +
); } @@ -267,6 +282,11 @@ export default function PostFeaturedImageEdit( props ) { withIllustration={ true } style={ borderProps.style } /> + ); } diff --git a/packages/block-library/src/post-featured-image/editor.scss b/packages/block-library/src/post-featured-image/editor.scss index be7b9a9dafa53..c52d14f44f7a6 100644 --- a/packages/block-library/src/post-featured-image/editor.scss +++ b/packages/block-library/src/post-featured-image/editor.scss @@ -1,85 +1,92 @@ // Provide special styling for the placeholder. // @todo: this particular minimal style of placeholder could be componentized further. -.wp-block-post-featured-image.wp-block-post-featured-image { - // 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; - } +.wp-block-post-featured-image { + .block-editor-media-placeholder { + z-index: 1; // Need to put it above the overlay so the upload button works. + backdrop-filter: none; // Removes background blur so the overlay's actual color is visible. + } - // Style the upload button. - .components-button.components-button { - padding: 0; - display: flex; + &.wp-block-post-featured-image { + // Style the placeholder. + .wp-block-post-featured-image__placeholder, + .components-placeholder { 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; + padding: 0; - > svg { - color: inherit; + // Hide the upload button, as it's also available in the media library. + .components-form-file-upload { + display: none; } - } - // Show default placeholder height when not resized. - min-height: 200px; + // 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; - // 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; - } + > svg { + color: inherit; + } + } - &: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; + // 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; + } + + &: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%; + // 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 5e7ed6f70332d..931d87c0265c1 100644 --- a/packages/block-library/src/post-featured-image/index.php +++ b/packages/block-library/src/post-featured-image/index.php @@ -19,10 +19,11 @@ function render_block_core_post_featured_image( $attributes, $content, $block ) } $post_ID = $block->context['postId']; - $is_link = isset( $attributes['isLink'] ) && $attributes['isLink']; - $size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail'; - $post_title = trim( strip_tags( get_the_title( $post_ID ) ) ); - $attr = get_block_core_post_featured_image_border_attributes( $attributes ); + $is_link = isset( $attributes['isLink'] ) && $attributes['isLink']; + $size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail'; + $post_title = trim( strip_tags( get_the_title( $post_ID ) ) ); + $attr = get_block_core_post_featured_image_border_attributes( $attributes ); + $overlay_markup = get_block_core_post_featured_image_overlay_element_markup( $attributes ); if ( $is_link ) { $attr['alt'] = $post_title; @@ -36,13 +37,22 @@ function render_block_core_post_featured_image( $attributes, $content, $block ) if ( $is_link ) { $link_target = $attributes['linkTarget']; $rel = ! empty( $attributes['rel'] ) ? 'rel="' . esc_attr( $attributes['rel'] ) . '"' : ''; - $featured_image = sprintf( '%4$s', get_the_permalink( $post_ID ), esc_attr( $link_target ), $rel, $featured_image ); + $featured_image = sprintf( + '%4$s%5$s', + get_the_permalink( $post_ID ), + esc_attr( $link_target ), + $rel, + $featured_image, + $overlay_markup + ); + } else { + $featured_image = $featured_image . $overlay_markup; } $has_width = ! empty( $attributes['width'] ); $has_height = ! empty( $attributes['height'] ); if ( ! $has_height && ! $has_width ) { - return "
$featured_image
"; + return "
{$featured_image}
"; } if ( $has_width ) { @@ -57,7 +67,78 @@ function render_block_core_post_featured_image( $attributes, $content, $block ) $featured_image = str_replace( 'src=', 'style="' . esc_attr( $image_styles ) . '" src=', $featured_image ); } - return "
$featured_image
"; + return "
{$featured_image}
"; +} + +/** + * Generate markup for the HTML element that will be used for the overlay. + * + * @param array $attributes Block attributes. + * + * @return string HTML markup in string format. + */ +function get_block_core_post_featured_image_overlay_element_markup( $attributes ) { + $has_dim_background = isset( $attributes['dimRatio'] ) && $attributes['dimRatio']; + $has_gradient = isset( $attributes['gradient'] ) && $attributes['gradient']; + $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(); + + if ( ! $has_dim_background ) { + return ''; + } + + // Generate required classes for the element. + if ( $has_dim_background ) { + $class_names[] = 'has-background-dim'; + $class_names[] = "has-background-dim-{$attributes['dimRatio']}"; + } + + if ( $has_solid_overlay ) { + $class_names[] = "has-{$attributes['overlayColor']}-background-color"; + } + + if ( $has_gradient || $has_custom_gradient ) { + $class_names[] = 'has-background-gradient'; + } + + if ( $has_gradient ) { + $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']; + } + + if ( $has_custom_gradient ) { + $styles_properties['background-image'] = $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; "; + } + + return sprintf( + '', + esc_attr( implode( ' ', $class_names ) ), + esc_attr( trim( $styles ) ) + ); + } /** diff --git a/packages/block-library/src/post-featured-image/overlay.js b/packages/block-library/src/post-featured-image/overlay.js new file mode 100644 index 0000000000000..572cef64801e7 --- /dev/null +++ b/packages/block-library/src/post-featured-image/overlay.js @@ -0,0 +1,118 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +/** + * WordPress dependencies + */ +import { + RangeControl, + __experimentalToolsPanelItem as ToolsPanelItem, +} from '@wordpress/components'; +import { + InspectorControls, + withColors, + __experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown, + __experimentalUseGradient, + __experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, + __experimentalUseBorderProps as useBorderProps, +} from '@wordpress/block-editor'; +import { compose } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { dimRatioToClass } from './utils'; + +const Overlay = ( { + clientId, + attributes, + setAttributes, + overlayColor, + setOverlayColor, +} ) => { + const { dimRatio } = attributes; + const { gradientClass, gradientValue, setGradient } = + __experimentalUseGradient(); + const colorGradientSettings = useMultipleOriginColorsAndGradients(); + + const borderProps = useBorderProps( attributes ); + const overlayStyles = { + backgroundColor: overlayColor.color, + backgroundImage: gradientValue, + ...borderProps.style, + }; + + return ( + <> +