Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add caption to post featured image #46883

Closed
wants to merge 13 commits into from
Closed
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,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), anchor, color (~~background~~, ~~text~~), spacing (margin, padding), ~~html~~
- **Attributes:** aspectRatio, customGradient, customOverlayColor, dimRatio, gradient, height, isLink, linkTarget, overlayColor, rel, scale, sizeSlug, width
- **Attributes:** aspectRatio, caption, customGradient, customOverlayColor, dimRatio, displayCaption, gradient, height, isLink, linkTarget, overlayColor, rel, scale, sizeSlug, width

## Post Navigation Link

Expand Down
7 changes: 7 additions & 0 deletions packages/block-library/src/post-featured-image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
},
"customGradient": {
"type": "string"
},
"displayCaption": {
"type": "boolean",
"default": false
},
"caption": {
"type": "string"
}
},
"usesContext": [ "postId", "postType", "queryId" ],
Expand Down
105 changes: 100 additions & 5 deletions packages/block-library/src/post-featured-image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Placeholder,
Button,
TextControl,
ToolbarButton,
} from '@wordpress/components';
import {
InspectorControls,
Expand All @@ -23,11 +24,16 @@ import {
MediaReplaceFlow,
useBlockProps,
store as blockEditorStore,
__experimentalGetElementClassName,
__experimentalUseBorderProps as useBorderProps,
RichText,
} from '@wordpress/block-editor';
import { __, sprintf } from '@wordpress/i18n';
import { upload } from '@wordpress/icons';
import { createBlock, getDefaultBlockName } from '@wordpress/blocks';
import { upload, caption as captionIcon } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { useEffect, useState, useCallback } from '@wordpress/element';
import { usePrevious } from '@wordpress/compose';

/**
* Internal dependencies
Expand All @@ -47,6 +53,8 @@ export default function PostFeaturedImageEdit( {
clientId,
attributes,
setAttributes,
isSelected,
insertBlocksAfter,
context: { postId, postType: postTypeSlug, queryId },
} ) {
const isDescendentOfQueryLoop = Number.isFinite( queryId );
Expand All @@ -59,6 +67,7 @@ export default function PostFeaturedImageEdit( {
sizeSlug,
rel,
linkTarget,
caption,
} = attributes;
const [ featuredImage, setFeaturedImage ] = useEntityProp(
'postType',
Expand All @@ -67,6 +76,32 @@ export default function PostFeaturedImageEdit( {
postId
);

const prevCaption = usePrevious( caption );
const [ showCaption, setShowCaption ] = useState( true );
// We need to show the caption when changes come from
// history navigation(undo/redo).
useEffect( () => {
if ( caption && ! prevCaption ) {
setShowCaption( true );
}
}, [ caption, prevCaption ] );

// Focus the caption when we click to add one.
const captionRef = useCallback(
( node ) => {
if ( node && ! caption ) {
node.focus();
}
},
[ caption ]
);

useEffect( () => {
if ( ! isSelected && ! caption ) {
setShowCaption( false );
}
}, [ isSelected, caption ] );

const { media, postType } = useSelect(
( select ) => {
const { getMedia, getPostType } = select( coreStore );
Expand All @@ -83,6 +118,10 @@ export default function PostFeaturedImageEdit( {
);
const mediaUrl = getMediaSourceUrlBySizeSlug( media, sizeSlug );

const mediaLibraryCaption = !! media?.caption?.rendered
? media?.caption?.rendered
: '';

const imageSizes = useSelect(
( select ) => select( blockEditorStore ).getSettings().imageSizes,
[]
Expand Down Expand Up @@ -130,8 +169,35 @@ export default function PostFeaturedImageEdit( {
createErrorNotice( message, { type: 'snackbar' } );
};

// Displays the caption when it is not editable.
const DisplayFigCaption = () => (
<figcaption
className={ __experimentalGetElementClassName( 'caption' ) }
dangerouslySetInnerHTML={ {
__html: !! caption ? caption : mediaLibraryCaption,
} }
/>
);

const controls = (
<>
<BlockControls group="block">
<ToolbarButton
onClick={ () => {
setShowCaption( ! showCaption );
if ( showCaption && caption ) {
setAttributes( { caption: undefined } );
}
} }
icon={ captionIcon }
isPressed={ showCaption }
label={
showCaption
? __( 'Remove caption' )
: __( 'Add caption' )
}
/>
</BlockControls>
<DimensionControls
clientId={ clientId }
attributes={ attributes }
Expand Down Expand Up @@ -188,14 +254,15 @@ export default function PostFeaturedImageEdit( {
return (
<>
{ controls }
<div { ...blockProps }>
<figure { ...blockProps }>
{ placeholder() }
<Overlay
attributes={ attributes }
setAttributes={ setAttributes }
clientId={ clientId }
/>
</div>
</figure>
{ showCaption && <DisplayFigCaption /> }
</>
);
}
Expand All @@ -214,14 +281,15 @@ export default function PostFeaturedImageEdit( {
setAttributes={ setAttributes }
imageSizeOptions={ imageSizeOptions }
/>
<div { ...blockProps }>
<figure { ...blockProps }>
{ placeholder() }
<Overlay
attributes={ attributes }
setAttributes={ setAttributes }
clientId={ clientId }
/>
</div>
{ showCaption && <DisplayFigCaption /> }
</figure>
</>
);
}
Expand Down Expand Up @@ -293,6 +361,7 @@ export default function PostFeaturedImageEdit( {
* - Is not inside a query loop
* Then display the image and the image replacement option.
*/

return (
<>
{ controls }
Expand All @@ -319,6 +388,32 @@ export default function PostFeaturedImageEdit( {
setAttributes={ setAttributes }
clientId={ clientId }
/>
{ showCaption &&
! isDescendentOfQueryLoop &&
( ! RichText.isEmpty( caption ) || isSelected ) && (
<RichText
tagName="figcaption"
className={ __experimentalGetElementClassName(
'caption'
) }
aria-label={ __( 'Image caption text' ) }
ref={ captionRef }
placeholder={ __( 'Add caption' ) }
value={ caption || mediaLibraryCaption }
onChange={ ( value ) =>
setAttributes( { caption: value } )
}
inlineToolbar
__unstableOnSplitAtEnd={ () =>
insertBlocksAfter(
createBlock( getDefaultBlockName() )
)
}
/>
) }
{ showCaption && isDescendentOfQueryLoop && (
<DisplayFigCaption />
) }
</figure>
</>
);
Expand Down
19 changes: 14 additions & 5 deletions packages/block-library/src/post-featured-image/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ function render_block_core_post_featured_image( $attributes, $content, $block )
the_post();
}

$is_link = isset( $attributes['isLink'] ) && $attributes['isLink'];
$size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail';
$attr = get_block_core_post_featured_image_border_attributes( $attributes );
$overlay_markup = get_block_core_post_featured_image_overlay_element_markup( $attributes );
$is_link = isset( $attributes['isLink'] ) && $attributes['isLink'];
$size_slug = isset( $attributes['sizeSlug'] ) ? $attributes['sizeSlug'] : 'post-thumbnail';
$attr = get_block_core_post_featured_image_border_attributes( $attributes );
$overlay_markup = get_block_core_post_featured_image_overlay_element_markup( $attributes );
$caption = isset( $attributes['caption'] ) ? $attributes['caption'] : '';
$display_caption = isset( $attributes['displayCaption'] ) ? $attributes['displayCaption'] : '';

if ( $is_link ) {
if ( get_the_title( $post_ID ) ) {
Expand Down Expand Up @@ -80,6 +82,13 @@ function render_block_core_post_featured_image( $attributes, $content, $block )
$featured_image = $featured_image . $overlay_markup;
}

$image_caption = '';
if ( $caption ) {
$image_caption = '<figcaption class="wp-element-caption">' . $caption . '</figcaption>';
} elseif ( $display_caption ) {
$image_caption = '<figcaption class="wp-element-caption">' . get_the_post_thumbnail_caption() . '</figcaption>';
}

$aspect_ratio = ! empty( $attributes['aspectRatio'] )
? esc_attr( safecss_filter_attr( 'aspect-ratio:' . $attributes['aspectRatio'] ) ) . ';'
: '';
Expand All @@ -94,7 +103,7 @@ function render_block_core_post_featured_image( $attributes, $content, $block )
} else {
$wrapper_attributes = get_block_wrapper_attributes( array( 'style' => $aspect_ratio . $width . $height ) );
}
return "<figure {$wrapper_attributes}>{$featured_image}</figure>";
return "<figure {$wrapper_attributes}>{$featured_image}{$image_caption}</figure>";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"scale": "cover",
"rel": "",
"linkTarget": "_self",
"dimRatio": 0
"dimRatio": 0,
"displayCaption": false
},
"innerBlocks": []
}
Expand Down