Skip to content

Commit

Permalink
Improve the featured image UI when it cannot retrieve the image file …
Browse files Browse the repository at this point in the history
…and data (WordPress#66936)

* Improve the featured image UI when cannot retrieve the image file and data.

* Address CR feedback.

* Use a Notice instead of a paragraph.

* Address more CR feedback.

Co-authored-by: afercia <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
  • Loading branch information
3 people authored Nov 15, 2024
1 parent c3a9c1a commit 7300373
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 56 deletions.
152 changes: 109 additions & 43 deletions packages/editor/src/components/post-featured-image/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import clsx from 'clsx';

/**
* WordPress dependencies
*/
Expand All @@ -10,9 +15,10 @@ import {
withNotices,
withFilters,
__experimentalHStack as HStack,
Notice,
} from '@wordpress/components';
import { isBlobURL } from '@wordpress/blob';
import { useState, useRef } from '@wordpress/element';
import { useState, useRef, useEffect } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import { useSelect, withDispatch, withSelect } from '@wordpress/data';
import {
Expand Down Expand Up @@ -94,11 +100,19 @@ function PostFeaturedImage( {
postType,
noticeUI,
noticeOperations,
isRequestingFeaturedImageMedia,
} ) {
const toggleRef = useRef();
const [ isLoading, setIsLoading ] = useState( false );
const { getSettings } = useSelect( blockEditorStore );
const { mediaSourceUrl } = getMediaDetails( media, currentPostId );
const toggleFocusTimerRef = useRef();

useEffect( () => {
return () => {
clearTimeout( toggleFocusTimerRef.current );
};
}, [] );

function onDropFiles( filesList ) {
getSettings().mediaUpload( {
Expand Down Expand Up @@ -150,6 +164,9 @@ function PostFeaturedImage( {
);
}

const isMissingMedia =
! isRequestingFeaturedImageMedia && !! featuredImageId && ! media;

return (
<PostFeaturedImageCheck>
{ noticeUI }
Expand All @@ -174,52 +191,83 @@ function PostFeaturedImage( {
modalClass="editor-post-featured-image__media-modal"
render={ ( { open } ) => (
<div className="editor-post-featured-image__container">
<Button
__next40pxDefaultSize
ref={ toggleRef }
className={
! featuredImageId
? 'editor-post-featured-image__toggle'
: 'editor-post-featured-image__preview'
}
onClick={ open }
aria-label={
! featuredImageId
? null
: __(
'Edit or replace the featured image'
)
}
aria-describedby={
! featuredImageId
? null
: `editor-post-featured-image-${ featuredImageId }-describedby`
}
aria-haspopup="dialog"
disabled={ isLoading }
accessibleWhenDisabled
>
{ !! featuredImageId && media && (
<img
className="editor-post-featured-image__preview-image"
src={ mediaSourceUrl }
alt={ getImageDescription( media ) }
/>
) }
{ isLoading && <Spinner /> }
{ ! featuredImageId &&
! isLoading &&
( postType?.labels
?.set_featured_image ||
DEFAULT_SET_FEATURE_IMAGE_LABEL ) }
</Button>
{ isMissingMedia ? (
<Notice
status="warning"
isDismissible={ false }
>
{ __(
'Could not retrieve the featured image data.'
) }
</Notice>
) : (
<Button
__next40pxDefaultSize
ref={ toggleRef }
className={
! featuredImageId
? 'editor-post-featured-image__toggle'
: 'editor-post-featured-image__preview'
}
onClick={ open }
aria-label={
! featuredImageId
? null
: __(
'Edit or replace the featured image'
)
}
aria-describedby={
! featuredImageId
? null
: `editor-post-featured-image-${ featuredImageId }-describedby`
}
aria-haspopup="dialog"
disabled={ isLoading }
accessibleWhenDisabled
>
{ !! featuredImageId && media && (
<img
className="editor-post-featured-image__preview-image"
src={ mediaSourceUrl }
alt={ getImageDescription(
media
) }
/>
) }
{ ( isLoading ||
isRequestingFeaturedImageMedia ) && (
<Spinner />
) }
{ ! featuredImageId &&
! isLoading &&
( postType?.labels
?.set_featured_image ||
DEFAULT_SET_FEATURE_IMAGE_LABEL ) }
</Button>
) }
{ !! featuredImageId && (
<HStack className="editor-post-featured-image__actions">
<HStack
className={ clsx(
'editor-post-featured-image__actions',
{
'editor-post-featured-image__actions-missing-image':
isMissingMedia,
'editor-post-featured-image__actions-is-requesting-image':
isRequestingFeaturedImageMedia,
}
) }
>
<Button
__next40pxDefaultSize
className="editor-post-featured-image__action"
onClick={ open }
aria-haspopup="dialog"
variant={
isMissingMedia
? 'secondary'
: undefined
}
>
{ __( 'Replace' ) }
</Button>
Expand All @@ -228,8 +276,19 @@ function PostFeaturedImage( {
className="editor-post-featured-image__action"
onClick={ () => {
onRemoveImage();
toggleRef.current.focus();
// The toggle button is rendered conditionally, we need
// to wait it is rendered before moving focus to it.
toggleFocusTimerRef.current =
setTimeout( () => {
toggleRef.current?.focus();
} );
} }
variant={
isMissingMedia
? 'secondary'
: undefined
}
isDestructive={ isMissingMedia }
>
{ __( 'Remove' ) }
</Button>
Expand All @@ -247,7 +306,8 @@ function PostFeaturedImage( {
}

const applyWithSelect = withSelect( ( select ) => {
const { getMedia, getPostType } = select( coreStore );
const { getMedia, getPostType, hasFinishedResolution } =
select( coreStore );
const { getCurrentPostId, getEditedPostAttribute } = select( editorStore );
const featuredImageId = getEditedPostAttribute( 'featured_media' );

Expand All @@ -258,6 +318,12 @@ const applyWithSelect = withSelect( ( select ) => {
currentPostId: getCurrentPostId(),
postType: getPostType( getEditedPostAttribute( 'type' ) ),
featuredImageId,
isRequestingFeaturedImageMedia:
!! featuredImageId &&
! hasFinishedResolution( 'getMedia', [
featuredImageId,
{ context: 'view' },
] ),
};
} );

Expand Down
36 changes: 23 additions & 13 deletions packages/editor/src/components/post-featured-image/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
&:hover,
&:focus,
&:focus-within {
.editor-post-featured-image__actions {
.editor-post-featured-image__actions:not(.editor-post-featured-image__actions-is-requesting-image) {
opacity: 1;
}
}

.editor-post-featured-image__actions.editor-post-featured-image__actions-missing-image {
opacity: 1;
margin-top: $grid-unit-20;
}

.components-drop-zone__content {
border-radius: $radius-small;
}
Expand Down Expand Up @@ -72,17 +77,22 @@
}

.editor-post-featured-image__actions {
@include reduce-motion("transition");
bottom: 0;
opacity: 0; // Use opacity instead of visibility so that the buttons remain in the tab order.
padding: $grid-unit-10;
position: absolute;
transition: opacity 50ms ease-out;
}
&:not(.editor-post-featured-image__actions-missing-image) {
@include reduce-motion("transition");
bottom: 0;
opacity: 0; // Use opacity instead of visibility so that the buttons remain in the tab order.
padding: $grid-unit-10;
position: absolute;
transition: opacity 50ms ease-out;

.editor-post-featured-image__action {
backdrop-filter: blur(16px) saturate(180%);
background: rgba(255, 255, 255, 0.75);
flex-grow: 1;
justify-content: center;
.editor-post-featured-image__action {
backdrop-filter: blur(16px) saturate(180%);
background: rgba(255, 255, 255, 0.75);
}
}

.editor-post-featured-image__action {
flex-grow: 1;
justify-content: center;
}
}

0 comments on commit 7300373

Please sign in to comment.