From b628e5bce633cc665bf0ca8ac98daebc832abae5 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 1 Apr 2022 14:12:29 +0300 Subject: [PATCH 01/17] [Document Settings]: Add summary panel version 1 --- .../components/sidebar/post-summary/index.js | 71 +++++ .../components/sidebar/post-title/index.js | 26 ++ .../sidebar/settings-sidebar/index.js | 2 + packages/editor/src/components/index.js | 3 + .../src/components/post-author/index.js | 4 +- .../src/components/post-author/select.js | 3 +- .../src/components/post-excerpt2/check.js | 10 + .../src/components/post-excerpt2/index.js | 43 +++ .../src/components/post-excerpt2/style.scss | 4 + .../components/post-featured-image2/README.md | 53 ++++ .../components/post-featured-image2/check.js | 15 + .../components/post-featured-image2/index.js | 266 ++++++++++++++++++ .../post-featured-image2/style.scss | 61 ++++ packages/editor/src/style.scss | 2 + 14 files changed, 560 insertions(+), 3 deletions(-) create mode 100644 packages/edit-post/src/components/sidebar/post-summary/index.js create mode 100644 packages/edit-post/src/components/sidebar/post-title/index.js create mode 100644 packages/editor/src/components/post-excerpt2/check.js create mode 100644 packages/editor/src/components/post-excerpt2/index.js create mode 100644 packages/editor/src/components/post-excerpt2/style.scss create mode 100644 packages/editor/src/components/post-featured-image2/README.md create mode 100644 packages/editor/src/components/post-featured-image2/check.js create mode 100644 packages/editor/src/components/post-featured-image2/index.js create mode 100644 packages/editor/src/components/post-featured-image2/style.scss diff --git a/packages/edit-post/src/components/sidebar/post-summary/index.js b/packages/edit-post/src/components/sidebar/post-summary/index.js new file mode 100644 index 00000000000000..112f67e47f7669 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-summary/index.js @@ -0,0 +1,71 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { PanelBody, PanelRow } from '@wordpress/components'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { + PostFeaturedImageCheck, + PostFeaturedImage2 as PostFeaturedImage, + PostExcerptCheck, + PostExcerpt2 as PostExcerpt, + PostAuthor, +} from '@wordpress/editor'; + +/** + * Internal dependencies + */ +import PostTitle from '../post-title'; +import { store as editPostStore } from '../../../store'; + +/** + * Module Constants + */ +const PANEL_NAME = 'post-summary'; + +function PostSummary() { + // TODO: check about the below logic and the preferences panels... + + const { isRemoved, isOpened } = useSelect( ( select ) => { + // We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do + // not use isEditorPanelEnabled since this panel should not be disabled through the UI. + const { isEditorPanelRemoved, isEditorPanelOpened } = select( + editPostStore + ); + return { + isRemoved: isEditorPanelRemoved( PANEL_NAME ), + isOpened: isEditorPanelOpened( PANEL_NAME ), + }; + }, [] ); + const { toggleEditorPanelOpened } = useDispatch( editPostStore ); + + if ( isRemoved ) { + return null; + } + return ( + toggleEditorPanelOpened( PANEL_NAME ) } + > + + + + + + + { /* Todo: I need to check/consolidate with panels preferences */ } + + + + + + + + + + ); +} + +export default PostSummary; diff --git a/packages/edit-post/src/components/sidebar/post-title/index.js b/packages/edit-post/src/components/sidebar/post-title/index.js new file mode 100644 index 00000000000000..aa701b932c3cd2 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-title/index.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { PlainText } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; +import { store as editorStore } from '@wordpress/editor'; +import { useSelect, useDispatch } from '@wordpress/data'; + +function PostTitle() { + const { editPost } = useDispatch( editorStore ); + const postTitle = useSelect( + ( select ) => select( editorStore ).getEditedPostAttribute( 'title' ), + [] + ); + return ( + editPost( { title } ) } + __experimentalVersion={ 2 } + /> + ); +} + +export default PostTitle; diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js index c6f5234e33cd5c..ea59eb60345ce7 100644 --- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js @@ -14,6 +14,7 @@ import { store as interfaceStore } from '@wordpress/interface'; * Internal dependencies */ import SettingsHeader from '../settings-header'; +import PostSummary from '../post-summary'; import PostStatus from '../post-status'; import LastRevision from '../last-revision'; import PostTaxonomies from '../post-taxonomies'; @@ -85,6 +86,7 @@ const SettingsSidebar = () => { > { ! isTemplateMode && sidebarName === 'edit-post/document' && ( <> + <PostSummary /> <PostStatus /> <Template /> <PluginDocumentSettingPanel.Slot /> diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index b89ef342a58628..3309b3b9b94e1b 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -23,8 +23,11 @@ export { default as PostAuthor } from './post-author'; export { default as PostAuthorCheck } from './post-author/check'; export { default as PostComments } from './post-comments'; export { default as PostExcerpt } from './post-excerpt'; +export { default as PostExcerpt2 } from './post-excerpt2'; export { default as PostExcerptCheck } from './post-excerpt/check'; export { default as PostFeaturedImage } from './post-featured-image'; +// TODO: of course rename :) and check possible deprecations.. +export { default as PostFeaturedImage2 } from './post-featured-image2'; export { default as PostFeaturedImageCheck } from './post-featured-image/check'; export { default as PostFormat } from './post-format'; export { default as PostFormatCheck } from './post-format/check'; diff --git a/packages/editor/src/components/post-author/index.js b/packages/editor/src/components/post-author/index.js index 7e734379f64f64..4fe59989d5e0ea 100644 --- a/packages/editor/src/components/post-author/index.js +++ b/packages/editor/src/components/post-author/index.js @@ -13,7 +13,7 @@ import { AUTHORS_QUERY } from './constants'; const minimumUsersForCombobox = 25; -function PostAuthor() { +function PostAuthor( { labelPosition } ) { const showCombobox = useSelect( ( select ) => { const authors = select( coreStore ).getUsers( AUTHORS_QUERY ); @@ -23,7 +23,7 @@ function PostAuthor() { if ( showCombobox ) { return <PostAuthorCombobox />; } - return <PostAuthorSelect />; + return <PostAuthorSelect labelPosition={ labelPosition } />; } export default PostAuthor; diff --git a/packages/editor/src/components/post-author/select.js b/packages/editor/src/components/post-author/select.js index fee86bf491f720..15f1e4020bd199 100644 --- a/packages/editor/src/components/post-author/select.js +++ b/packages/editor/src/components/post-author/select.js @@ -14,7 +14,7 @@ import { store as coreStore } from '@wordpress/core-data'; import { store as editorStore } from '../../store'; import { AUTHORS_QUERY } from './constants'; -function PostAuthorSelect() { +function PostAuthorSelect( { labelPosition } ) { const { editPost } = useDispatch( editorStore ); const { postAuthor, authors } = useSelect( ( select ) => { return { @@ -46,6 +46,7 @@ function PostAuthorSelect() { options={ authorOptions } onChange={ setAuthorId } value={ postAuthor } + labelPosition={ labelPosition } /> ); } diff --git a/packages/editor/src/components/post-excerpt2/check.js b/packages/editor/src/components/post-excerpt2/check.js new file mode 100644 index 00000000000000..a94a5badec180c --- /dev/null +++ b/packages/editor/src/components/post-excerpt2/check.js @@ -0,0 +1,10 @@ +/** + * Internal dependencies + */ +import PostTypeSupportCheck from '../post-type-support-check'; + +function PostExcerptCheck( props ) { + return <PostTypeSupportCheck { ...props } supportKeys="excerpt" />; +} + +export default PostExcerptCheck; diff --git a/packages/editor/src/components/post-excerpt2/index.js b/packages/editor/src/components/post-excerpt2/index.js new file mode 100644 index 00000000000000..55d7c937f40f44 --- /dev/null +++ b/packages/editor/src/components/post-excerpt2/index.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { ExternalLink } from '@wordpress/components'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { RichText } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; + +function PostExcerpt2() { + const { editPost } = useDispatch( editorStore ); + const excerpt = useSelect( + ( select ) => select( editorStore ).getEditedPostAttribute( 'excerpt' ), + [] + ); + return ( + <div className="editor-post-excerpt"> + <RichText + className="" + aria-label={ __( 'Post excerpt text' ) } + placeholder={ __( 'Add excerpt' ) } + value={ excerpt } + onChange={ ( newExcerpt ) => + editPost( { excerpt: newExcerpt } ) + } + tagName="p" + /> + <ExternalLink + href={ __( + 'https://wordpress.org/support/article/settings-sidebar/#excerpt' + ) } + > + { __( 'Learn more about manual excerpts' ) } + </ExternalLink> + </div> + ); +} + +export default PostExcerpt2; diff --git a/packages/editor/src/components/post-excerpt2/style.scss b/packages/editor/src/components/post-excerpt2/style.scss new file mode 100644 index 00000000000000..056d81ad36c731 --- /dev/null +++ b/packages/editor/src/components/post-excerpt2/style.scss @@ -0,0 +1,4 @@ +.editor-post-excerpt__textarea { + width: 100%; + margin-bottom: 10px; +} diff --git a/packages/editor/src/components/post-featured-image2/README.md b/packages/editor/src/components/post-featured-image2/README.md new file mode 100644 index 00000000000000..9b1520228703fb --- /dev/null +++ b/packages/editor/src/components/post-featured-image2/README.md @@ -0,0 +1,53 @@ +# PostFeaturedImage + +`PostFeaturedImage` is a React component used to render the Post Featured Image selection tool. + +## Setup + +It includes a `wp.hooks` filter `editor.PostFeaturedImage` that enables developers to replace or extend it. + +_Examples:_ + +Replace the contents of the panel: + +```js +function replacePostFeaturedImage() { + return function () { + return wp.element.createElement( + 'div', + {}, + 'The replacement contents or components.' + ); + }; +} + +wp.hooks.addFilter( + 'editor.PostFeaturedImage', + 'my-plugin/replace-post-featured-image', + replacePostFeaturedImage +); +``` + +Prepend and append to the panel contents: + +```js +var el = wp.element.createElement; + +function wrapPostFeaturedImage( OriginalComponent ) { + return function ( props ) { + return el( + wp.element.Fragment, + {}, + 'Prepend above', + el( OriginalComponent, props ), + 'Append below' + ); + }; +} + +wp.hooks.addFilter( + 'editor.PostFeaturedImage', + 'my-plugin/wrap-post-featured-image', + wrapPostFeaturedImage +); +``` diff --git a/packages/editor/src/components/post-featured-image2/check.js b/packages/editor/src/components/post-featured-image2/check.js new file mode 100644 index 00000000000000..5481deaa81604b --- /dev/null +++ b/packages/editor/src/components/post-featured-image2/check.js @@ -0,0 +1,15 @@ +/** + * Internal dependencies + */ +import PostTypeSupportCheck from '../post-type-support-check'; +import ThemeSupportCheck from '../theme-support-check'; + +function PostFeaturedImageCheck( props ) { + return ( + <ThemeSupportCheck supportKeys="post-thumbnails"> + <PostTypeSupportCheck { ...props } supportKeys="thumbnail" /> + </ThemeSupportCheck> + ); +} + +export default PostFeaturedImageCheck; diff --git a/packages/editor/src/components/post-featured-image2/index.js b/packages/editor/src/components/post-featured-image2/index.js new file mode 100644 index 00000000000000..48c30deed2bcb0 --- /dev/null +++ b/packages/editor/src/components/post-featured-image2/index.js @@ -0,0 +1,266 @@ +/** + * External dependencies + */ +import { has, get } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { applyFilters } from '@wordpress/hooks'; +import { + DropZone, + Button, + Spinner, + ResponsiveWrapper, + withNotices, + withFilters, +} from '@wordpress/components'; +import { compose } from '@wordpress/compose'; +import { withSelect, withDispatch } from '@wordpress/data'; +import { + MediaUpload, + MediaUploadCheck, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { store as coreStore } from '@wordpress/core-data'; + +/** + * Internal dependencies + */ +import PostFeaturedImageCheck from './check'; +import { store as editorStore } from '../../store'; + +const ALLOWED_MEDIA_TYPES = [ 'image' ]; + +// Used when labels from post type were not yet loaded or when they are not present. +const DEFAULT_FEATURE_IMAGE_LABEL = __( 'Featured image' ); +const DEFAULT_SET_FEATURE_IMAGE_LABEL = __( 'Set featured image' ); +const DEFAULT_REMOVE_FEATURE_IMAGE_LABEL = __( 'Remove image' ); + +function PostFeaturedImage( { + currentPostId, + featuredImageId, + onUpdateImage, + onDropImage, + onRemoveImage, + media, + postType, + noticeUI, +} ) { + const postLabel = get( postType, [ 'labels' ], {} ); + const instructions = ( + <p> + { __( + 'To edit the featured image, you need permission to upload media.' + ) } + </p> + ); + + let mediaWidth, mediaHeight, mediaSourceUrl; + if ( media ) { + const mediaSize = applyFilters( + 'editor.PostFeaturedImage.imageSize', + 'post-thumbnail', + media.id, + currentPostId + ); + if ( has( media, [ 'media_details', 'sizes', mediaSize ] ) ) { + // Use mediaSize when available. + mediaWidth = media.media_details.sizes[ mediaSize ].width; + mediaHeight = media.media_details.sizes[ mediaSize ].height; + mediaSourceUrl = media.media_details.sizes[ mediaSize ].source_url; + } else { + // Get fallbackMediaSize if mediaSize is not available. + const fallbackMediaSize = applyFilters( + 'editor.PostFeaturedImage.imageSize', + 'thumbnail', + media.id, + currentPostId + ); + if ( + has( media, [ 'media_details', 'sizes', fallbackMediaSize ] ) + ) { + // Use fallbackMediaSize when mediaSize is not available. + mediaWidth = + media.media_details.sizes[ fallbackMediaSize ].width; + mediaHeight = + media.media_details.sizes[ fallbackMediaSize ].height; + mediaSourceUrl = + media.media_details.sizes[ fallbackMediaSize ].source_url; + } else { + // Use full image size when mediaFallbackSize and mediaSize are not available. + mediaWidth = media.media_details.width; + mediaHeight = media.media_details.height; + mediaSourceUrl = media.source_url; + } + } + } + + return ( + <PostFeaturedImageCheck> + { noticeUI } + <div className="editor-post-featured-image"> + { media && ( + <div + id={ `editor-post-featured-image-${ featuredImageId }-describedby` } + className="hidden" + > + { media.alt_text && + sprintf( + // Translators: %s: The selected image alt text. + __( 'Current image: %s' ), + media.alt_text + ) } + { ! media.alt_text && + sprintf( + // Translators: %s: The selected image filename. + __( + 'The current image has no alternative text. The file name is: %s' + ), + media.media_details.sizes?.full?.file || + media.slug + ) } + </div> + ) } + <MediaUploadCheck fallback={ instructions }> + <MediaUpload + title={ + postLabel.featured_image || + DEFAULT_FEATURE_IMAGE_LABEL + } + onSelect={ onUpdateImage } + unstableFeaturedImageFlow + allowedTypes={ ALLOWED_MEDIA_TYPES } + modalClass="editor-post-featured-image__media-modal" + render={ ( { open } ) => ( + <div className="editor-post-featured-image__container"> + <Button + className={ + ! featuredImageId + ? 'editor-post-featured-image__toggle' + : 'editor-post-featured-image__preview' + } + onClick={ open } + aria-label={ + ! featuredImageId + ? null + : __( 'Edit or update the image' ) + } + aria-describedby={ + ! featuredImageId + ? null + : `editor-post-featured-image-${ featuredImageId }-describedby` + } + > + { !! featuredImageId && media && ( + <ResponsiveWrapper + naturalWidth={ mediaWidth } + naturalHeight={ mediaHeight } + isInline + > + <img + src={ mediaSourceUrl } + alt="" + /> + </ResponsiveWrapper> + ) } + { !! featuredImageId && ! media && ( + <Spinner /> + ) } + { ! featuredImageId && + ( postLabel.set_featured_image || + DEFAULT_SET_FEATURE_IMAGE_LABEL ) } + </Button> + <DropZone onFilesDrop={ onDropImage } /> + </div> + ) } + value={ featuredImageId } + /> + </MediaUploadCheck> + { !! featuredImageId && media && ! media.isLoading && ( + <MediaUploadCheck> + <MediaUpload + title={ + postLabel.featured_image || + DEFAULT_FEATURE_IMAGE_LABEL + } + onSelect={ onUpdateImage } + unstableFeaturedImageFlow + allowedTypes={ ALLOWED_MEDIA_TYPES } + modalClass="editor-post-featured-image__media-modal" + render={ ( { open } ) => ( + <Button onClick={ open } variant="secondary"> + { __( 'Replace Image' ) } + </Button> + ) } + /> + </MediaUploadCheck> + ) } + { !! featuredImageId && ( + <MediaUploadCheck> + <Button + onClick={ onRemoveImage } + variant="link" + isDestructive + > + { postLabel.remove_featured_image || + DEFAULT_REMOVE_FEATURE_IMAGE_LABEL } + </Button> + </MediaUploadCheck> + ) } + </div> + </PostFeaturedImageCheck> + ); +} + +const applyWithSelect = withSelect( ( select ) => { + const { getMedia, getPostType } = select( coreStore ); + const { getCurrentPostId, getEditedPostAttribute } = select( editorStore ); + const featuredImageId = getEditedPostAttribute( 'featured_media' ); + + return { + media: featuredImageId + ? getMedia( featuredImageId, { context: 'view' } ) + : null, + currentPostId: getCurrentPostId(), + postType: getPostType( getEditedPostAttribute( 'type' ) ), + featuredImageId, + }; +} ); + +const applyWithDispatch = withDispatch( + ( dispatch, { noticeOperations }, { select } ) => { + const { editPost } = dispatch( editorStore ); + return { + onUpdateImage( image ) { + editPost( { featured_media: image.id } ); + }, + onDropImage( filesList ) { + select( blockEditorStore ) + .getSettings() + .mediaUpload( { + allowedTypes: [ 'image' ], + filesList, + onFileChange( [ image ] ) { + editPost( { featured_media: image.id } ); + }, + onError( message ) { + noticeOperations.removeAllNotices(); + noticeOperations.createErrorNotice( message ); + }, + } ); + }, + onRemoveImage() { + editPost( { featured_media: 0 } ); + }, + }; + } +); + +export default compose( + withNotices, + applyWithSelect, + applyWithDispatch, + withFilters( 'editor.PostFeaturedImage' ) +)( PostFeaturedImage ); diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss new file mode 100644 index 00000000000000..965780179e6ef9 --- /dev/null +++ b/packages/editor/src/components/post-featured-image2/style.scss @@ -0,0 +1,61 @@ +.editor-post-featured-image { + padding: 0; + + &__container { + margin-bottom: 1em; + position: relative; + } + + .components-spinner { + position: absolute; + top: 50%; + left: 50%; + margin-top: -9px; + margin-left: -9px; + } + + // Stack consecutive buttons. + .components-button + .components-button { + display: block; + margin-top: 1em; + } + + // This keeps images at their intrinsic size (eg. a 50px + // image will never be wider than 50px). + .components-responsive-wrapper__content { + max-width: 100%; + width: auto; + } +} + +.editor-post-featured-image__toggle, +.editor-post-featured-image__preview { + display: block; + width: 100%; + padding: 0; + transition: all 0.1s ease-out; + @include reduce-motion("transition"); + box-shadow: 0 0 0 0 var(--wp-admin-theme-color); +} + +.editor-post-featured-image__preview { + height: auto; +} + +.editor-post-featured-image__preview:not(:disabled):not([aria-disabled="true"]):focus { + box-shadow: 0 0 0 4px var(--wp-admin-theme-color); +} + +.editor-post-featured-image__toggle { + border-radius: $radius-block-ui; + background-color: $gray-100; + min-height: 90px; + line-height: 20px; + padding: $grid-unit-10 0; + text-align: center; + + &:hover { + background: $gray-300; + color: $gray-900; + } +} diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 88ed59125a939b..1cd60250a82007 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -5,7 +5,9 @@ @import "./components/error-boundary/style.scss"; @import "./components/page-attributes/style.scss"; @import "./components/post-excerpt/style.scss"; +@import "./components/post-excerpt2/style.scss"; @import "./components/post-featured-image/style.scss"; +@import "./components/post-featured-image2/style.scss"; @import "./components/post-format/style.scss"; @import "./components/post-last-revision/style.scss"; @import "./components/post-locked-modal/style.scss"; From 32ccb4176e700e6dfa747a38bc3ff8930dd5b76a Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Fri, 1 Apr 2022 14:09:18 +0200 Subject: [PATCH 02/17] Polish featured image. --- .../components/post-featured-image2/index.js | 155 +++++++++--------- .../post-featured-image2/style.scss | 83 ++++++---- 2 files changed, 134 insertions(+), 104 deletions(-) diff --git a/packages/editor/src/components/post-featured-image2/index.js b/packages/editor/src/components/post-featured-image2/index.js index 48c30deed2bcb0..fb76aeaf0ccf6c 100644 --- a/packages/editor/src/components/post-featured-image2/index.js +++ b/packages/editor/src/components/post-featured-image2/index.js @@ -24,6 +24,7 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; +import { edit, trash } from '@wordpress/icons'; /** * Internal dependencies @@ -123,63 +124,8 @@ function PostFeaturedImage( { ) } </div> ) } - <MediaUploadCheck fallback={ instructions }> - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL - } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <div className="editor-post-featured-image__container"> - <Button - className={ - ! featuredImageId - ? 'editor-post-featured-image__toggle' - : 'editor-post-featured-image__preview' - } - onClick={ open } - aria-label={ - ! featuredImageId - ? null - : __( 'Edit or update the image' ) - } - aria-describedby={ - ! featuredImageId - ? null - : `editor-post-featured-image-${ featuredImageId }-describedby` - } - > - { !! featuredImageId && media && ( - <ResponsiveWrapper - naturalWidth={ mediaWidth } - naturalHeight={ mediaHeight } - isInline - > - <img - src={ mediaSourceUrl } - alt="" - /> - </ResponsiveWrapper> - ) } - { !! featuredImageId && ! media && ( - <Spinner /> - ) } - { ! featuredImageId && - ( postLabel.set_featured_image || - DEFAULT_SET_FEATURE_IMAGE_LABEL ) } - </Button> - <DropZone onFilesDrop={ onDropImage } /> - </div> - ) } - value={ featuredImageId } - /> - </MediaUploadCheck> - { !! featuredImageId && media && ! media.isLoading && ( - <MediaUploadCheck> + <div className="editor-post-featured-image__container"> + <MediaUploadCheck fallback={ instructions }> <MediaUpload title={ postLabel.featured_image || @@ -190,25 +136,88 @@ function PostFeaturedImage( { allowedTypes={ ALLOWED_MEDIA_TYPES } modalClass="editor-post-featured-image__media-modal" render={ ( { open } ) => ( - <Button onClick={ open } variant="secondary"> - { __( 'Replace Image' ) } - </Button> + <> + <Button + className={ + ! featuredImageId + ? 'editor-post-featured-image__toggle' + : 'editor-post-featured-image__preview' + } + onClick={ open } + aria-label={ + ! featuredImageId + ? null + : __( + 'Edit or update the image' + ) + } + aria-describedby={ + ! featuredImageId + ? null + : `editor-post-featured-image-${ featuredImageId }-describedby` + } + > + { !! featuredImageId && media && ( + <ResponsiveWrapper + naturalWidth={ mediaWidth } + naturalHeight={ mediaHeight } + isInline + > + <img + src={ mediaSourceUrl } + alt="" + /> + </ResponsiveWrapper> + ) } + { !! featuredImageId && ! media && ( + <Spinner /> + ) } + { ! featuredImageId && + ( postLabel.set_featured_image || + DEFAULT_SET_FEATURE_IMAGE_LABEL ) } + </Button> + <DropZone onFilesDrop={ onDropImage } /> + </> ) } + value={ featuredImageId } /> </MediaUploadCheck> - ) } - { !! featuredImageId && ( - <MediaUploadCheck> - <Button - onClick={ onRemoveImage } - variant="link" - isDestructive - > - { postLabel.remove_featured_image || - DEFAULT_REMOVE_FEATURE_IMAGE_LABEL } - </Button> - </MediaUploadCheck> - ) } + <div className="editor-post-featured-image__actions"> + { !! featuredImageId && media && ! media.isLoading && ( + <MediaUploadCheck> + <MediaUpload + title={ + postLabel.featured_image || + DEFAULT_FEATURE_IMAGE_LABEL + } + onSelect={ onUpdateImage } + unstableFeaturedImageFlow + allowedTypes={ ALLOWED_MEDIA_TYPES } + modalClass="editor-post-featured-image__media-modal" + render={ ( { open } ) => ( + <Button + label={ __( 'Replace Image' ) } + icon={ edit } + onClick={ open } + /> + ) } + /> + </MediaUploadCheck> + ) } + { !! featuredImageId && ( + <MediaUploadCheck> + <Button + label={ + postLabel.remove_featured_image || + DEFAULT_REMOVE_FEATURE_IMAGE_LABEL + } + icon={ trash } + onClick={ onRemoveImage } + /> + </MediaUploadCheck> + ) } + </div> + </div> </div> </PostFeaturedImageCheck> ); diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss index 965780179e6ef9..5249baa60c0341 100644 --- a/packages/editor/src/components/post-featured-image2/style.scss +++ b/packages/editor/src/components/post-featured-image2/style.scss @@ -1,61 +1,82 @@ .editor-post-featured-image { padding: 0; + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; - &__container { - margin-bottom: 1em; + // Thumbnail container. + .editor-post-featured-image__container { + display: flex; + align-items: center; + justify-content: center; position: relative; } + // @todo: these rules can be removed if we retire post-featured-image. .components-spinner { - position: absolute; - top: 50%; - left: 50%; - margin-top: -9px; - margin-left: -9px; - } - - // Stack consecutive buttons. - .components-button + .components-button { - display: block; - margin-top: 1em; + position: relative; + margin-top: 0; + margin-left: 0; } // This keeps images at their intrinsic size (eg. a 50px // image will never be wider than 50px). + // @todo: we should replace this with loading a higher resolution image and applying object-fit: cover; + // This would also afford a refactor to use the image as a background, which would fix the cropped inset focus style. .components-responsive-wrapper__content { max-width: 100%; width: auto; } + + // Edit/Replace action buttons. + // @todo: container could be replaced with a flex container. + .editor-post-featured-image__actions { + position: absolute; + display: flex; + background: $white; + border-radius: $radius-block-ui; + bottom: $grid-unit-20; + right: $grid-unit-20; + opacity: 0; + transition: all 0.1s ease-out; + @include reduce-motion("transition"); + + // @todo: these rules can be removed if we retire post-featured-image. + .components-button + .components-button { + display: block; + margin-top: 0; + } + } + + &:focus .editor-post-featured-image__actions, + &:hover .editor-post-featured-image__actions { + opacity: 1; + } } + +// Button to set featured image when an image is set. .editor-post-featured-image__toggle, .editor-post-featured-image__preview { display: block; width: 100%; padding: 0; - transition: all 0.1s ease-out; - @include reduce-motion("transition"); - box-shadow: 0 0 0 0 var(--wp-admin-theme-color); -} - -.editor-post-featured-image__preview { - height: auto; -} - -.editor-post-featured-image__preview:not(:disabled):not([aria-disabled="true"]):focus { - box-shadow: 0 0 0 4px var(--wp-admin-theme-color); -} - -.editor-post-featured-image__toggle { - border-radius: $radius-block-ui; background-color: $gray-100; - min-height: 90px; - line-height: 20px; - padding: $grid-unit-10 0; + border-radius: 0; + min-height: 140px; + height: auto; text-align: center; &:hover { background: $gray-300; color: $gray-900; } + + // Override generic focus styles to be inset. + &:focus:not(:disabled), + &:not(:disabled):not([aria-disabled="true"]):focus { + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + } + + transition: all 0.1s ease-out; + @include reduce-motion("transition"); } From 0874b3973ebd38f84394ed58eca4a4551311c33e Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Fri, 1 Apr 2022 14:14:53 +0200 Subject: [PATCH 03/17] Tweak excerpt. --- packages/editor/src/components/post-excerpt2/index.js | 8 -------- packages/editor/src/components/post-excerpt2/style.scss | 4 ---- packages/editor/src/style.scss | 1 - 3 files changed, 13 deletions(-) delete mode 100644 packages/editor/src/components/post-excerpt2/style.scss diff --git a/packages/editor/src/components/post-excerpt2/index.js b/packages/editor/src/components/post-excerpt2/index.js index 55d7c937f40f44..f4ef71d96fd873 100644 --- a/packages/editor/src/components/post-excerpt2/index.js +++ b/packages/editor/src/components/post-excerpt2/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { ExternalLink } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { RichText } from '@wordpress/block-editor'; @@ -29,13 +28,6 @@ function PostExcerpt2() { } tagName="p" /> - <ExternalLink - href={ __( - 'https://wordpress.org/support/article/settings-sidebar/#excerpt' - ) } - > - { __( 'Learn more about manual excerpts' ) } - </ExternalLink> </div> ); } diff --git a/packages/editor/src/components/post-excerpt2/style.scss b/packages/editor/src/components/post-excerpt2/style.scss deleted file mode 100644 index 056d81ad36c731..00000000000000 --- a/packages/editor/src/components/post-excerpt2/style.scss +++ /dev/null @@ -1,4 +0,0 @@ -.editor-post-excerpt__textarea { - width: 100%; - margin-bottom: 10px; -} diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 1cd60250a82007..3f279c70110927 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -5,7 +5,6 @@ @import "./components/error-boundary/style.scss"; @import "./components/page-attributes/style.scss"; @import "./components/post-excerpt/style.scss"; -@import "./components/post-excerpt2/style.scss"; @import "./components/post-featured-image/style.scss"; @import "./components/post-featured-image2/style.scss"; @import "./components/post-format/style.scss"; From 07e2f9fdc7a8e899b35cd7cecc94ee96296019e9 Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Fri, 1 Apr 2022 14:31:07 +0200 Subject: [PATCH 04/17] Fix focus styles for edit and trash. --- packages/editor/src/components/post-featured-image2/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss index 5249baa60c0341..3d4dbe62e66ad3 100644 --- a/packages/editor/src/components/post-featured-image2/style.scss +++ b/packages/editor/src/components/post-featured-image2/style.scss @@ -47,6 +47,7 @@ } } + &:focus-within .editor-post-featured-image__actions, &:focus .editor-post-featured-image__actions, &:hover .editor-post-featured-image__actions { opacity: 1; From fd41ac3741f104c0d569528658549550db6e788c Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Fri, 1 Apr 2022 14:38:13 +0200 Subject: [PATCH 05/17] Fix focus styles. --- .../components/post-featured-image2/style.scss | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss index 3d4dbe62e66ad3..5813a19eeea654 100644 --- a/packages/editor/src/components/post-featured-image2/style.scss +++ b/packages/editor/src/components/post-featured-image2/style.scss @@ -75,9 +75,24 @@ // Override generic focus styles to be inset. &:focus:not(:disabled), &:not(:disabled):not([aria-disabled="true"]):focus { + box-shadow: none; + outline: none; + } + + &:focus:not(:disabled)::after { + content: ""; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Shown for high contrast modes. + outline: 2px solid transparent; } - transition: all 0.1s ease-out; + transition: all 5.1s ease-out; @include reduce-motion("transition"); } From 8f4538d52707ff3bdd5d32a765a303111e8930ff Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Mon, 4 Apr 2022 11:38:39 +0200 Subject: [PATCH 06/17] Improve thumbnail resolution and appearance. --- .../components/post-featured-image2/index.js | 2 +- .../post-featured-image2/style.scss | 29 +++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/editor/src/components/post-featured-image2/index.js b/packages/editor/src/components/post-featured-image2/index.js index fb76aeaf0ccf6c..72f2ae0fa4bba5 100644 --- a/packages/editor/src/components/post-featured-image2/index.js +++ b/packages/editor/src/components/post-featured-image2/index.js @@ -62,7 +62,7 @@ function PostFeaturedImage( { if ( media ) { const mediaSize = applyFilters( 'editor.PostFeaturedImage.imageSize', - 'post-thumbnail', + 'large', media.id, currentPostId ); diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss index 5813a19eeea654..fb778fbea20146 100644 --- a/packages/editor/src/components/post-featured-image2/style.scss +++ b/packages/editor/src/components/post-featured-image2/style.scss @@ -3,25 +3,42 @@ margin-left: -$grid-unit-20; margin-right: -$grid-unit-20; + // Ensure a consistent dropzone and avoid jumps when loading. + height: 140px; + overflow: hidden; + // Thumbnail container. .editor-post-featured-image__container { display: flex; align-items: center; justify-content: center; position: relative; + height: 100%; } - // @todo: these rules can be removed if we retire post-featured-image. .components-spinner { - position: relative; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + // @todo: these rules can be removed if we retire post-featured-image. margin-top: 0; margin-left: 0; } + // Always center the content inside the cropped thumbnail. + .components-responsive-wrapper { + position: absolute; + width: 100%; + height: 100%; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + // This keeps images at their intrinsic size (eg. a 50px // image will never be wider than 50px). - // @todo: we should replace this with loading a higher resolution image and applying object-fit: cover; - // This would also afford a refactor to use the image as a background, which would fix the cropped inset focus style. .components-responsive-wrapper__content { max-width: 100%; width: auto; @@ -58,13 +75,13 @@ // Button to set featured image when an image is set. .editor-post-featured-image__toggle, .editor-post-featured-image__preview { + position: relative; display: block; width: 100%; padding: 0; background-color: $gray-100; border-radius: 0; - min-height: 140px; - height: auto; + height: 100%; text-align: center; &:hover { From 2302eb67ff09a832d9f54c29d53bf39f2e20da03 Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 16:02:29 +0300 Subject: [PATCH 07/17] update FeaturedImage in inspector controls + remove the previous panel. The preference for displaying the previous panel is still respected and will show/hide the featured image from `post summary` now. --- .../sidebar/featured-image/index.js | 61 +--- .../components/sidebar/post-summary/index.js | 7 +- .../sidebar/settings-sidebar/index.js | 2 - packages/editor/src/components/index.js | 3 +- .../components/post-featured-image/index.js | 157 +++++----- .../components/post-featured-image/style.scss | 105 +++++-- .../components/post-featured-image2/README.md | 53 ---- .../components/post-featured-image2/check.js | 15 - .../components/post-featured-image2/index.js | 275 ------------------ .../post-featured-image2/style.scss | 115 -------- 10 files changed, 174 insertions(+), 619 deletions(-) delete mode 100644 packages/editor/src/components/post-featured-image2/README.md delete mode 100644 packages/editor/src/components/post-featured-image2/check.js delete mode 100644 packages/editor/src/components/post-featured-image2/index.js delete mode 100644 packages/editor/src/components/post-featured-image2/style.scss diff --git a/packages/edit-post/src/components/sidebar/featured-image/index.js b/packages/edit-post/src/components/sidebar/featured-image/index.js index 50e8356bb8dc41..51cec18c61493d 100644 --- a/packages/edit-post/src/components/sidebar/featured-image/index.js +++ b/packages/edit-post/src/components/sidebar/featured-image/index.js @@ -1,21 +1,8 @@ -/** - * External dependencies - */ -import { get, partial } from 'lodash'; - /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { PanelBody } from '@wordpress/components'; -import { - PostFeaturedImage, - PostFeaturedImageCheck, - store as editorStore, -} from '@wordpress/editor'; -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { PostFeaturedImage, PostFeaturedImageCheck } from '@wordpress/editor'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -27,48 +14,18 @@ import { store as editPostStore } from '../../../store'; */ const PANEL_NAME = 'featured-image'; -function FeaturedImage( { isEnabled, isOpened, postType, onTogglePanel } ) { +export default function FeaturedImage() { + const isEnabled = useSelect( + ( select ) => + select( editPostStore ).isEditorPanelEnabled( PANEL_NAME ), + [] + ); if ( ! isEnabled ) { return null; } - return ( <PostFeaturedImageCheck> - <PanelBody - title={ get( - postType, - [ 'labels', 'featured_image' ], - __( 'Featured image' ) - ) } - opened={ isOpened } - onToggle={ onTogglePanel } - > - <PostFeaturedImage /> - </PanelBody> + <PostFeaturedImage /> </PostFeaturedImageCheck> ); } - -const applyWithSelect = withSelect( ( select ) => { - const { getEditedPostAttribute } = select( editorStore ); - const { getPostType } = select( coreStore ); - const { isEditorPanelEnabled, isEditorPanelOpened } = select( - editPostStore - ); - - return { - postType: getPostType( getEditedPostAttribute( 'type' ) ), - isEnabled: isEditorPanelEnabled( PANEL_NAME ), - isOpened: isEditorPanelOpened( PANEL_NAME ), - }; -} ); - -const applyWithDispatch = withDispatch( ( dispatch ) => { - const { toggleEditorPanelOpened } = dispatch( editPostStore ); - - return { - onTogglePanel: partial( toggleEditorPanelOpened, PANEL_NAME ), - }; -} ); - -export default compose( applyWithSelect, applyWithDispatch )( FeaturedImage ); diff --git a/packages/edit-post/src/components/sidebar/post-summary/index.js b/packages/edit-post/src/components/sidebar/post-summary/index.js index 112f67e47f7669..6a78f8ef319574 100644 --- a/packages/edit-post/src/components/sidebar/post-summary/index.js +++ b/packages/edit-post/src/components/sidebar/post-summary/index.js @@ -5,8 +5,6 @@ import { __ } from '@wordpress/i18n'; import { PanelBody, PanelRow } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { - PostFeaturedImageCheck, - PostFeaturedImage2 as PostFeaturedImage, PostExcerptCheck, PostExcerpt2 as PostExcerpt, PostAuthor, @@ -16,6 +14,7 @@ import { * Internal dependencies */ import PostTitle from '../post-title'; +import FeaturedImage from '../featured-image'; import { store as editPostStore } from '../../../store'; /** @@ -49,9 +48,7 @@ function PostSummary() { opened={ isOpened } onToggle={ () => toggleEditorPanelOpened( PANEL_NAME ) } > - <PostFeaturedImageCheck> - <PostFeaturedImage /> - </PostFeaturedImageCheck> + <FeaturedImage /> <PanelRow> <PostTitle /> </PanelRow> diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js index ea59eb60345ce7..a6ab784b7a64c4 100644 --- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js @@ -18,7 +18,6 @@ import PostSummary from '../post-summary'; import PostStatus from '../post-status'; import LastRevision from '../last-revision'; import PostTaxonomies from '../post-taxonomies'; -import FeaturedImage from '../featured-image'; import PostExcerpt from '../post-excerpt'; import PostLink from '../post-link'; import DiscussionPanel from '../discussion-panel'; @@ -93,7 +92,6 @@ const SettingsSidebar = () => { <LastRevision /> <PostLink /> <PostTaxonomies /> - <FeaturedImage /> <PostExcerpt /> <DiscussionPanel /> <PageAttributes /> diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index 3309b3b9b94e1b..cb023863439f7b 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -23,11 +23,10 @@ export { default as PostAuthor } from './post-author'; export { default as PostAuthorCheck } from './post-author/check'; export { default as PostComments } from './post-comments'; export { default as PostExcerpt } from './post-excerpt'; +// TODO: of course rename :) and check possible deprecations.. export { default as PostExcerpt2 } from './post-excerpt2'; export { default as PostExcerptCheck } from './post-excerpt/check'; export { default as PostFeaturedImage } from './post-featured-image'; -// TODO: of course rename :) and check possible deprecations.. -export { default as PostFeaturedImage2 } from './post-featured-image2'; export { default as PostFeaturedImageCheck } from './post-featured-image/check'; export { default as PostFormat } from './post-format'; export { default as PostFormatCheck } from './post-format/check'; diff --git a/packages/editor/src/components/post-featured-image/index.js b/packages/editor/src/components/post-featured-image/index.js index 48c30deed2bcb0..72f2ae0fa4bba5 100644 --- a/packages/editor/src/components/post-featured-image/index.js +++ b/packages/editor/src/components/post-featured-image/index.js @@ -24,6 +24,7 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { store as coreStore } from '@wordpress/core-data'; +import { edit, trash } from '@wordpress/icons'; /** * Internal dependencies @@ -61,7 +62,7 @@ function PostFeaturedImage( { if ( media ) { const mediaSize = applyFilters( 'editor.PostFeaturedImage.imageSize', - 'post-thumbnail', + 'large', media.id, currentPostId ); @@ -123,63 +124,8 @@ function PostFeaturedImage( { ) } </div> ) } - <MediaUploadCheck fallback={ instructions }> - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL - } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <div className="editor-post-featured-image__container"> - <Button - className={ - ! featuredImageId - ? 'editor-post-featured-image__toggle' - : 'editor-post-featured-image__preview' - } - onClick={ open } - aria-label={ - ! featuredImageId - ? null - : __( 'Edit or update the image' ) - } - aria-describedby={ - ! featuredImageId - ? null - : `editor-post-featured-image-${ featuredImageId }-describedby` - } - > - { !! featuredImageId && media && ( - <ResponsiveWrapper - naturalWidth={ mediaWidth } - naturalHeight={ mediaHeight } - isInline - > - <img - src={ mediaSourceUrl } - alt="" - /> - </ResponsiveWrapper> - ) } - { !! featuredImageId && ! media && ( - <Spinner /> - ) } - { ! featuredImageId && - ( postLabel.set_featured_image || - DEFAULT_SET_FEATURE_IMAGE_LABEL ) } - </Button> - <DropZone onFilesDrop={ onDropImage } /> - </div> - ) } - value={ featuredImageId } - /> - </MediaUploadCheck> - { !! featuredImageId && media && ! media.isLoading && ( - <MediaUploadCheck> + <div className="editor-post-featured-image__container"> + <MediaUploadCheck fallback={ instructions }> <MediaUpload title={ postLabel.featured_image || @@ -190,25 +136,88 @@ function PostFeaturedImage( { allowedTypes={ ALLOWED_MEDIA_TYPES } modalClass="editor-post-featured-image__media-modal" render={ ( { open } ) => ( - <Button onClick={ open } variant="secondary"> - { __( 'Replace Image' ) } - </Button> + <> + <Button + className={ + ! featuredImageId + ? 'editor-post-featured-image__toggle' + : 'editor-post-featured-image__preview' + } + onClick={ open } + aria-label={ + ! featuredImageId + ? null + : __( + 'Edit or update the image' + ) + } + aria-describedby={ + ! featuredImageId + ? null + : `editor-post-featured-image-${ featuredImageId }-describedby` + } + > + { !! featuredImageId && media && ( + <ResponsiveWrapper + naturalWidth={ mediaWidth } + naturalHeight={ mediaHeight } + isInline + > + <img + src={ mediaSourceUrl } + alt="" + /> + </ResponsiveWrapper> + ) } + { !! featuredImageId && ! media && ( + <Spinner /> + ) } + { ! featuredImageId && + ( postLabel.set_featured_image || + DEFAULT_SET_FEATURE_IMAGE_LABEL ) } + </Button> + <DropZone onFilesDrop={ onDropImage } /> + </> ) } + value={ featuredImageId } /> </MediaUploadCheck> - ) } - { !! featuredImageId && ( - <MediaUploadCheck> - <Button - onClick={ onRemoveImage } - variant="link" - isDestructive - > - { postLabel.remove_featured_image || - DEFAULT_REMOVE_FEATURE_IMAGE_LABEL } - </Button> - </MediaUploadCheck> - ) } + <div className="editor-post-featured-image__actions"> + { !! featuredImageId && media && ! media.isLoading && ( + <MediaUploadCheck> + <MediaUpload + title={ + postLabel.featured_image || + DEFAULT_FEATURE_IMAGE_LABEL + } + onSelect={ onUpdateImage } + unstableFeaturedImageFlow + allowedTypes={ ALLOWED_MEDIA_TYPES } + modalClass="editor-post-featured-image__media-modal" + render={ ( { open } ) => ( + <Button + label={ __( 'Replace Image' ) } + icon={ edit } + onClick={ open } + /> + ) } + /> + </MediaUploadCheck> + ) } + { !! featuredImageId && ( + <MediaUploadCheck> + <Button + label={ + postLabel.remove_featured_image || + DEFAULT_REMOVE_FEATURE_IMAGE_LABEL + } + icon={ trash } + onClick={ onRemoveImage } + /> + </MediaUploadCheck> + ) } + </div> + </div> </div> </PostFeaturedImageCheck> ); diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index 965780179e6ef9..01ae28f0e97b58 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -1,23 +1,40 @@ .editor-post-featured-image { padding: 0; + margin-left: -$grid-unit-20; + margin-right: -$grid-unit-20; - &__container { - margin-bottom: 1em; + // Ensure a consistent dropzone and avoid jumps when loading. + height: 140px; + overflow: hidden; + + // Thumbnail container. + .editor-post-featured-image__container { + display: flex; + align-items: center; + justify-content: center; position: relative; + height: 100%; } .components-spinner { position: absolute; top: 50%; left: 50%; - margin-top: -9px; - margin-left: -9px; + transform: translate(-50%, -50%); + + // @todo: these rules can be removed if we retire post-featured-image. + margin-top: 0; + margin-left: 0; } - // Stack consecutive buttons. - .components-button + .components-button { - display: block; - margin-top: 1em; + // Always center the content inside the cropped thumbnail. + .components-responsive-wrapper { + position: absolute; + width: 100%; + height: 100%; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } // This keeps images at their intrinsic size (eg. a 50px @@ -26,36 +43,72 @@ max-width: 100%; width: auto; } + + // Edit/Replace action buttons. + // @todo: container could be replaced with a flex container. + .editor-post-featured-image__actions { + position: absolute; + display: flex; + background: $white; + border-radius: $radius-block-ui; + bottom: $grid-unit-20; + right: $grid-unit-20; + opacity: 0; + transition: all 0.1s ease-out; + @include reduce-motion("transition"); + + // @todo: these rules can be removed if we retire post-featured-image. + .components-button + .components-button { + display: block; + margin-top: 0; + } + } + + &:focus-within .editor-post-featured-image__actions, + &:focus .editor-post-featured-image__actions, + &:hover .editor-post-featured-image__actions { + opacity: 1; + } } +// Button to set featured image when an image is set. .editor-post-featured-image__toggle, .editor-post-featured-image__preview { + position: relative; display: block; width: 100%; padding: 0; - transition: all 0.1s ease-out; - @include reduce-motion("transition"); - box-shadow: 0 0 0 0 var(--wp-admin-theme-color); -} - -.editor-post-featured-image__preview { - height: auto; -} - -.editor-post-featured-image__preview:not(:disabled):not([aria-disabled="true"]):focus { - box-shadow: 0 0 0 4px var(--wp-admin-theme-color); -} - -.editor-post-featured-image__toggle { - border-radius: $radius-block-ui; background-color: $gray-100; - min-height: 90px; - line-height: 20px; - padding: $grid-unit-10 0; + border-radius: 0; + height: 100%; text-align: center; &:hover { background: $gray-300; color: $gray-900; } + + // Override generic focus styles to be inset. + &:focus:not(:disabled), + &:not(:disabled):not([aria-disabled="true"]):focus { + box-shadow: none; + outline: none; + } + + &:focus:not(:disabled)::after { + content: ""; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Shown for high contrast modes. + outline: 2px solid transparent; + } + + transition: all 5.1s ease-out; + @include reduce-motion("transition"); } diff --git a/packages/editor/src/components/post-featured-image2/README.md b/packages/editor/src/components/post-featured-image2/README.md deleted file mode 100644 index 9b1520228703fb..00000000000000 --- a/packages/editor/src/components/post-featured-image2/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# PostFeaturedImage - -`PostFeaturedImage` is a React component used to render the Post Featured Image selection tool. - -## Setup - -It includes a `wp.hooks` filter `editor.PostFeaturedImage` that enables developers to replace or extend it. - -_Examples:_ - -Replace the contents of the panel: - -```js -function replacePostFeaturedImage() { - return function () { - return wp.element.createElement( - 'div', - {}, - 'The replacement contents or components.' - ); - }; -} - -wp.hooks.addFilter( - 'editor.PostFeaturedImage', - 'my-plugin/replace-post-featured-image', - replacePostFeaturedImage -); -``` - -Prepend and append to the panel contents: - -```js -var el = wp.element.createElement; - -function wrapPostFeaturedImage( OriginalComponent ) { - return function ( props ) { - return el( - wp.element.Fragment, - {}, - 'Prepend above', - el( OriginalComponent, props ), - 'Append below' - ); - }; -} - -wp.hooks.addFilter( - 'editor.PostFeaturedImage', - 'my-plugin/wrap-post-featured-image', - wrapPostFeaturedImage -); -``` diff --git a/packages/editor/src/components/post-featured-image2/check.js b/packages/editor/src/components/post-featured-image2/check.js deleted file mode 100644 index 5481deaa81604b..00000000000000 --- a/packages/editor/src/components/post-featured-image2/check.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Internal dependencies - */ -import PostTypeSupportCheck from '../post-type-support-check'; -import ThemeSupportCheck from '../theme-support-check'; - -function PostFeaturedImageCheck( props ) { - return ( - <ThemeSupportCheck supportKeys="post-thumbnails"> - <PostTypeSupportCheck { ...props } supportKeys="thumbnail" /> - </ThemeSupportCheck> - ); -} - -export default PostFeaturedImageCheck; diff --git a/packages/editor/src/components/post-featured-image2/index.js b/packages/editor/src/components/post-featured-image2/index.js deleted file mode 100644 index 72f2ae0fa4bba5..00000000000000 --- a/packages/editor/src/components/post-featured-image2/index.js +++ /dev/null @@ -1,275 +0,0 @@ -/** - * External dependencies - */ -import { has, get } from 'lodash'; - -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; -import { applyFilters } from '@wordpress/hooks'; -import { - DropZone, - Button, - Spinner, - ResponsiveWrapper, - withNotices, - withFilters, -} from '@wordpress/components'; -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { - MediaUpload, - MediaUploadCheck, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { store as coreStore } from '@wordpress/core-data'; -import { edit, trash } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import PostFeaturedImageCheck from './check'; -import { store as editorStore } from '../../store'; - -const ALLOWED_MEDIA_TYPES = [ 'image' ]; - -// Used when labels from post type were not yet loaded or when they are not present. -const DEFAULT_FEATURE_IMAGE_LABEL = __( 'Featured image' ); -const DEFAULT_SET_FEATURE_IMAGE_LABEL = __( 'Set featured image' ); -const DEFAULT_REMOVE_FEATURE_IMAGE_LABEL = __( 'Remove image' ); - -function PostFeaturedImage( { - currentPostId, - featuredImageId, - onUpdateImage, - onDropImage, - onRemoveImage, - media, - postType, - noticeUI, -} ) { - const postLabel = get( postType, [ 'labels' ], {} ); - const instructions = ( - <p> - { __( - 'To edit the featured image, you need permission to upload media.' - ) } - </p> - ); - - let mediaWidth, mediaHeight, mediaSourceUrl; - if ( media ) { - const mediaSize = applyFilters( - 'editor.PostFeaturedImage.imageSize', - 'large', - media.id, - currentPostId - ); - if ( has( media, [ 'media_details', 'sizes', mediaSize ] ) ) { - // Use mediaSize when available. - mediaWidth = media.media_details.sizes[ mediaSize ].width; - mediaHeight = media.media_details.sizes[ mediaSize ].height; - mediaSourceUrl = media.media_details.sizes[ mediaSize ].source_url; - } else { - // Get fallbackMediaSize if mediaSize is not available. - const fallbackMediaSize = applyFilters( - 'editor.PostFeaturedImage.imageSize', - 'thumbnail', - media.id, - currentPostId - ); - if ( - has( media, [ 'media_details', 'sizes', fallbackMediaSize ] ) - ) { - // Use fallbackMediaSize when mediaSize is not available. - mediaWidth = - media.media_details.sizes[ fallbackMediaSize ].width; - mediaHeight = - media.media_details.sizes[ fallbackMediaSize ].height; - mediaSourceUrl = - media.media_details.sizes[ fallbackMediaSize ].source_url; - } else { - // Use full image size when mediaFallbackSize and mediaSize are not available. - mediaWidth = media.media_details.width; - mediaHeight = media.media_details.height; - mediaSourceUrl = media.source_url; - } - } - } - - return ( - <PostFeaturedImageCheck> - { noticeUI } - <div className="editor-post-featured-image"> - { media && ( - <div - id={ `editor-post-featured-image-${ featuredImageId }-describedby` } - className="hidden" - > - { media.alt_text && - sprintf( - // Translators: %s: The selected image alt text. - __( 'Current image: %s' ), - media.alt_text - ) } - { ! media.alt_text && - sprintf( - // Translators: %s: The selected image filename. - __( - 'The current image has no alternative text. The file name is: %s' - ), - media.media_details.sizes?.full?.file || - media.slug - ) } - </div> - ) } - <div className="editor-post-featured-image__container"> - <MediaUploadCheck fallback={ instructions }> - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL - } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <> - <Button - className={ - ! featuredImageId - ? 'editor-post-featured-image__toggle' - : 'editor-post-featured-image__preview' - } - onClick={ open } - aria-label={ - ! featuredImageId - ? null - : __( - 'Edit or update the image' - ) - } - aria-describedby={ - ! featuredImageId - ? null - : `editor-post-featured-image-${ featuredImageId }-describedby` - } - > - { !! featuredImageId && media && ( - <ResponsiveWrapper - naturalWidth={ mediaWidth } - naturalHeight={ mediaHeight } - isInline - > - <img - src={ mediaSourceUrl } - alt="" - /> - </ResponsiveWrapper> - ) } - { !! featuredImageId && ! media && ( - <Spinner /> - ) } - { ! featuredImageId && - ( postLabel.set_featured_image || - DEFAULT_SET_FEATURE_IMAGE_LABEL ) } - </Button> - <DropZone onFilesDrop={ onDropImage } /> - </> - ) } - value={ featuredImageId } - /> - </MediaUploadCheck> - <div className="editor-post-featured-image__actions"> - { !! featuredImageId && media && ! media.isLoading && ( - <MediaUploadCheck> - <MediaUpload - title={ - postLabel.featured_image || - DEFAULT_FEATURE_IMAGE_LABEL - } - onSelect={ onUpdateImage } - unstableFeaturedImageFlow - allowedTypes={ ALLOWED_MEDIA_TYPES } - modalClass="editor-post-featured-image__media-modal" - render={ ( { open } ) => ( - <Button - label={ __( 'Replace Image' ) } - icon={ edit } - onClick={ open } - /> - ) } - /> - </MediaUploadCheck> - ) } - { !! featuredImageId && ( - <MediaUploadCheck> - <Button - label={ - postLabel.remove_featured_image || - DEFAULT_REMOVE_FEATURE_IMAGE_LABEL - } - icon={ trash } - onClick={ onRemoveImage } - /> - </MediaUploadCheck> - ) } - </div> - </div> - </div> - </PostFeaturedImageCheck> - ); -} - -const applyWithSelect = withSelect( ( select ) => { - const { getMedia, getPostType } = select( coreStore ); - const { getCurrentPostId, getEditedPostAttribute } = select( editorStore ); - const featuredImageId = getEditedPostAttribute( 'featured_media' ); - - return { - media: featuredImageId - ? getMedia( featuredImageId, { context: 'view' } ) - : null, - currentPostId: getCurrentPostId(), - postType: getPostType( getEditedPostAttribute( 'type' ) ), - featuredImageId, - }; -} ); - -const applyWithDispatch = withDispatch( - ( dispatch, { noticeOperations }, { select } ) => { - const { editPost } = dispatch( editorStore ); - return { - onUpdateImage( image ) { - editPost( { featured_media: image.id } ); - }, - onDropImage( filesList ) { - select( blockEditorStore ) - .getSettings() - .mediaUpload( { - allowedTypes: [ 'image' ], - filesList, - onFileChange( [ image ] ) { - editPost( { featured_media: image.id } ); - }, - onError( message ) { - noticeOperations.removeAllNotices(); - noticeOperations.createErrorNotice( message ); - }, - } ); - }, - onRemoveImage() { - editPost( { featured_media: 0 } ); - }, - }; - } -); - -export default compose( - withNotices, - applyWithSelect, - applyWithDispatch, - withFilters( 'editor.PostFeaturedImage' ) -)( PostFeaturedImage ); diff --git a/packages/editor/src/components/post-featured-image2/style.scss b/packages/editor/src/components/post-featured-image2/style.scss deleted file mode 100644 index fb778fbea20146..00000000000000 --- a/packages/editor/src/components/post-featured-image2/style.scss +++ /dev/null @@ -1,115 +0,0 @@ -.editor-post-featured-image { - padding: 0; - margin-left: -$grid-unit-20; - margin-right: -$grid-unit-20; - - // Ensure a consistent dropzone and avoid jumps when loading. - height: 140px; - overflow: hidden; - - // Thumbnail container. - .editor-post-featured-image__container { - display: flex; - align-items: center; - justify-content: center; - position: relative; - height: 100%; - } - - .components-spinner { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - - // @todo: these rules can be removed if we retire post-featured-image. - margin-top: 0; - margin-left: 0; - } - - // Always center the content inside the cropped thumbnail. - .components-responsive-wrapper { - position: absolute; - width: 100%; - height: 100%; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - // This keeps images at their intrinsic size (eg. a 50px - // image will never be wider than 50px). - .components-responsive-wrapper__content { - max-width: 100%; - width: auto; - } - - // Edit/Replace action buttons. - // @todo: container could be replaced with a flex container. - .editor-post-featured-image__actions { - position: absolute; - display: flex; - background: $white; - border-radius: $radius-block-ui; - bottom: $grid-unit-20; - right: $grid-unit-20; - opacity: 0; - transition: all 0.1s ease-out; - @include reduce-motion("transition"); - - // @todo: these rules can be removed if we retire post-featured-image. - .components-button + .components-button { - display: block; - margin-top: 0; - } - } - - &:focus-within .editor-post-featured-image__actions, - &:focus .editor-post-featured-image__actions, - &:hover .editor-post-featured-image__actions { - opacity: 1; - } -} - - -// Button to set featured image when an image is set. -.editor-post-featured-image__toggle, -.editor-post-featured-image__preview { - position: relative; - display: block; - width: 100%; - padding: 0; - background-color: $gray-100; - border-radius: 0; - height: 100%; - text-align: center; - - &:hover { - background: $gray-300; - color: $gray-900; - } - - // Override generic focus styles to be inset. - &:focus:not(:disabled), - &:not(:disabled):not([aria-disabled="true"]):focus { - box-shadow: none; - outline: none; - } - - &:focus:not(:disabled)::after { - content: ""; - display: block; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - - // Shown for high contrast modes. - outline: 2px solid transparent; - } - - transition: all 5.1s ease-out; - @include reduce-motion("transition"); -} From 39be3b1a77f4ed8fde5bd8fa7abe940b99183385 Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:16:51 +0300 Subject: [PATCH 08/17] add a `minimal` version of PostSummary editor component and remove the `excerpt panel` from inspector controls --- .../components/sidebar/post-excerpt/index.js | 39 +++----------- .../components/sidebar/post-summary/index.js | 35 +++--------- .../sidebar/settings-sidebar/index.js | 2 - .../src/components/post-excerpt/index.js | 54 +++++++++++++------ .../src/components/post-excerpt2/check.js | 10 ---- .../src/components/post-excerpt2/index.js | 35 ------------ 6 files changed, 52 insertions(+), 123 deletions(-) delete mode 100644 packages/editor/src/components/post-excerpt2/check.js delete mode 100644 packages/editor/src/components/post-excerpt2/index.js diff --git a/packages/edit-post/src/components/sidebar/post-excerpt/index.js b/packages/edit-post/src/components/sidebar/post-excerpt/index.js index 208fa733fc7289..953948de0828d9 100644 --- a/packages/edit-post/src/components/sidebar/post-excerpt/index.js +++ b/packages/edit-post/src/components/sidebar/post-excerpt/index.js @@ -1,14 +1,11 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; -import { PanelBody } from '@wordpress/components'; import { PostExcerpt as PostExcerptForm, PostExcerptCheck, } from '@wordpress/editor'; -import { compose } from '@wordpress/compose'; -import { withSelect, withDispatch } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -20,38 +17,18 @@ import { store as editPostStore } from '../../../store'; */ const PANEL_NAME = 'post-excerpt'; -function PostExcerpt( { isEnabled, isOpened, onTogglePanel } ) { +export default function PostExcerpt( { isMinimal } ) { + const isEnabled = useSelect( + ( select ) => + select( editPostStore ).isEditorPanelEnabled( PANEL_NAME ), + [] + ); if ( ! isEnabled ) { return null; } - return ( <PostExcerptCheck> - <PanelBody - title={ __( 'Excerpt' ) } - opened={ isOpened } - onToggle={ onTogglePanel } - > - <PostExcerptForm /> - </PanelBody> + <PostExcerptForm isMinimal={ isMinimal } /> </PostExcerptCheck> ); } - -export default compose( [ - withSelect( ( select ) => { - return { - isEnabled: select( editPostStore ).isEditorPanelEnabled( - PANEL_NAME - ), - isOpened: select( editPostStore ).isEditorPanelOpened( PANEL_NAME ), - }; - } ), - withDispatch( ( dispatch ) => ( { - onTogglePanel() { - return dispatch( editPostStore ).toggleEditorPanelOpened( - PANEL_NAME - ); - }, - } ) ), -] )( PostExcerpt ); diff --git a/packages/edit-post/src/components/sidebar/post-summary/index.js b/packages/edit-post/src/components/sidebar/post-summary/index.js index 6a78f8ef319574..811ba3803ed8a9 100644 --- a/packages/edit-post/src/components/sidebar/post-summary/index.js +++ b/packages/edit-post/src/components/sidebar/post-summary/index.js @@ -4,17 +4,14 @@ import { __ } from '@wordpress/i18n'; import { PanelBody, PanelRow } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { - PostExcerptCheck, - PostExcerpt2 as PostExcerpt, - PostAuthor, -} from '@wordpress/editor'; +import { PostAuthor } from '@wordpress/editor'; /** * Internal dependencies */ import PostTitle from '../post-title'; import FeaturedImage from '../featured-image'; +import PostExcerpt from '../post-excerpt'; import { store as editPostStore } from '../../../store'; /** @@ -23,24 +20,11 @@ import { store as editPostStore } from '../../../store'; const PANEL_NAME = 'post-summary'; function PostSummary() { - // TODO: check about the below logic and the preferences panels... - - const { isRemoved, isOpened } = useSelect( ( select ) => { - // We use isEditorPanelRemoved to hide the panel if it was programatically removed. We do - // not use isEditorPanelEnabled since this panel should not be disabled through the UI. - const { isEditorPanelRemoved, isEditorPanelOpened } = select( - editPostStore - ); - return { - isRemoved: isEditorPanelRemoved( PANEL_NAME ), - isOpened: isEditorPanelOpened( PANEL_NAME ), - }; - }, [] ); + const isOpened = useSelect( + ( select ) => select( editPostStore ).isEditorPanelOpened( PANEL_NAME ), + [] + ); const { toggleEditorPanelOpened } = useDispatch( editPostStore ); - - if ( isRemoved ) { - return null; - } return ( <PanelBody className="edit-post-post-summary" @@ -52,12 +36,7 @@ function PostSummary() { <PanelRow> <PostTitle /> </PanelRow> - { /* Todo: I need to check/consolidate with panels preferences */ } - <PostExcerptCheck> - <PanelRow> - <PostExcerpt /> - </PanelRow> - </PostExcerptCheck> + <PostExcerpt isMinimal /> <PanelRow> <PostAuthor labelPosition="side" /> </PanelRow> diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js index a6ab784b7a64c4..4a2c062bd38628 100644 --- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js +++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js @@ -18,7 +18,6 @@ import PostSummary from '../post-summary'; import PostStatus from '../post-status'; import LastRevision from '../last-revision'; import PostTaxonomies from '../post-taxonomies'; -import PostExcerpt from '../post-excerpt'; import PostLink from '../post-link'; import DiscussionPanel from '../discussion-panel'; import PageAttributes from '../page-attributes'; @@ -92,7 +91,6 @@ const SettingsSidebar = () => { <LastRevision /> <PostLink /> <PostTaxonomies /> - <PostExcerpt /> <DiscussionPanel /> <PageAttributes /> <MetaBoxes location="side" /> diff --git a/packages/editor/src/components/post-excerpt/index.js b/packages/editor/src/components/post-excerpt/index.js index fcba84ec03754a..c894995b7b2a2f 100644 --- a/packages/editor/src/components/post-excerpt/index.js +++ b/packages/editor/src/components/post-excerpt/index.js @@ -3,21 +3,37 @@ */ import { __ } from '@wordpress/i18n'; import { ExternalLink, TextareaControl } from '@wordpress/components'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; +import { RichText } from '@wordpress/block-editor'; /** * Internal dependencies */ import { store as editorStore } from '../../store'; -function PostExcerpt( { excerpt, onUpdateExcerpt } ) { +function PostExcerptMinimal( { excerpt, onChange } ) { return ( <div className="editor-post-excerpt"> + <RichText + className="" + aria-label={ __( 'Post excerpt text' ) } + placeholder={ __( 'Add excerpt' ) } + value={ excerpt } + onChange={ onChange } + tagName="p" + /> + </div> + ); +} + +function PostExcerptVerbose( { excerpt, onChange } ) { + return ( + <> <TextareaControl label={ __( 'Write an excerpt (optional)' ) } className="editor-post-excerpt__textarea" - onChange={ ( value ) => onUpdateExcerpt( value ) } + onChange={ onChange } value={ excerpt } /> <ExternalLink @@ -27,19 +43,23 @@ function PostExcerpt( { excerpt, onUpdateExcerpt } ) { > { __( 'Learn more about manual excerpts' ) } </ExternalLink> - </div> + </> ); } -export default compose( [ - withSelect( ( select ) => { - return { - excerpt: select( editorStore ).getEditedPostAttribute( 'excerpt' ), - }; - } ), - withDispatch( ( dispatch ) => ( { - onUpdateExcerpt( excerpt ) { - dispatch( editorStore ).editPost( { excerpt } ); - }, - } ) ), -] )( PostExcerpt ); +export default function PostExcerpt( { isMinimal } ) { + const { editPost } = useDispatch( editorStore ); + const excerpt = useSelect( + ( select ) => select( editorStore ).getEditedPostAttribute( 'excerpt' ), + [] + ); + const onChange = useCallback( () => { + return ( newExcerpt ) => editPost( { excerpt: newExcerpt } ); + }, [] ); + const Component = isMinimal ? PostExcerptMinimal : PostExcerptVerbose; + return ( + <div className="editor-post-excerpt"> + <Component excerpt={ excerpt } onChange={ onChange } /> + </div> + ); +} diff --git a/packages/editor/src/components/post-excerpt2/check.js b/packages/editor/src/components/post-excerpt2/check.js deleted file mode 100644 index a94a5badec180c..00000000000000 --- a/packages/editor/src/components/post-excerpt2/check.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Internal dependencies - */ -import PostTypeSupportCheck from '../post-type-support-check'; - -function PostExcerptCheck( props ) { - return <PostTypeSupportCheck { ...props } supportKeys="excerpt" />; -} - -export default PostExcerptCheck; diff --git a/packages/editor/src/components/post-excerpt2/index.js b/packages/editor/src/components/post-excerpt2/index.js deleted file mode 100644 index f4ef71d96fd873..00000000000000 --- a/packages/editor/src/components/post-excerpt2/index.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { RichText } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import { store as editorStore } from '../../store'; - -function PostExcerpt2() { - const { editPost } = useDispatch( editorStore ); - const excerpt = useSelect( - ( select ) => select( editorStore ).getEditedPostAttribute( 'excerpt' ), - [] - ); - return ( - <div className="editor-post-excerpt"> - <RichText - className="" - aria-label={ __( 'Post excerpt text' ) } - placeholder={ __( 'Add excerpt' ) } - value={ excerpt } - onChange={ ( newExcerpt ) => - editPost( { excerpt: newExcerpt } ) - } - tagName="p" - /> - </div> - ); -} - -export default PostExcerpt2; From 78958e99e69eb72020c201c7b8124f63d665de74 Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:19:50 +0300 Subject: [PATCH 09/17] remove obsolete export --- packages/editor/src/components/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/editor/src/components/index.js b/packages/editor/src/components/index.js index cb023863439f7b..b89ef342a58628 100644 --- a/packages/editor/src/components/index.js +++ b/packages/editor/src/components/index.js @@ -23,8 +23,6 @@ export { default as PostAuthor } from './post-author'; export { default as PostAuthorCheck } from './post-author/check'; export { default as PostComments } from './post-comments'; export { default as PostExcerpt } from './post-excerpt'; -// TODO: of course rename :) and check possible deprecations.. -export { default as PostExcerpt2 } from './post-excerpt2'; export { default as PostExcerptCheck } from './post-excerpt/check'; export { default as PostFeaturedImage } from './post-featured-image'; export { default as PostFeaturedImageCheck } from './post-featured-image/check'; From 8216852d2295b7ffcf9ee8c6c29e9ebd662c020d Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:27:21 +0300 Subject: [PATCH 10/17] fix postExcerpt callback --- packages/editor/src/components/post-excerpt/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/components/post-excerpt/index.js b/packages/editor/src/components/post-excerpt/index.js index c894995b7b2a2f..1553656bc5eecd 100644 --- a/packages/editor/src/components/post-excerpt/index.js +++ b/packages/editor/src/components/post-excerpt/index.js @@ -4,7 +4,6 @@ import { __ } from '@wordpress/i18n'; import { ExternalLink, TextareaControl } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { useCallback } from '@wordpress/element'; import { RichText } from '@wordpress/block-editor'; /** @@ -53,13 +52,15 @@ export default function PostExcerpt( { isMinimal } ) { ( select ) => select( editorStore ).getEditedPostAttribute( 'excerpt' ), [] ); - const onChange = useCallback( () => { - return ( newExcerpt ) => editPost( { excerpt: newExcerpt } ); - }, [] ); const Component = isMinimal ? PostExcerptMinimal : PostExcerptVerbose; return ( <div className="editor-post-excerpt"> - <Component excerpt={ excerpt } onChange={ onChange } /> + <Component + excerpt={ excerpt } + onChange={ ( newExcerpt ) => + editPost( { excerpt: newExcerpt } ) + } + /> </div> ); } From 86c407576c17720d903ce939eec6e42936a3927c Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:38:16 +0300 Subject: [PATCH 11/17] remove obsolete styles import --- packages/editor/src/style.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss index 3f279c70110927..88ed59125a939b 100644 --- a/packages/editor/src/style.scss +++ b/packages/editor/src/style.scss @@ -6,7 +6,6 @@ @import "./components/page-attributes/style.scss"; @import "./components/post-excerpt/style.scss"; @import "./components/post-featured-image/style.scss"; -@import "./components/post-featured-image2/style.scss"; @import "./components/post-format/style.scss"; @import "./components/post-last-revision/style.scss"; @import "./components/post-locked-modal/style.scss"; From 8c01268afecb48bf8df9d2c21bc01040a1d2711d Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:42:22 +0300 Subject: [PATCH 12/17] remove PostAuthor from status panel --- packages/edit-post/src/components/sidebar/post-status/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-status/index.js b/packages/edit-post/src/components/sidebar/post-status/index.js index 2d96f3a33af911..aced8fdcdceecf 100644 --- a/packages/edit-post/src/components/sidebar/post-status/index.js +++ b/packages/edit-post/src/components/sidebar/post-status/index.js @@ -13,7 +13,6 @@ import PostVisibility from '../post-visibility'; import PostTrash from '../post-trash'; import PostSchedule from '../post-schedule'; import PostSticky from '../post-sticky'; -import PostAuthor from '../post-author'; import PostSlug from '../post-slug'; import PostFormat from '../post-format'; import PostPendingStatus from '../post-pending-status'; @@ -42,7 +41,6 @@ function PostStatus( { isOpened, onTogglePanel } ) { <PostSticky /> <PostPendingStatus /> <PostSlug /> - <PostAuthor /> { fills } <PostTrash /> </> From a59e08656c09784e91224c558046b563825bba3a Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Mon, 4 Apr 2022 17:51:55 +0300 Subject: [PATCH 13/17] make post title a `span` --- packages/edit-post/src/components/sidebar/post-title/index.js | 3 ++- .../edit-post/src/components/sidebar/post-title/style.scss | 3 +++ packages/edit-post/src/style.scss | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/edit-post/src/components/sidebar/post-title/style.scss diff --git a/packages/edit-post/src/components/sidebar/post-title/index.js b/packages/edit-post/src/components/sidebar/post-title/index.js index aa701b932c3cd2..395fa6ece53394 100644 --- a/packages/edit-post/src/components/sidebar/post-title/index.js +++ b/packages/edit-post/src/components/sidebar/post-title/index.js @@ -14,7 +14,8 @@ function PostTitle() { ); return ( <PlainText - tagName="h1" + className="edit-post-post-title" + tagName="span" placeholder={ __( 'Add title' ) } value={ postTitle } onChange={ ( title ) => editPost( { title } ) } diff --git a/packages/edit-post/src/components/sidebar/post-title/style.scss b/packages/edit-post/src/components/sidebar/post-title/style.scss new file mode 100644 index 00000000000000..a1ffb480b920b8 --- /dev/null +++ b/packages/edit-post/src/components/sidebar/post-title/style.scss @@ -0,0 +1,3 @@ +.edit-post-post-title { + font-size: 2em; +} diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index a8360e0d8be2b7..1b93f991a9ba96 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -15,6 +15,7 @@ @import "./components/sidebar/post-schedule/style.scss"; @import "./components/sidebar/post-slug/style.scss"; @import "./components/sidebar/post-status/style.scss"; +@import "./components/sidebar/post-title/style.scss"; @import "./components/sidebar/post-visibility/style.scss"; @import "./components/sidebar/settings-header/style.scss"; @import "./components/sidebar/template/style.scss"; From ce320e7aa94f36ff7db6f1309c52233ad996ba9b Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Mon, 4 Apr 2022 17:49:13 +0200 Subject: [PATCH 14/17] Polish heading. --- .../components/sidebar/post-title/style.scss | 5 ++++- .../editor/src/components/post-excerpt/index.js | 17 +++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-title/style.scss b/packages/edit-post/src/components/sidebar/post-title/style.scss index a1ffb480b920b8..4b7f5d222579b1 100644 --- a/packages/edit-post/src/components/sidebar/post-title/style.scss +++ b/packages/edit-post/src/components/sidebar/post-title/style.scss @@ -1,3 +1,6 @@ .edit-post-post-title { - font-size: 2em; + font-size: 16px; + line-height: 1.6; + font-weight: 500; + margin: $grid-unit-20 0; } diff --git a/packages/editor/src/components/post-excerpt/index.js b/packages/editor/src/components/post-excerpt/index.js index 1553656bc5eecd..2c1a7d069a5261 100644 --- a/packages/editor/src/components/post-excerpt/index.js +++ b/packages/editor/src/components/post-excerpt/index.js @@ -13,16 +13,13 @@ import { store as editorStore } from '../../store'; function PostExcerptMinimal( { excerpt, onChange } ) { return ( - <div className="editor-post-excerpt"> - <RichText - className="" - aria-label={ __( 'Post excerpt text' ) } - placeholder={ __( 'Add excerpt' ) } - value={ excerpt } - onChange={ onChange } - tagName="p" - /> - </div> + <RichText + aria-label={ __( 'Post excerpt text' ) } + placeholder={ __( 'Add excerpt' ) } + value={ excerpt } + onChange={ onChange } + tagName="p" + /> ); } From 4e35b7825352196325fa94f009e0cfdc2557f95b Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Tue, 5 Apr 2022 10:06:27 +0300 Subject: [PATCH 15/17] fix tests and add a new one --- .../specs/editor/plugins/meta-boxes.test.js | 15 ++-- .../various/new-post-default-content.test.js | 10 +-- .../specs/editor/various/sidebar.test.js | 68 +++++++++++++------ 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/packages/e2e-tests/specs/editor/plugins/meta-boxes.test.js b/packages/e2e-tests/specs/editor/plugins/meta-boxes.test.js index 8b5d5564fd818f..69dbf44422e7ac 100644 --- a/packages/e2e-tests/specs/editor/plugins/meta-boxes.test.js +++ b/packages/e2e-tests/specs/editor/plugins/meta-boxes.test.js @@ -103,19 +103,16 @@ describe( 'Meta boxes', () => { // Open the excerpt panel. await openDocumentSettingsSidebar(); - const excerptButton = await findSidebarPanelToggleButtonWithTitle( - 'Excerpt' + const summaryButton = await findSidebarPanelToggleButtonWithTitle( + 'Summary' ); - if ( excerptButton ) { - await excerptButton.click( 'button' ); + if ( summaryButton ) { + await summaryButton.click( 'button' ); } - await page.waitForSelector( '.editor-post-excerpt textarea' ); + await page.waitForSelector( '.editor-post-excerpt p' ); - await page.type( - '.editor-post-excerpt textarea', - 'Explicitly set excerpt.' - ); + await page.type( '.editor-post-excerpt p', 'Explicitly set excerpt.' ); await publishPost(); diff --git a/packages/e2e-tests/specs/editor/various/new-post-default-content.test.js b/packages/e2e-tests/specs/editor/various/new-post-default-content.test.js index e61927e10ff17f..11b5ceb04d09be 100644 --- a/packages/e2e-tests/specs/editor/various/new-post-default-content.test.js +++ b/packages/e2e-tests/specs/editor/various/new-post-default-content.test.js @@ -33,14 +33,14 @@ describe( 'new editor filtered state', () => { // open the sidebar, we want to see the excerpt. await openDocumentSettingsSidebar(); - const excerptButton = await findSidebarPanelToggleButtonWithTitle( - 'Excerpt' + const summaryButton = await findSidebarPanelToggleButtonWithTitle( + 'Summary' ); - if ( excerptButton ) { - await excerptButton.click( 'button' ); + if ( summaryButton ) { + await summaryButton.click( 'button' ); } const excerpt = await page.$eval( - '.editor-post-excerpt textarea', + '.editor-post-excerpt p', ( element ) => element.innerHTML ); diff --git a/packages/e2e-tests/specs/editor/various/sidebar.test.js b/packages/e2e-tests/specs/editor/various/sidebar.test.js index 2be81eac943e76..052348e0bec25c 100644 --- a/packages/e2e-tests/specs/editor/various/sidebar.test.js +++ b/packages/e2e-tests/specs/editor/various/sidebar.test.js @@ -16,6 +16,19 @@ const SIDEBAR_SELECTOR = '.edit-post-sidebar'; const ACTIVE_SIDEBAR_TAB_SELECTOR = '.edit-post-sidebar__panel-tab.is-active'; const ACTIVE_SIDEBAR_BUTTON_TEXT = 'Post'; +const openSidebarPanelWithTitle = async ( title ) => { + const panel = await page.waitForXPath( + `//div[contains(@class,"edit-post-sidebar")]//button[@class="components-button components-panel__body-toggle"][contains(text(),"${ title }")]` + ); + const expanded = await page.evaluate( + ( element ) => element.getAttribute( 'aria-expanded' ), + panel + ); + if ( expanded === 'false' ) { + return panel.click(); + } +}; + describe( 'Sidebar', () => { afterEach( () => { disableFocusLossObservation(); @@ -123,25 +136,23 @@ describe( 'Sidebar', () => { await createNewPost(); await enableFocusLossObservation(); await openDocumentSettingsSidebar(); - - expect( await findSidebarPanelWithTitle( 'Categories' ) ).toBeDefined(); - expect( await findSidebarPanelWithTitle( 'Tags' ) ).toBeDefined(); - expect( - await findSidebarPanelWithTitle( 'Featured image' ) - ).toBeDefined(); - expect( await findSidebarPanelWithTitle( 'Excerpt' ) ).toBeDefined(); - expect( await findSidebarPanelWithTitle( 'Discussion' ) ).toBeDefined(); - expect( - await findSidebarPanelWithTitle( 'Status & visibility' ) - ).toBeDefined(); + const panelNames = [ + 'Summary', + 'Categories', + 'Tags', + 'Discussion', + 'Status & visibility', + ]; + const panels = await Promise.all( + panelNames.map( findSidebarPanelWithTitle ) + ); + panels.forEach( ( panel ) => expect( panel ).toBeDefined() ); await page.evaluate( () => { const { removeEditorPanel } = wp.data.dispatch( 'core/edit-post' ); removeEditorPanel( 'taxonomy-panel-category' ); removeEditorPanel( 'taxonomy-panel-post_tag' ); - removeEditorPanel( 'featured-image' ); - removeEditorPanel( 'post-excerpt' ); removeEditorPanel( 'discussion-panel' ); removeEditorPanel( 'post-status' ); } ); @@ -156,12 +167,6 @@ describe( 'Sidebar', () => { expect( await page.$x( getPanelToggleSelector( 'Tags' ) ) ).toEqual( [] ); - expect( - await page.$x( getPanelToggleSelector( 'Featured image' ) ) - ).toEqual( [] ); - expect( await page.$x( getPanelToggleSelector( 'Excerpt' ) ) ).toEqual( - [] - ); expect( await page.$x( getPanelToggleSelector( 'Discussion' ) ) ).toEqual( [] ); @@ -169,4 +174,29 @@ describe( 'Sidebar', () => { await page.$x( getPanelToggleSelector( 'Status & visibility' ) ) ).toEqual( [] ); } ); + describe( 'Summary panel', () => { + beforeEach( async () => { + await createNewPost(); + await enableFocusLossObservation(); + await openDocumentSettingsSidebar(); + } ); + it( 'should show all elements', async () => { + await openSidebarPanelWithTitle( 'Summary' ); + const getSelector = ( cssClass ) => + `//div[contains(@class, "edit-post-sidebar")]//div[contains(@class, "edit-post-post-summary")]//*[contains(@class, "${ cssClass }")]`; + const panelElements = await Promise.all( + [ + 'editor-post-featured-image', + 'edit-post-post-title', + 'editor-post-excerpt', + 'post-author-selector', + ].map( ( target ) => + page.waitForXPath( getSelector( target ) ) + ) + ); + panelElements.forEach( ( element ) => + expect( element ).toBeDefined() + ); + } ); + } ); } ); From 7fe7b93bad60b15d85500697e4eede04b15ffcc9 Mon Sep 17 00:00:00 2001 From: jasmussen <joen@automattic.com> Date: Tue, 5 Apr 2022 09:51:16 +0200 Subject: [PATCH 16/17] Spacing and focus styles. --- .../src/components/sidebar/post-title/style.scss | 13 ++++++++++++- .../editor/src/components/post-excerpt/style.scss | 12 ++++++++++++ .../src/components/post-featured-image/style.scss | 12 ++++-------- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-title/style.scss b/packages/edit-post/src/components/sidebar/post-title/style.scss index 4b7f5d222579b1..831896d629e8cf 100644 --- a/packages/edit-post/src/components/sidebar/post-title/style.scss +++ b/packages/edit-post/src/components/sidebar/post-title/style.scss @@ -2,5 +2,16 @@ font-size: 16px; line-height: 1.6; font-weight: 500; - margin: $grid-unit-20 0; + margin: $grid-unit-15 0; + + // Focus style + width: 100%; + border-radius: $radius-block-ui - $border-width; + + &:focus-within { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } } diff --git a/packages/editor/src/components/post-excerpt/style.scss b/packages/editor/src/components/post-excerpt/style.scss index 056d81ad36c731..ebd21d8d797cbb 100644 --- a/packages/editor/src/components/post-excerpt/style.scss +++ b/packages/editor/src/components/post-excerpt/style.scss @@ -2,3 +2,15 @@ width: 100%; margin-bottom: 10px; } + +.editor-post-excerpt { + // Focus style + border-radius: $radius-block-ui - $border-width; + + &:focus-within { + box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Windows High Contrast mode will show this outline, but not the box-shadow. + outline: 2px solid transparent; + } +} diff --git a/packages/editor/src/components/post-featured-image/style.scss b/packages/editor/src/components/post-featured-image/style.scss index 01ae28f0e97b58..c7797520260019 100644 --- a/packages/editor/src/components/post-featured-image/style.scss +++ b/packages/editor/src/components/post-featured-image/style.scss @@ -3,6 +3,10 @@ margin-left: -$grid-unit-20; margin-right: -$grid-unit-20; + .components-panel__body-title + & { + margin-top: -5px; + } + // Ensure a consistent dropzone and avoid jumps when loading. height: 140px; overflow: hidden; @@ -21,8 +25,6 @@ top: 50%; left: 50%; transform: translate(-50%, -50%); - - // @todo: these rules can be removed if we retire post-featured-image. margin-top: 0; margin-left: 0; } @@ -56,12 +58,6 @@ opacity: 0; transition: all 0.1s ease-out; @include reduce-motion("transition"); - - // @todo: these rules can be removed if we retire post-featured-image. - .components-button + .components-button { - display: block; - margin-top: 0; - } } &:focus-within .editor-post-featured-image__actions, From 3c76b9792275ccb83bed667f11f6d72897c74dd2 Mon Sep 17 00:00:00 2001 From: ntsekouras <ntsekouras@outlook.com> Date: Wed, 6 Apr 2022 10:53:46 +0300 Subject: [PATCH 17/17] add post-type support checks for title and author --- .../components/sidebar/post-summary/index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/edit-post/src/components/sidebar/post-summary/index.js b/packages/edit-post/src/components/sidebar/post-summary/index.js index 811ba3803ed8a9..fd8e2435bc8415 100644 --- a/packages/edit-post/src/components/sidebar/post-summary/index.js +++ b/packages/edit-post/src/components/sidebar/post-summary/index.js @@ -4,7 +4,7 @@ import { __ } from '@wordpress/i18n'; import { PanelBody, PanelRow } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; -import { PostAuthor } from '@wordpress/editor'; +import { PostAuthor, PostTypeSupportCheck } from '@wordpress/editor'; /** * Internal dependencies @@ -33,13 +33,17 @@ function PostSummary() { onToggle={ () => toggleEditorPanelOpened( PANEL_NAME ) } > <FeaturedImage /> - <PanelRow> - <PostTitle /> - </PanelRow> + <PostTypeSupportCheck supportKeys="title"> + <PanelRow> + <PostTitle /> + </PanelRow> + </PostTypeSupportCheck> <PostExcerpt isMinimal /> - <PanelRow> - <PostAuthor labelPosition="side" /> - </PanelRow> + <PostTypeSupportCheck supportKeys="author"> + <PanelRow> + <PostAuthor labelPosition="side" /> + </PanelRow> + </PostTypeSupportCheck> </PanelBody> ); }