diff --git a/packages/block-editor/src/components/media-placeholder/index.js b/packages/block-editor/src/components/media-placeholder/index.js index d156138b96676..58bc1a8635248 100644 --- a/packages/block-editor/src/components/media-placeholder/index.js +++ b/packages/block-editor/src/components/media-placeholder/index.js @@ -76,6 +76,8 @@ export function MediaPlaceholder( { onFilesPreUpload = noop, onHTMLDrop = noop, children, + mediaLibraryButton, + placeholder, } ) { const mediaUpload = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); @@ -178,7 +180,7 @@ export function MediaPlaceholder( { onFilesUpload( event.target.files ); }; - const renderPlaceholder = ( content ) => { + const defaultRenderPlaceholder = ( content ) => { let { instructions, title } = labels; if ( ! mediaUpload && ! onSelectURL ) { @@ -252,6 +254,7 @@ export function MediaPlaceholder( { ); }; + const renderPlaceholder = placeholder ?? defaultRenderPlaceholder; const renderDropZone = () => { if ( disableDropZone ) { @@ -304,7 +307,20 @@ export function MediaPlaceholder( { }; const renderMediaUploadChecked = () => { - const mediaLibraryButton = ( + const defaultButton = ( { open } ) => { + return ( + + ); + }; + const libraryButton = mediaLibraryButton ?? defaultButton; + const uploadMediaLibraryButton = ( id ) : value.id } - render={ ( { open } ) => { - return ( - - ); - } } + render={ libraryButton } /> ); @@ -352,7 +357,7 @@ export function MediaPlaceholder( { > { __( 'Upload' ) } - { mediaLibraryButton } + { uploadMediaLibraryButton } { renderUrlSelectionUI() } { renderCancelLink() } @@ -380,7 +385,7 @@ export function MediaPlaceholder( { > { __( 'Upload' ) } - { mediaLibraryButton } + { uploadMediaLibraryButton } { renderUrlSelectionUI() } { renderCancelLink() } @@ -388,7 +393,7 @@ export function MediaPlaceholder( { return renderPlaceholder( content ); } - return renderPlaceholder( mediaLibraryButton ); + return renderPlaceholder( uploadMediaLibraryButton ); }; if ( dropZoneUIOnly || disableMediaButtons ) { diff --git a/packages/block-library/src/site-logo/edit.js b/packages/block-library/src/site-logo/edit.js index a2d3515aefbe4..6719a4244ab8b 100644 --- a/packages/block-library/src/site-logo/edit.js +++ b/packages/block-library/src/site-logo/edit.js @@ -12,7 +12,6 @@ import { useEffect, useState, useRef } from '@wordpress/element'; import { __, isRTL } from '@wordpress/i18n'; import { MenuItem, - Notice, PanelBody, RangeControl, ResizableBox, @@ -20,11 +19,11 @@ import { ToggleControl, ToolbarButton, Placeholder, + Button, } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { BlockControls, - BlockIcon, InspectorControls, MediaPlaceholder, MediaReplaceFlow, @@ -35,7 +34,9 @@ import { } from '@wordpress/block-editor'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; -import { crop, siteLogo as icon } from '@wordpress/icons'; +import { crop, upload } from '@wordpress/icons'; +import { SVG, Path } from '@wordpress/primitives'; +import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -309,7 +310,6 @@ export default function LogoEdit( { } ) { const { width } = attributes; const [ logoUrl, setLogoUrl ] = useState(); - const [ error, setError ] = useState(); const ref = useRef(); const { @@ -373,7 +373,6 @@ export default function LogoEdit( { if ( ! media.id && media.url ) { // This is a temporary blob image setLogo( undefined ); - setError( null ); setLogoUrl( media.url ); return; } @@ -386,8 +385,9 @@ export default function LogoEdit( { setLogoUrl( undefined ); }; + const { createErrorNotice } = useDispatch( noticesStore ); const onUploadError = ( message ) => { - setError( message[ 2 ] ? message[ 2 ] : null ); + createErrorNotice( message[ 2 ], { type: 'snackbar' } ); }; const controls = canUserEdit && logoUrl && ( @@ -404,7 +404,6 @@ export default function LogoEdit( { ); - const label = __( 'Site Logo' ); let logoImage; const isLoading = siteLogoId === undefined || isRequestingMediaItem; if ( isLoading ) { @@ -426,23 +425,52 @@ export default function LogoEdit( { /> ); } + const placeholder = ( content ) => { + const placeholderClassName = classnames( + 'block-editor-media-placeholder', + className + ); + + return ( + + { + + + + } + { content } + + ); + }; + const classes = classnames( className, { 'is-default-size': ! width, } ); + const blockProps = useBlockProps( { ref, className: classes, } ); + + const label = __( 'Add a site logo' ); + return (
{ controls } { !! logoUrl && logoImage } { ! logoUrl && ! canUserEdit && ( - + { isLoading && ( @@ -452,25 +480,25 @@ export default function LogoEdit( { ) } { ! logoUrl && canUserEdit && ( } - labels={ { - title: label, - instructions: __( - 'Upload an image, or pick one from your media library, to be your site logo' - ), - } } onSelect={ onSelectLogo } accept={ ACCEPT_MEDIA_STRING } allowedTypes={ ALLOWED_MEDIA_TYPES } - mediaPreview={ logoImage } - notices={ - error && ( - - { error } - - ) - } onError={ onUploadError } + placeholder={ placeholder } + mediaLibraryButton={ ( { open } ) => { + return ( +
diff --git a/packages/block-library/src/site-logo/editor.scss b/packages/block-library/src/site-logo/editor.scss index 6c420268aa36b..cfde7320f9172 100644 --- a/packages/block-library/src/site-logo/editor.scss +++ b/packages/block-library/src/site-logo/editor.scss @@ -24,7 +24,6 @@ } } - .custom-logo-link { cursor: inherit; @@ -42,24 +41,36 @@ height: auto; max-width: 100%; } +} - // Placeholder improvements. - .components-placeholder { - justify-content: flex-start; - min-height: auto; +// Provide special styling for the placeholder. +.wp-block-site-logo.wp-block-site-logo { + // Inherit border radius from style variations. + .components-placeholder, + .components-resizable-box__container { + border-radius: inherit; + } + + // Match the default logo size. + &.is-default-size .components-placeholder { height: 120px; - padding: $grid-unit-15; + width: 120px; + } - // Massage the label. - .components-placeholder__label { - margin-top: $grid-unit-15; - white-space: nowrap; - } + .components-placeholder { + justify-content: center; + align-items: center; + box-shadow: none; + padding: 0; - .components-placeholder__label .block-editor-block-icon, - .components-placeholder__label > svg { - margin-right: $grid-unit-05; - } + // Provide a minimum size for the placeholder, for when the logo is resized. + // @todo: resizing is currently only possible by adding an image, resizing, + // and then removing the image again. We might want to enable resizing on the + // placeholder itself. + min-height: $grid-unit-60; + min-width: $grid-unit-60; + height: 100%; + width: 100%; // Hide the upload button, as it's also available in the media library. .components-form-file-upload { @@ -79,9 +90,80 @@ justify-content: center; } - // Hide drag and drop text. + // Hide items. .components-drop-zone__content-text { display: none; } + + // Draw the dashed outline. + // By setting the dashed border to currentColor, we ensure it's visible + // against any background color. + color: currentColor; + &::before { + content: ""; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + border: $border-width dashed currentColor; + opacity: 0.3; + pointer-events: none; + + // Inherit border radius from style variations. + border-radius: inherit; + } + + // Style the upload button. + .components-placeholder__fieldset { + width: auto; + } + + .components-button.components-button { + color: inherit; + padding: 0; + display: flex; + justify-content: center; + align-items: center; + width: $grid-unit-60; + height: $grid-unit-60; + border-radius: 50%; + position: relative; + visibility: hidden; + + // Animation. + background: transparent; + transition: all 0.1s linear; + @include reduce-motion("transition"); + } + + .components-button.components-button > svg { + color: $white; + } + + // Style the placeholder illustration. + .components-placeholder__illustration { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + stroke: currentColor; + stroke-dasharray: 3; + opacity: 0.3; + } + } + + // Show upload button on block selection. + &.is-selected .components-button.components-button { + background: var(--wp-admin-theme-color); + border-color: var(--wp-admin-theme-color); + border-style: solid; + color: $white; + opacity: 1; + visibility: visible; } } diff --git a/packages/block-library/src/site-logo/style.scss b/packages/block-library/src/site-logo/style.scss index dd8a883238f56..00dc6b44efe9a 100644 --- a/packages/block-library/src/site-logo/style.scss +++ b/packages/block-library/src/site-logo/style.scss @@ -11,12 +11,18 @@ height: auto; } + // Inherit border radius from style variations. + a, + img { + border-radius: inherit; + } + .aligncenter { display: table; } // Style variations - &.is-style-rounded img { + &.is-style-rounded { // We use an absolute pixel to prevent the oval shape that a value of 50% would give // to rectangular images. A pill-shape is better than otherwise. border-radius: 9999px; diff --git a/packages/components/src/drop-zone/style.scss b/packages/components/src/drop-zone/style.scss index 012edd3ce8bed..a289d963a86fc 100644 --- a/packages/components/src/drop-zone/style.scss +++ b/packages/components/src/drop-zone/style.scss @@ -51,6 +51,7 @@ margin: 0 auto; line-height: 0; fill: currentColor; + pointer-events: none; }